././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7022057 hvcc-0.13.3/LICENSE0000644000000000000000000007640514435670357010506 0ustar00GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. “This License” refers to version 3 of the GNU General Public License. “Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. “The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations. To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work. A “covered work” means either the unmodified Program or a work based on the Program. To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work. A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”. c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. “Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. “Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”. A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739952989.4286463 hvcc-0.13.3/README.md0000644000000000000000000001613014755311535010740 0ustar00# Heavy Compiler Collection (hvcc) [![Build Status](https://github.com/Wasted-Audio/hvcc/actions/workflows/ci.yml/badge.svg)](https://github.com/Wasted-Audio/hvcc/actions) [![pypi](https://img.shields.io/pypi/v/hvcc.svg)](https://pypi.python.org/pypi/hvcc) [![python](https://img.shields.io/pypi/pyversions/hvcc.svg)](https://pypi.python.org/pypi/hvcc) `hvcc` is a python-based dataflow audio programming language compiler that generates C/C++ code and a variety of specific framework wrappers. ## Background Originaly created by Enzien Audio, the need for `hvcc` arose from running against performance limitations while creating interactive music and sound products for the iPhone. [Pure Data](https://puredata.info) (libpd) was the only real choice for a design tool as it was embeddable and provided a high enough abstraction level that musicians or sound designers could be creative. The goal was to leverage Pure Data as a design interface and statically interpret the resultant patches to generate a low-level, portable and optimised C/C++ program that would be structured to take advantage of modern hardware whilst still generating the same behaviour and audio output as Pure Data. It has since then been expanded to provide further support for many different platforms and frameworks, targeting game audio design, daw plugins and embedded production tools. In 2021 Wasted Audio took over maintenance of the project. ## Documentation * [Introduction](/docs/01.introduction.md) * [What is heavy?](/docs/01.introduction.md#what-is-heavy) * [Supported patch formats](/docs/01.introduction.md#supported-patch-formats) * [Supported platforms](/docs/01.introduction.md#supported-platforms) * [Supported frameworks](/docs/01.introduction.md#supported-frameworks) * [Licensing](/docs/01.introduction.md#licensing) * [Getting Started](/docs/02.getting_started.md) * [Generators](/docs/03.generators.md) * [MIDI](/docs/04.midi.md) * [C API](/docs/05.c.md) * [C++ API](/docs/06.cpp.md) * [Heavy Lang Info](/docs/07.heavy_lang.md) * [Heavy IR Info](/docs/08.heavy_ir_lang.md) * [Supported vanilla objects](/docs/09.supported_vanilla_objects.md) * [Unsupported vanilla objects](/docs/10.unsupported_vanilla_objects.md) ## Integrations hvcc has been integrated into several projects and services. This allows to easily compile patches without having to install hvcc manually. * [plugdata](https://plugdata.org/) - Modern interface for Pure Data. Includes a full cross-platform toolchain and targets Daisy, DPF and PD Externals. * [mod-cloud-builder](https://github.com/moddevices/mod-cloud-builder) - Online service for building LV2 plugins for the MOD platform. * [OWL Patch Library](https://www.rebeltech.org/patch-library) - Online service for building OWL plugins (uses an old fork). ## Requirements Python 3.8 up to 3.12 * `jinja2` (for generator templating) * `importlib_resources` (for reading static resources) * `json2daisy` (for daisy integration) For tests: * `tox` (python install) * `numpy/scipy` (requirements-dev) * `midifile` (git submodule) * `tinywav` (git submodule) * `clang/clang++` (system install) ## Installation hvcc is available from pypi.org and can be installed using python3 pip: `$ pip3 install hvcc` If you want to develop hvcc you can install it from the source directory: `$ git clone https://github.com/Wasted-Audio/hvcc.git` `$ cd hvcc/` `$ pip3 install -e .` ## Usage `hvcc` requires at least one argument that determines the top-level patch file to be loaded. Generate a C/C++ program from `input.pd` and place the files in `~/myProject/` `$ hvcc ~/myProject/_main.pd` This command will generate the following directories: * `~/myProject/hv` heavylang representation of the input pd patch(es) * `~/myProject/ir` heavyir representation of the heavylang patch * `~/myProject/c` final generated C/C++ source files (this is what you would use in your project) ### `-o` Select output directory As seen in the above command, typical output of `hvcc` is split into several directories that contain the intermediate files used by the compiler itself, the final generated source files, and any additional framework specific files and projects. The `-o` or `--out_dir` parameter will specify where the output files are placed after a successful compile. For example: `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/` Will place all the generated files in `~/Desktop/somewhere/else/`. ### `-n` Specify Patch Name The `-n` or `--name` parameter can be used to easily namespace the generated code so that there are no conflicts when integrating multiple patches into the same project. `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/ -n mySynth` ### `-g` Generators Once `hvcc` has generated internal information about the patch the `-g` or `--gen` parameter can be used to specify the output files it should generate. By default it will always include `c` for the C/C++ source files and additional generators can specified for certain framework targets. For example: `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/ -n mySynth -g unity` Will also generate a `unity` section in the output directory contain all the build projects and source files to compile a Unity plugin. It is also possible to pass a list of generators: `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/ -n mySynth -g unity wwise js` A list of available generator options can be found [here](/docs/03.generators.md) ### `-p` Search Paths `hvcc` will iterate through various directories when resolving patch objects and abstractions. The `-p` or `--search_paths` argument can be used to add additional folders for `hvcc` to look in. Note that this argument is not needed for abstractions in the same folder as the top-level patch. This can be handy when using a third-party patch library like [heavylib](https://github.com/Wasted-Audio/heavylib) for example. Simply append any folder paths after the `-p` flag like so: `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/ -n mySynth -p ~/Workspace/Projects/Enzien/heavylib/ ~/Desktop/myLib/` ### `-m` Meta Data `hvcc` can take extra meta-data via a supplied json file. It depends on the generator which fields are supported. ### `--copyright` User Copyright By default all the generated source files via `hvcc` will have the following copyright text applied to the top of the file: `Copyright (c) 2018 Enzien Audio, Ltd.` This can be changed with `--copyright` parameter `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/ -n mySynth --copyright "Copyright (c) Los Pollos Hermanos 2019"` ### `--help` Displays all the available parameters and options for hvcc. ## Contact There are several places where heavy/hvcc conversation is happening: * [Discord](https://discord.gg/fmxJveg) * [IRC](https://web.libera.chat/#hvcc) * A number of forums: * [Bela](https://forum.bela.io/?q=hvcc) * [Rebel Technology](https://community.rebeltech.org/tags/puredata) * [Daisy](https://forum.electro-smith.com/c/integrations/pure-data/32) * [MOD](https://forum.moddevices.com/c/developers/pure-data/56) Or you can use the [discussions](https://github.com/Wasted-Audio/hvcc/discussions) tab of this repository ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1739952822.569362 hvcc-0.13.3/hvcc/__init__.py0000644000000000000000000000012614755311267012515 0ustar00from hvcc.compiler import compile_dataflow # noqa from hvcc.main import main # noqa ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1739952822.569362 hvcc-0.13.3/hvcc/compiler.py0000644000000000000000000003113514755311267012574 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2021-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import importlib import inspect import json import os import re import sys from typing import Any, List, Dict, Optional from hvcc.interpreters.pd2hv import pd2hv from hvcc.core.hv2ir import hv2ir from hvcc.generators.ir2c import ir2c from hvcc.generators.ir2c import ir2c_perf from hvcc.generators.c2js import c2js from hvcc.generators.c2daisy import c2daisy from hvcc.generators.c2dpf import c2dpf from hvcc.generators.c2owl import c2owl from hvcc.generators.c2pdext import c2pdext from hvcc.generators.c2wwise import c2wwise from hvcc.generators.c2unity import c2unity from hvcc.types.compiler import ( CompilerResults, CompilerResp, CompilerNotif, CompilerMsg, Generator, ExternInfo, ExternMemoryPool, ExternMidi, ExternEvents, ExternParams ) from hvcc.types.IR import IRGraph from hvcc.types.meta import Meta def add_error( results: CompilerResults, error: str ) -> CompilerResults: if "hvcc" in results.root: results.root["hvcc"].notifs.errors.append(CompilerMsg(message=error)) else: results.root["hvcc"] = CompilerResp( stage="hvcc", notifs=CompilerNotif( has_error=True, errors=[CompilerMsg(message=error)] ) ) return results def check_extern_name_conflicts(extern_type: str, extern_list: List, results: CompilerResults) -> None: """ In most of the generator code extern names become capitalised when used as enums. This method makes sure that there are no cases where two unique keys become the same after being capitalised. Note(joe): hvcc is probably the best place to check as at this point we have a list of all extern names. """ for i, v in enumerate(extern_list): for j, u in enumerate(extern_list[i + 1:]): if v[0].upper() == u[0].upper(): add_error(results, f"Conflicting {extern_type} names '{v[0]}' and '{u[0]}', make sure that " "capital letters are not the only difference.") def count_midi_objects(hvir: IRGraph) -> Dict[str, List[str]]: in_midi = [] out_midi = [] midi_in_objs = [ '__hv_bendin', '__hv_ctlin', '__hv_midiin', '__hv_midirealtimein', '__hv_notein', '__hv_pgmin', '__hv_polytouchin', '__hv_touchin', ] midi_out_objs = [ '__hv_bendout', '__hv_ctlout', '__hv_midiout', '__hv_midioutport', '__hv_noteout', '__hv_pgmout', '__hv_polytouchout', '__hv_touchout', ] for recv in hvir.control.receivers.keys(): if recv in midi_in_objs: in_midi.append(recv) for msg in hvir.control.sendMessage: if msg.name in midi_out_objs: out_midi.append(msg.name) return { 'in': in_midi, 'out': out_midi } def filter_midi_from_out_parameters(output_parameter_list: List, midi_out_objects: List) -> List: new_out_list = [] for item in output_parameter_list: if not item[0] in midi_out_objects: new_out_list.append(item) return new_out_list def generate_extern_info(hvir: IRGraph, results: CompilerResults) -> ExternInfo: """ Simplifies the receiver/send and table lists by only containing values externed with @hv_param, @hv_event or @hv_table """ # Exposed input parameters in_parameter_list = [(k, v) for k, v in hvir.control.receivers.items() if v.extern == "param"] in_parameter_list.sort(key=lambda x: x[0]) check_extern_name_conflicts("input parameter", in_parameter_list, results) # Exposed input events in_event_list = [(k, v) for k, v in hvir.control.receivers.items() if v.extern == "event"] in_event_list.sort(key=lambda x: x[0]) check_extern_name_conflicts("input event", in_event_list, results) # Exposed output parameters out_parameter_list = [(v.name, v) for v in hvir.control.sendMessage if v.extern == "param"] # remove duplicate output parameters/events # NOTE(joe): is the id argument important here? We'll only take the first one in this case. out_parameter_list = list(dict(out_parameter_list).items()) out_parameter_list.sort(key=lambda x: x[0]) check_extern_name_conflicts("output parameter", out_parameter_list, results) # Exposed output events out_event_list = [(v.name, v) for v in hvir.control.sendMessage if v.extern == "event"] out_event_list = list(dict(out_event_list).items()) out_event_list.sort(key=lambda x: x[0]) check_extern_name_conflicts("output event", out_event_list, results) # Exposed tables table_list = [(k, v) for k, v in hvir.tables.items() if v.extern] table_list.sort(key=lambda x: x[0]) check_extern_name_conflicts("table", table_list, results) # Exposed midi objects midi_objects = count_midi_objects(hvir) # filter midi objects from the output parameters list out_parameter_list = filter_midi_from_out_parameters(out_parameter_list, midi_objects['out']) return ExternInfo( parameters=ExternParams( inParam=in_parameter_list, outParam=out_parameter_list ), events=ExternEvents( inEvent=in_event_list, outEvent=out_event_list ), midi=ExternMidi( inMidi=midi_objects['in'], outMidi=midi_objects['out'] ), tables=table_list, # generate patch heuristics to ensure enough memory allocated for the patch memoryPoolSizesKb=ExternMemoryPool( internal=10, # TODO(joe): should this increase if there are a lot of internal connections? inputQueue=max(2, int( len(in_parameter_list) + (len(in_event_list) / 4) + len(midi_objects['in']) # TODO(dreamer): should this depend on the MIDI type? )), outputQueue=max(2, int( len(out_parameter_list) + (len(out_event_list) / 4) + len(midi_objects['out']) )) ) ) def load_ext_generator(module_name: str, verbose: bool) -> Optional[Generator]: try: module = importlib.import_module(module_name) for _, member in inspect.getmembers(module): if inspect.isclass(member) and not inspect.isabstract(member) and issubclass(member, Generator): return member() if verbose: print(f"---> Module {module_name} does not contain a class derived from hvcc.types.Compiler") return None except ModuleNotFoundError: return None def compile_dataflow( in_path: str, out_dir: str, patch_name: str = "heavy", patch_meta_file: Optional[str] = None, search_paths: Optional[List[str]] = None, generators: Optional[List[str]] = None, ext_generators: Optional[List[str]] = None, verbose: bool = False, copyright: Optional[str] = None, nodsp: Optional[bool] = False ) -> CompilerResults: results = CompilerResults(root={}) patch_meta = Meta() # basic error checking on input if os.path.isfile(in_path): if not in_path.endswith((".pd")): return add_error(results, "Can only process Pd files.") elif os.path.isdir(in_path): if not os.path.basename("c"): return add_error(results, "Can only process c directories.") else: return add_error(results, f"Unknown input path {in_path}") # meta-data file if patch_meta_file: if os.path.isfile(patch_meta_file): with open(patch_meta_file) as json_file: try: patch_meta_json = json.load(json_file) patch_meta = Meta(**patch_meta_json) except Exception as e: return add_error(results, f"Unable to open json_file: {e}") patch_name = patch_meta.name or patch_name generators = ["c"] if generators is None else [x.lower() for x in generators] if verbose: print("--> Generating C") results.root["pd2hv"] = pd2hv.pd2hv.compile( pd_path=in_path, hv_dir=os.path.join(out_dir, "hv"), search_paths=search_paths, verbose=verbose) # check for errors response: CompilerResp = list(results.root.values())[0] if response.notifs.has_error: return results subst_name = re.sub(r'\W', '_', patch_name) results.root["hv2ir"] = hv2ir.hv2ir.compile( hv_file=os.path.join(response.out_dir, response.out_file), # ensure that the ir filename has no funky characters in it ir_file=os.path.join(out_dir, "ir", f"{subst_name}.heavy.ir.json"), patch_name=patch_name, verbose=verbose) # check for errors if results.root["hv2ir"].notifs.has_error: return results # get the hvir data hvir = results.root["hv2ir"].ir assert hvir is not None patch_name = hvir.name.escaped externs = generate_extern_info(hvir, results) # get application path if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'): application_path = os.path.join(sys._MEIPASS, 'hvcc') elif __file__: application_path = os.path.dirname(__file__) c_src_dir = os.path.join(out_dir, "c") results.root["ir2c"] = ir2c.ir2c.compile( hv_ir_path=os.path.join(results.root["hv2ir"].out_dir, results.root["hv2ir"].out_file), static_dir=os.path.join(application_path, "generators/ir2c/static"), output_dir=c_src_dir, externs=externs, copyright=copyright, nodsp=nodsp) # check for errors if results.root["ir2c"].notifs.has_error: return results # ir2c_perf results.root["ir2c_perf"] = CompilerResp( stage="ir2c_perf", obj_perf=ir2c_perf.ir2c_perf.perf(hvir, verbose=verbose), in_dir=results.root["hv2ir"].out_dir, in_file=results.root["hv2ir"].out_file, ) # run the c2x generators, merge the results num_input_channels = hvir.signal.numInputBuffers num_output_channels = hvir.signal.numOutputBuffers gen_args: Dict[str, Any] = { 'c_src_dir': c_src_dir, 'out_dir': out_dir, 'patch_name': patch_name, 'patch_meta': patch_meta, 'num_input_channels': num_input_channels, 'num_output_channels': num_output_channels, 'externs': externs, 'copyright': copyright, 'verbose': verbose } if "js" in generators: if verbose: print("--> Generating Javascript") results.root["c2js"] = c2js.c2js.compile(**gen_args) if "daisy" in generators: if verbose: print("--> Generating Daisy module") results.root["c2daisy"] = c2daisy.c2daisy.compile(**gen_args) if "dpf" in generators: if verbose: print("--> Generating DPF plugin") results.root["c2dpf"] = c2dpf.c2dpf.compile(**gen_args) if "owl" in generators: if verbose: print("--> Generating OWL plugin") results.root["c2owl"] = c2owl.c2owl.compile(**gen_args) if "pdext" in generators: if verbose: print("--> Generating Pd external") results.root["c2pdext"] = c2pdext.c2pdext.compile(**gen_args) if "unity" in generators: if verbose: print("--> Generating Unity plugin") results.root["c2unity"] = c2unity.c2unity.compile(**gen_args) if "wwise" in generators: if verbose: print("--> Generating Wwise plugin") results.root["c2wwise"] = c2wwise.c2wwise.compile(**gen_args) if ext_generators: for module_name in ext_generators: generator = load_ext_generator(module_name, verbose) if generator is not None: if verbose: print(f"--> Executing custom generator from module {module_name}") results.root[module_name] = generator.compile(**gen_args) return results ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7462065 hvcc-0.13.3/hvcc/core/__init__.py0000644000000000000000000000000014435670357013437 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2595525 hvcc-0.13.3/hvcc/core/hv2ir/BufferPool.py0000644000000000000000000001021514677551203015002 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from collections import defaultdict from typing import Dict, List, Optional, Tuple from .HeavyException import HeavyException class BufferPool: def __init__(self) -> None: # the idea is that the same buffer is reused as quickly as possible so that it doesn't need # to be moved around in the cache. It does not give substantially different results # from a Counter-based implementation, but it is more consistent and predictable. self.pool: Dict = { "~f>": defaultdict(list), "~i>": defaultdict(list) } def num_buffers(self, connection_type: Optional[str] = None) -> int: """ Returns the number of buffers with the given retain count. By default returns the size of the entire pool. Number of buffers per connection type can also be retrieved. """ if connection_type is None: return self.num_buffers("~f>") + self.num_buffers("~i>") elif connection_type in self.pool: return sum(len(v) for v in self.pool[connection_type].values()) else: raise HeavyException(f"Unknown connection type: \"{connection_type}\"") def get_buffer(self, connection_type: str, count: int = 1, excludeSet: Optional[set] = None) -> Tuple[str, int]: """ Returns a currently unused buffer. The buffer can be assigned a retain count. An optional exclude set can also be supplied, ensuring that the returned buffer is not one of them. """ excludeSet = excludeSet if excludeSet is not None else set() pool = self.pool[connection_type] # get the most recently used, unused buffer b = next((b for b in reversed(pool[0]) if b not in excludeSet), None) if b is not None: pool[0].remove(b) else: # if we get here, then no available buffer was found. Create a new one. b = (connection_type, self.num_buffers(connection_type)) # new buffer index for the given type pool[count].append(b) return b def retain_buffer(self, b: List, count: int = 1) -> int: """ Increases the retain count of the buffer. Returns the new count. """ # adc~ and ZERO_BUFFER are special. They cannot be retained. if b[0] in {"zero", "input"}: return 0 else: pool = self.pool[b[0]] for k, v in pool.items(): if b in v: v.remove(b) pool[k + count].append(b) return k + count # return the new retain count raise HeavyException(f"{b} not found in BufferPool!") def release_buffer(self, b: List, count: int = 1) -> int: """ Reduces the retain count of the buffer. Returns the new count. """ # adc~, ZERO_BUFFER, send~ buffers are special. They can not be released. # if the buffer is otherwise unknown (as may be in the case that objects provide their own), # they cannot be released if b[0] in {"zero", "input"}: return 0 else: pool = self.pool[b[0]] for k, v in pool.items(): if b in v: v.remove(b) pool[k - count].append(b) return k - count # return the new retain count raise HeavyException(f"{b} not found in BufferPool!") def __repr__(self) -> str: return self.pool["~f>"].__repr__() + self.pool["~i>"].__repr__() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2595525 hvcc-0.13.3/hvcc/core/hv2ir/Connection.py0000644000000000000000000000621314677551203015041 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, TYPE_CHECKING if TYPE_CHECKING: from .HeavyIrObject import HeavyIrObject class Connection: """ A Connection describes a connection between two objects. """ def __init__( self, from_object: 'HeavyIrObject', outlet_index: int, to_object: 'HeavyIrObject', inlet_index: int, conn_type: str ) -> None: self.from_object = from_object self.outlet_index = outlet_index self.to_object = to_object self.inlet_index = inlet_index self.type = conn_type # cache the hash of this object self.__hash = hash(( self.from_object, self.outlet_index, self.to_object, self.inlet_index, self.type)) def copy( self, from_object: Optional['HeavyIrObject'] = None, outlet_index: Optional[int] = None, to_object: Optional['HeavyIrObject'] = None, inlet_index: Optional[int] = None, type: Optional[str] = None ) -> 'Connection': """ Create a new connection based on the existing one, changing the given values. """ return Connection(from_object=self.from_object if from_object is None else from_object, outlet_index=self.outlet_index if outlet_index is None else outlet_index, to_object=self.to_object if to_object is None else to_object, inlet_index=self.inlet_index if inlet_index is None else inlet_index, conn_type=self.type if type is None else type) @property def is_signal(self) -> bool: return self.is_signal_type(self.type) @property def is_control(self) -> bool: return self.type == "-->" @property def is_float_signal(self) -> bool: return self.type == "~f>" @property def is_integer_signal(self) -> bool: return self.type == "~i>" @property def is_mixed(self) -> bool: return self.type == "-~>" @classmethod def is_signal_type(cls, type: Optional[str]) -> bool: return type in {"~i>", "~f>"} def __eq__(self, other: object) -> bool: return self.__hash == other.__hash__() if isinstance(other, Connection) else False def __hash__(self) -> int: return self.__hash def __repr__(self) -> str: return f"[{self.from_object}:{self.outlet_index}] {self.type} [{self.to_object}:{self.inlet_index}]" ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.258823 hvcc-0.13.3/hvcc/core/hv2ir/HIrConvolution.py0000644000000000000000000000327214735300474015663 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, Optional, List, Set, Tuple from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HIrConvolution(HeavyIrObject): """ __conv~f """ def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional[HeavyGraph] = None, annotations: Optional[Dict] = None ) -> None: assert obj_type == "__conv~f" super().__init__(obj_type, args=args, graph=graph, annotations=annotations) def reduce(self) -> Optional[Tuple[Set, List]]: if self.graph is not None: table_obj = self.graph.resolve_object_for_name( self.args["table"], ["table", "__table"]) if table_obj is not None: self.args["table_id"] = table_obj.id return ({self}, []) else: self.add_error(f"Cannot find table named \"{self.args['table']}\" for object {self}.") return None ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.258823 hvcc-0.13.3/hvcc/core/hv2ir/HIrInlet.py0000644000000000000000000000400414735300474014411 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, Optional from .HeavyException import HeavyException from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph from hvcc.types.Lang import LangLetType class HIrInlet(HeavyIrObject): """ A specific implementation of the inlet object. """ def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional[HeavyGraph] = None, annotations: Optional[Dict] = None ) -> None: super().__init__("__inlet", args=args, graph=graph, annotations=annotations) def _resolved_outlet_type(self, outlet_index: int = 0) -> Optional[LangLetType]: if self.graph is not None: connections = self.graph.inlet_connections[self.args["index"]] connection_type_set = {c.type for c in connections} if len(connection_type_set) == 0: # object has no incident connections. return "-->" # outlet type defaults to control (-->) elif len(connection_type_set) == 1: return list(connection_type_set)[0] else: raise HeavyException( f"{self} has multiple incident connections of differing type. " "The outlet type cannot be explicitly resolved.") return None ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2605526 hvcc-0.13.3/hvcc/core/hv2ir/HIrLorenz.py0000644000000000000000000000226714677551203014623 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, Optional from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HIrLorenz(HeavyIrObject): """ __lorenz~f """ def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional[HeavyGraph] = None, annotations: Optional[Dict] = None ) -> None: assert obj_type == "__lorenz~f" super().__init__(obj_type, args=args, graph=graph, annotations=annotations) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.258823 hvcc-0.13.3/hvcc/core/hv2ir/HIrOutlet.py0000644000000000000000000000300714735300474014614 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List, Optional from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph from hvcc.types.IR import IROnMessage class HIrOutlet(HeavyIrObject): """ A specific implementation of the outlet object. """ def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional[HeavyGraph] = None, annotations: Optional[Dict] = None ) -> None: super().__init__("__outlet", args=args, graph=graph, annotations=annotations) def get_ir_on_message(self, inlet_index: int = 0) -> List[IROnMessage]: x = [] if self.graph is not None: for c in self.graph.outlet_connections[self.args["index"]]: x.extend(c.to_object.get_ir_on_message(c.inlet_index)) return x ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2605526 hvcc-0.13.3/hvcc/core/hv2ir/HIrPack.py0000644000000000000000000000252714677551203014227 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, Optional from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HIrPack(HeavyIrObject): def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional[HeavyGraph] = None, annotations: Optional[Dict] = None ) -> None: if args is not None: num_inlets = len(args["values"]) else: num_inlets = 0 super().__init__("__pack", args=args, graph=graph, num_inlets=num_inlets, num_outlets=1, annotations=annotations) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.258823 hvcc-0.13.3/hvcc/core/hv2ir/HIrReceive.py0000644000000000000000000000324514735300474014726 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import re from typing import Dict, Optional, TYPE_CHECKING from .HeavyIrObject import HeavyIrObject if TYPE_CHECKING: from .HeavyGraph import HeavyGraph class HIrReceive(HeavyIrObject): """ A specific implementation of the __receive object. """ def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional['HeavyGraph'] = None, annotations: Optional[Dict] = None ) -> None: super().__init__("__receive", args=args, graph=graph, annotations=annotations) if args is not None and args["extern"]: # externed receivers must contain only alphanumeric characters or underscores, # so that the names can be easily and transparently turned into code if re.search(r"\W", args["name"]): self.add_error(f"Parameter and Event names may only contain \ alphanumeric characters or underscore: '{args['name']}'") ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.258823 hvcc-0.13.3/hvcc/core/hv2ir/HIrSend.py0000644000000000000000000000466314735300474014242 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import re from typing import Dict, List, Optional from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph from hvcc.types.IR import IRSendMessage class HIrSend(HeavyIrObject): """ A specific implementation of the __send object. """ def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional[HeavyGraph] = None, annotations: Optional[Dict] = None ) -> None: super().__init__("__send", args=args, graph=graph, annotations=annotations) if args is not None and args["extern"]: # output parameters must contain only alphanumeric characters or underscores, # so that the names can be easily and transparently turned into code if re.search(r"\W", args["name"]): self.add_error(f"Parameter and Event names may only contain \ alphanumeric characters or underscore: '{args['name']}'") def get_ir_control_list(self) -> List[IRSendMessage]: if self.graph is not None and self.name is not None: receive_objs = self.graph.resolve_objects_for_name(self.name, "__receive") on_message_list = [x for o in receive_objs for x in o.get_ir_on_message(inlet_index=0)] return [IRSendMessage( id=self.id, type="send", onMessage=[on_message_list], extern=self.args["extern"], attributes=self.args["attributes"], hash=self.args["hash"], display=self.args["name"], name=((f"_{self.args['name']}") if re.match(r"\d", self.args["name"]) else self.args["name"]) )] else: return [] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2615526 hvcc-0.13.3/hvcc/core/hv2ir/HIrSwitchcase.py0000644000000000000000000000273314677551203015445 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, Optional from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HIrSwitchcase(HeavyIrObject): """ A specific implementation of the __switchcase object. """ def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional[HeavyGraph] = None, annotations: Optional[Dict] = None ) -> None: if args is not None: num_cases = len(args["cases"]) else: num_cases = 0 super().__init__("__switchcase", args=args, graph=graph, num_inlets=1, num_outlets=num_cases + 1, annotations=annotations) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.258823 hvcc-0.13.3/hvcc/core/hv2ir/HIrTabhead.py0000644000000000000000000000331314735300474014670 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, Optional, List, Set, Tuple from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HIrTabhead(HeavyIrObject): """ __tabhead~f and __tabhead """ def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional[HeavyGraph] = None, annotations: Optional[Dict] = None ) -> None: assert obj_type in {"__tabhead~f", "__tabhead"} super().__init__(obj_type, args=args, graph=graph, annotations=annotations) def reduce(self) -> Optional[Tuple[Set, List]]: if self.graph is not None: table_obj = self.graph.resolve_object_for_name( self.args["table"], ["table", "__table"]) if table_obj is not None: self.args["table_id"] = table_obj.id return ({self}, []) else: self.add_error(f"Can't find table with name \"{self.args['table']}\".") return None ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2598228 hvcc-0.13.3/hvcc/core/hv2ir/HIrTabread.py0000644000000000000000000000340514735300474014704 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, Optional, List, Set, Tuple from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HIrTabread(HeavyIrObject): """ __tabread~if """ def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional[HeavyGraph] = None, annotations: Optional[Dict] = None ) -> None: assert obj_type in {"__tabread~if", "__tabread~f", "__tabread_stoppable~f", "__tabreadu~f", "__tabread"} super().__init__(obj_type, args=args, graph=graph, annotations=annotations) def reduce(self) -> Optional[Tuple[Set, List]]: if self.graph is not None: table_obj = self.graph.resolve_object_for_name( self.args["table"], ["table", "__table"]) if table_obj is not None: self.args["table_id"] = table_obj.id return ({self}, []) else: self.add_error(f"Cannot find table named \"{self.args['table']}\" for object {self}.") return None ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2598228 hvcc-0.13.3/hvcc/core/hv2ir/HIrTabwrite.py0000644000000000000000000000333214735300474015122 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, Optional, List, Set, Tuple from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HIrTabwrite(HeavyIrObject): """ __tabwrite~f """ def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional[HeavyGraph] = None, annotations: Optional[Dict] = None ) -> None: assert obj_type in {"__tabwrite~f", "__tabwrite_stoppable~f", "__tabwrite"} super().__init__(obj_type, args=args, graph=graph, annotations=annotations) def reduce(self) -> Optional[Tuple[Set, List]]: if self.graph is not None: table_obj = self.graph.resolve_object_for_name( self.args["table"], ["table", "__table"]) if table_obj is not None: self.args["table_id"] = table_obj.id return ({self}, []) else: self.add_error(f"Can't find table with name \"{self.args['table']}\".") return None ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2598228 hvcc-0.13.3/hvcc/core/hv2ir/HLangAdc.py0000644000000000000000000000432214735300474014337 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyIrObject import HeavyIrObject from .HeavyLangObject import HeavyLangObject from .HeavyGraph import HeavyGraph from hvcc.types.Lang import LangLetType class HLangAdc(HeavyLangObject): """ adc """ def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "adc" super().__init__(obj_type, args, graph, num_inlets=0, num_outlets=len(args[self._HEAVY_LANG_DICT[obj_type].args[0].name]), annotations=annotations) def _resolved_outlet_type(self, outlet_index: int = 0) -> LangLetType: return "~f>" def reduce(self) -> tuple: objects = set() connections = [] # reduce a HeavyLang adc to a number of individual HeavyIR __inlet objects for i, channel_index in enumerate(self.args["channels"]): if len(self.outlet_connections[i]) > 0: # if there are any connections to this inlet x = HeavyIrObject("__inlet", args={ "index": 127 + channel_index }) x.outlet_buffers[0] = ("input", channel_index - 1) # channel indicies are one-indexed objects.add(x) for c in self.outlet_connections[i]: connections.append((c, [c.copy(from_object=x, outlet_index=0)])) return (objects, connections) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2615526 hvcc-0.13.3/hvcc/core/hv2ir/HLangBinop.py0000644000000000000000000002516014677551203014725 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .Connection import Connection from .HeavyLangObject import HeavyLangObject from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HLangBinop(HeavyLangObject): __HEAVY_DICT = { "+": ["__add", "__add_k", "__add~f", "__add~i"], "-": ["__sub", "__sub_k", "__sub~f", "__sub~i"], "*": ["__mul", "__mul_k", "__mul~f", "__mul~i"], "/": ["__div", "__div_k", "__div~f", "__div~i"], "max": ["__max", "__max_k", "__max~f", "__max~i"], "min": ["__min", "__min_k", "__min~f", "__min~i"], ">": ["__gt", "__gt_k", "__gt~f", "__gt~i"], ">=": ["__gte", "__gte_k", "__gte~f", "__gte~i"], "==": ["__eq", "__eq_k", "__eq~f", "__eq~i"], "!=": ["__neq", "__neq_k", "__neq~f", "__neq~i"], "<": ["__lt", "__lt_k", "__lt~f", "__lt~i"], "<=": ["__lte", "__lte_k", "__lte~f", "__lte~i"], "&": ["__and", "__and_k", "__and~f", "__and~i"], # binary and "&&": ["__logand", "__logand_k"], # logical or "&!": ["__andnot", "__andnot~f", "__andnot~i"], "|": ["__or", "__or_k", "__or~f", "__or~i"], # binary or "||": ["__logor", "__logor_k"], # logical or "pow": ["__pow", "__pow_k", "__pow~f", "__pow~i"], "atan2": ["__atan2", "__atan2_k", "__atan2~f"], "mod": ["__unimod", "__unimod_k"], "%": ["__bimod", "__bimod_k"], ">>": ["__shiftright", "__shiftright_k"], # binary right shift "<<": ["__shiftleft", "__shiftleft_k"] # binary left shift } def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional['HeavyGraph'] = None, annotations: Optional[Dict] = None ) -> None: super().__init__(obj_type, args, graph, num_inlets=2, num_outlets=1, annotations=annotations) @classmethod def handles_type(cls, obj_type: str) -> bool: """Returns True if this class handles the given object type. False otherwise. """ return obj_type in HLangBinop.__HEAVY_DICT def reduce(self) -> Optional[tuple]: if self.has_inlet_connection_format("__") or \ self.has_inlet_connection_format("_c") or \ self.has_inlet_connection_format("_f") or \ self.has_outlet_connection_format("_"): # binary operator objects must have a left inlet or outlet connection. return (set(), []) # remove this object if self.has_inlet_connection_format("ff"): ir_type = [x for x in HLangBinop.__HEAVY_DICT[self.type] if x.endswith("~f")][0] x = HeavyIrObject(ir_type) return ({x}, self.get_connection_move_list(x)) elif self.has_inlet_connection_format("fc"): ir_type = [x for x in HLangBinop.__HEAVY_DICT[self.type] if x.endswith("~f")][0] x = HeavyIrObject(ir_type) y = HeavyIrObject("__var~f", {"k": self.args[self.name_for_arg()]}) z = HeavyIrObject("__varread~f", {"var_id": y.id}) connections = [(None, [Connection(z, 0, x, 1, "~f>")])] for c in self.inlet_connections[0]: # left inlet to ir_type connections.append((c, [c.copy(to_object=x)])) for c in self.inlet_connections[1]: # right inlet to __var~f connections.append((c, [c.copy(to_object=y, inlet_index=0)])) for c in self.outlet_connections[0]: # ir_type outlet connections.append((c, [c.copy(from_object=x)])) return ({x, y, z}, connections) elif self.has_inlet_connection_format("f_"): ir_type = [x for x in HLangBinop.__HEAVY_DICT[self.type] if x.endswith("~f")][0] # handle identity-operations if (self.type == "+" and self.args["k"] == 0.0) or \ (self.type == "-" and self.args["k"] == 0.0) or \ (self.type == "*" and self.args["k"] == 1.0) or \ (self.type == "/" and self.args["k"] == 1.0): if len(self.inlet_connections[0]) == 0: return (set(), []) # remove this object elif len(self.inlet_connections[0]) == 1: # there is only one connection, pass through the connection # and remove this object c = self.inlet_connections[0][0] connections = [(c, [c.copy(to_object=v.to_object, inlet_index=v.inlet_index) for v in self.outlet_connections[0]])] return (set(), connections) else: # len(self.inlet_connections[0]) > 1 # there are multiple connections to the left inlet # create a __add~f, move one connection to the left inlet # and the remainder to the right inlet x = HeavyIrObject("__add~f") c = self.inlet_connections[0][0] connections = [(c, [c.copy(to_object=x, inlet_index=0)])] for c in self.inlet_connections[0][1:]: connections.append((c, [c.copy(to_object=x, inlet_index=1)])) for c in self.outlet_connections[0]: connections.append((c, [c.copy(from_object=x, outlet_index=0)])) return ({x}, connections) if self.type == "*": # self.args["k"] == 1.0 case handled above if self.args["k"] == 0.0: # this object does nothing at all. Remove it. return (set(), []) if self.args["k"] == -1.0: x = HeavyIrObject("__neg~f") return ({x}, self.get_connection_move_list(x)) x = HeavyIrObject(ir_type) # add constant generator y = HeavyIrObject( "__var_k~f", args={"k": self.args[self.name_for_arg()]}) connections = self.get_connection_move_list(x) connections.append((None, [Connection(y, 0, x, 1, "~f>")])) return ({x, y}, connections) elif self.has_inlet_connection_format("ii"): ir_type = [x for x in HLangBinop.__HEAVY_DICT[self.type] if x.endswith("~i")][0] x = HeavyIrObject(ir_type) return ({x}, self.get_connection_move_list(x)) elif self.has_inlet_connection_format("ic"): ir_type = [x for x in HLangBinop.__HEAVY_DICT[self.type] if x.endswith("~i")][0] x = HeavyIrObject(ir_type) y = HeavyIrObject("__var~i", {"k": self.args[self.name_for_arg()]}) z = HeavyIrObject("__varread~i", {"var_id": y.id}) connections = [(None, [Connection(z, 0, x, 1, "~f>")])] for c in self.inlet_connections[0]: connections.append((c, [c.copy(to_object=x)])) for c in self.inlet_connections[1]: connections.append((c, [c.copy(to_object=y, inlet_index=0)])) for c in self.outlet_connections[0]: connections.append((c, [c.copy(from_object=x)])) return ({x, y, z}, connections) elif self.has_inlet_connection_format("i_"): ir_type = [x for x in HLangBinop.__HEAVY_DICT[self.type] if x.endswith("~i")][0] x = HeavyIrObject(ir_type) # add constant generator y = HeavyIrObject( "__var_k~i", args={"k": self.args[self.name_for_arg()]}) connections = [(None, [Connection(y, 0, x, 1, "~i>")])] for c in self.inlet_connections[0]: connections.append((c, [c.copy(to_object=x)])) for c in self.inlet_connections[1]: connections.append((c, [c.copy(to_object=y, inlet_index=0)])) for c in self.outlet_connections[0]: connections.append((c, [c.copy(from_object=x)])) return ({x, y}, connections) elif self.has_inlet_connection_format("cc"): ir_type = HLangBinop.__HEAVY_DICT[self.type][0] # standardise the operation's constant argument name to "k" args = {"k": self.args[self.name_for_arg()]} x = HeavyIrObject(ir_type, args) return ({x}, self.get_connection_move_list(x)) elif self.has_inlet_connection_format("c_"): # if the right inlet is empty, generate a constant variation of the object ir_type = [x for x in HLangBinop.__HEAVY_DICT[self.type] if x.endswith("_k")][0] # standardise the operation's constant argument name to "k" args = {"k": self.args[self.name_for_arg()]} x = HeavyIrObject(ir_type, args) return ({x}, self.get_connection_move_list(x)) elif self.has_inlet_connection_format("cf"): ir_type = [x for x in HLangBinop.__HEAVY_DICT[self.type] if x.endswith("~f")][0] x = HeavyIrObject(ir_type) v = HeavyIrObject("__var~f") vr = HeavyIrObject("__varread~f", args={"var_id": v.id}) obj_set = set([x, v, vr]) connections = [(None, [Connection(vr, 0, x, 0, "~f>")])] for c in self.inlet_connections[0]: connections.append((c, [c.copy(to_object=v, inlet_index=0)])) for c in self.inlet_connections[1]: connections.append((c, [c.copy(to_object=x, inlet_index=1)])) for c in self.outlet_connections[0]: connections.append((c, [c.copy(from_object=x, outlet_index=0)])) return (obj_set, connections) else: fmt = self._get_connection_format(self.inlet_connections) if "m" in fmt: self.add_error( "A binary operator cannot have both a signal and control " f"connection to the same inlet: {fmt}") else: self.add_error(f"Unknown inlet configuration: {fmt}") return None ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2615526 hvcc-0.13.3/hvcc/core/hv2ir/HLangBiquad.py0000644000000000000000000000400714677551203015060 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import re from typing import Optional, Dict from .HeavyException import HeavyException from .HeavyIrObject import HeavyIrObject from .HeavyLangObject import HeavyLangObject from .HeavyGraph import HeavyGraph class HLangBiquad(HeavyLangObject): """ Translates HeavyLang object biquad to HeavyIR biquad~. """ # used to detect valid connection configuration formats __re_fmt_k = re.compile("[f_][c_]+") __re_fmt_f = re.compile("[f_]+") def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "biquad" super().__init__(obj_type, args, graph, num_inlets=6, num_outlets=1, annotations=annotations) def reduce(self) -> tuple: fmt = self._get_connection_format(self.inlet_connections) if self.__re_fmt_k.search(fmt): x = HeavyIrObject("__biquad_k~f", self.args) return {x}, self.get_connection_move_list(x) elif self.__re_fmt_f.search(fmt): x = HeavyIrObject("__biquad~f", self.args) return {x}, self.get_connection_move_list(x) else: raise HeavyException(f"Unsupported connection format to biquad: {fmt}") ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2598228 hvcc-0.13.3/hvcc/core/hv2ir/HLangDac.py0000644000000000000000000000415114735300474014337 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyIrObject import HeavyIrObject from .HeavyLangObject import HeavyLangObject from .HeavyGraph import HeavyGraph class HLangDac(HeavyLangObject): """ Translates HeavyLang [dac] to HeavyIR [__add~f]. """ def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "dac" super().__init__(obj_type, args, graph, num_inlets=len(args[self._HEAVY_LANG_DICT[obj_type].args[0].name]), num_outlets=0, annotations=annotations) def reduce(self) -> tuple: objects = set() connections = [] # reduce a HeavyLang dac to a number of individual HeavyIR __add~f objects for i, channel_index in enumerate(self.args["channels"]): if len(self.inlet_connections[i]) > 0: # if there are any connections to this inlet x = HeavyIrObject("__add~f") x.inlet_buffers[1] = ("output", channel_index - 1) # channel indicies are one-indexed x.outlet_buffers[0] = ("output", channel_index - 1) objects.add(x) for c in self.inlet_connections[i]: connections.append((c, [c.copy(to_object=x, inlet_index=0)])) return (objects, connections) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2615526 hvcc-0.13.3/hvcc/core/hv2ir/HLangDelay.py0000644000000000000000000000276314677551203014720 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyIrObject import HeavyIrObject from .HeavyLangObject import HeavyLangObject from .HeavyGraph import HeavyGraph class HLangDelay(HeavyLangObject): """ Handle the delay object. """ def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional['HeavyGraph'] = None, annotations: Optional[Dict] = None ) -> None: assert obj_type == "delay" super().__init__("delay", args, graph, num_inlets=2, num_outlets=1, annotations=annotations) def reduce(self) -> tuple: x = HeavyIrObject("__delay", self.args, annotations=self.annotations) return ({x}, self.get_connection_move_list(x)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7482066 hvcc-0.13.3/hvcc/core/hv2ir/HLangIf.py0000644000000000000000000000373214435670357014221 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # moved to HeavyParser.py because of circular dependency # from .HeavyException import HeavyException # from .HeavyIrObject import HeavyIrObject # from .HeavyLangObject import HeavyLangObject # class HLangIf(HeavyLangObject): # """ Translates HeavyLang object [if] to HeavyIR [if] or [if~]. # """ # def __init__(self, obj_type, args, graph, annotations=None): # HeavyLangObject.__init__(self, "if", args, graph, # num_inlets=2, # num_outlets=2, # annotations=annotations) # def reduce(self): # if self.has_inlet_connection_format(["cc", "_c", "c_", "__"]): # x = HeavyIrObject("__if", self.args) # elif self.has_inlet_connection_format("ff"): # # TODO(mhroth): implement this # x = HeavyParser.graph_from_file("./hvlib/if~f.hv.json") # elif self.has_inlet_connection_format("ii"): # # TODO(mhroth): implement this # x = HeavyParser.graph_from_file("./hvlib/if~i.hv.json") # else: # fmt = self._get_connection_format(self.inlet_connections) # raise HeavyException(f"Unhandled connection configuration to object [if]: {fmt}") # return ({x}, self.get_connection_move_list(x)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2625525 hvcc-0.13.3/hvcc/core/hv2ir/HLangLine.py0000644000000000000000000000330714677551203014544 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyIrObject import HeavyIrObject from .HeavyLangObject import HeavyLangObject from .HeavyGraph import HeavyGraph class HLangLine(HeavyLangObject): """ Translates HeavyLang object [line] to HeavyIR [__line] or [__line~f]. """ def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "line" super().__init__("line", args, graph, num_inlets=2, num_outlets=1, annotations=annotations) def reduce(self) -> tuple: if self.has_outlet_connection_format("f"): x = HeavyIrObject("__line~f", self.args) elif self.has_outlet_connection_format("c"): x = HeavyIrObject("__line", self.args) else: self.add_error("Unknown inlet configuration.") return ({x}, self.get_connection_move_list(x)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2625525 hvcc-0.13.3/hvcc/core/hv2ir/HLangMessage.py0000644000000000000000000000271114677551203015237 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyLangObject import HeavyLangObject from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HLangMessage(HeavyLangObject): """ Handles the HeavyLang "message" object. """ def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "message" super().__init__(obj_type, args, graph, num_inlets=1, num_outlets=1, annotations=annotations) def reduce(self) -> tuple: x = HeavyIrObject("__message", self.args) return ({x}, self.get_connection_move_list(x)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2625525 hvcc-0.13.3/hvcc/core/hv2ir/HLangNoise.py0000644000000000000000000000325014677551203014727 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # moved to HeavyParser.py because of circular dependency # import os # import random # from .HeavyLangObject import HeavyLangObject # from .HeavyParser import HeavyParser # class HLangNoise(HeavyLangObject): # """ Handles the HeavyLang "noise" object. # """ # def __init__(self, obj_type, args, graph, annotations=None): # assert obj_type == "noise" # HeavyLangObject.__init__(self, "noise", args, graph, # num_inlets=1, # num_outlets=1, # annotations=annotations) # def reduce(self): # seed = int(random.uniform(1, 2147483647)) # assign a random 32-bit seed # noise_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "./hvlib/noise.hv.json") # x = HeavyParser.graph_from_file(noise_path, graph_args={"seed": seed}) # x.reduce() # # TODO(mhroth): deal with control input # return ({x}, self.get_connection_move_list(x)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2625525 hvcc-0.13.3/hvcc/core/hv2ir/HLangPhasor.py0000644000000000000000000000307014677551203015106 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyIrObject import HeavyIrObject from .HeavyLangObject import HeavyLangObject from .HeavyGraph import HeavyGraph class HLangPhasor(HeavyLangObject): """ Translates HeavyLang object [phasor] to HeavyIR [phasor~]. """ def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "phasor" super().__init__(obj_type, args, graph, annotations=annotations) def reduce(self) -> tuple: if self.has_inlet_connection_format(["f_", "fc"]): x = HeavyIrObject("__phasor~f", self.args) return ({x}, self.get_connection_move_list(x)) else: x = HeavyIrObject("__phasor_k~f", self.args) return ({x}, self.get_connection_move_list(x)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2625525 hvcc-0.13.3/hvcc/core/hv2ir/HLangPrint.py0000644000000000000000000000270114677551203014746 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyLangObject import HeavyLangObject from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HLangPrint(HeavyLangObject): """ Handles the HeavyLang "print" object. """ def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "print" super().__init__(obj_type, args, graph, num_inlets=1, num_outlets=0, annotations=annotations) def reduce(self) -> tuple: x = HeavyIrObject("__print", self.args) return ({x}, self.get_connection_move_list(x)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2625525 hvcc-0.13.3/hvcc/core/hv2ir/HLangRandom.py0000644000000000000000000000303314677551203015071 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import random from typing import Optional, Dict from .HeavyLangObject import HeavyLangObject from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HLangRandom(HeavyLangObject): """ Handles the HeavyLang "print" object. """ def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "random" super().__init__(obj_type, args, graph, num_inlets=2, num_outlets=1, annotations=annotations) def reduce(self) -> tuple: self.args["seed"] = int(random.uniform(-2147483647, 2147483648)) x = HeavyIrObject("__random", self.args) return ({x}, self.get_connection_move_list(x)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2625525 hvcc-0.13.3/hvcc/core/hv2ir/HLangReceive.py0000644000000000000000000000421214677551203015233 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyLangObject import HeavyLangObject from .HIrReceive import HIrReceive from .HeavyGraph import HeavyGraph class HLangReceive(HeavyLangObject): """ Translates HeavyLang object [receive] to HeavyIR [__receive if control, otherwise for signal connections it will remove the send~/receive~ objects and reorder the graph. """ def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "receive" super().__init__(obj_type, args, graph, annotations=annotations) def reduce(self) -> Optional[tuple]: if self.has_outlet_connection_format(["c"]): x = HIrReceive("__receive", self.args, annotations=self.annotations) return ({x}, self.get_connection_move_list(x)) elif self.has_outlet_connection_format(["f"]): # this case should be handled already in HeavyGraph.remap_send_receive() # clean up just in case return (set(), []) elif self.has_outlet_connection_format("_"): self.add_warning("receive~ object doesn't have any outputs, this one is being removed.") return (set(), []) else: fmt = self._get_connection_format(self.outlet_connections) self.add_error(f"Unknown outlet configuration: {fmt}") return None ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2625525 hvcc-0.13.3/hvcc/core/hv2ir/HLangSend.py0000644000000000000000000000470114677551203014545 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyLangObject import HeavyLangObject from .HIrSend import HIrSend from .HeavyGraph import HeavyGraph class HLangSend(HeavyLangObject): """ Translates HeavyLang object [send] to HeavyIR [__send] if control, otherwise for signal connections it will remove the send~/receive~ objects and reorder the graph. """ def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "send" super().__init__(obj_type, args, graph, annotations=annotations) def reduce(self) -> Optional[tuple]: if self.has_inlet_connection_format("c"): ir_args = dict(self.args) ir_args["hash"] = f"0x{HeavyLangObject.get_hash(ir_args['name']):X}" x = HIrSend("__send", ir_args, annotations=self.annotations) return ({x}, self.get_connection_move_list(x)) elif self.has_inlet_connection_format("f"): # this case should be handled already in HeavyGraph.remap_send_receive() # clean up just in case return (set(), []) elif self.has_inlet_connection_format("_"): self.add_warning("send~ object doesn't have any inputs, this one is being removed.") return (set(), []) elif self.has_inlet_connection_format("m"): self.add_error( "Inlet can support either control or signal connections, " "but not both at the same time.") return None else: fmt = self._get_connection_format(self.inlet_connections) self.add_error(f"Unknown inlet configuration: {fmt}") return None ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2598228 hvcc-0.13.3/hvcc/core/hv2ir/HLangSequence.py0000644000000000000000000000636114735300474015425 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict, List from .Connection import Connection from .HeavyException import HeavyException from .HeavyIrObject import HeavyIrObject from .HeavyLangObject import HeavyLangObject from .HeavyGraph import HeavyGraph class HLangSequence(HeavyLangObject): def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: # get the number of outlets that this object has num_outlets = len(args[self._HEAVY_LANG_DICT[obj_type].args[0].name]) super().__init__(obj_type, args, graph, num_inlets=1, num_outlets=num_outlets, annotations=annotations) def reduce(self) -> tuple: cast_objs: List = [] for a in self.args[self.name_for_arg()]: if a in {"a", "anything", "l", "list"}: cast_objs.append(None) # pass through elif a in {"b", "bang"}: cast_objs.append(HeavyIrObject("__cast_b", {})) elif a in {"f", "float"}: cast_objs.append(HeavyIrObject("__cast_f", {})) elif a in {"s", "symbol"}: cast_objs.append(HeavyIrObject("__cast_s", {})) else: raise HeavyException(f"Unsupported cast type '{a}'.") connections = [] # establish connections from inlet objects to the cast objects for ci in self.inlet_connections[0]: c_list = [] for i in range(self.num_outlets - 1, -1, -1): if cast_objs[i] is not None: c_list.append(Connection.copy(ci, to_object=cast_objs[i], inlet_index=0)) else: # for anything casts, establish a connection directly to the target for co in self.outlet_connections[i]: c_list.append(Connection.copy(ci, to_object=co.to_object, inlet_index=co.inlet_index)) connections.append((ci, c_list)) # establish connections from the cast objects for i in range(self.num_outlets - 1, -1, -1): if cast_objs[i] is not None: for c in self.outlet_connections[i]: connections.append((c, [c.copy(from_object=cast_objs[i], outlet_index=0)])) # remove None objects from cast_objs. It was only used as a placeholder # to indicate that a cast passthrough objects = set(cast_objs) objects.discard(None) return (objects, connections) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2625525 hvcc-0.13.3/hvcc/core/hv2ir/HLangSlice.py0000644000000000000000000000270114677551203014711 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyLangObject import HeavyLangObject from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HLangSlice(HeavyLangObject): """ Handles the HeavyLang "slice" object. """ def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "slice" super().__init__(obj_type, args, graph, num_inlets=3, num_outlets=2, annotations=annotations) def reduce(self) -> tuple: x = HeavyIrObject("__slice", self.args) return ({x}, self.get_connection_move_list(x)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2625525 hvcc-0.13.3/hvcc/core/hv2ir/HLangSystem.py0000644000000000000000000000270514677551203015142 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyLangObject import HeavyLangObject from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HLangSystem(HeavyLangObject): """ Handles the HeavyLang "system" object. """ def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "system" super().__init__(obj_type, args, graph, num_inlets=1, num_outlets=1, annotations=annotations) def reduce(self) -> tuple: x = HeavyIrObject("__system", self.args) return ({x}, self.get_connection_move_list(x)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2598228 hvcc-0.13.3/hvcc/core/hv2ir/HLangTable.py0000644000000000000000000000416714735300474014706 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import re from typing import Optional, Dict from .HeavyLangObject import HeavyLangObject from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HLangTable(HeavyLangObject): """ Handles the HeavyLang "table" object. """ def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "table" super().__init__(obj_type, args, graph, annotations=annotations) # the values argument overrides the size argument if len(self.args.get("values", [])) > 0: self.args["size"] = len(self.args["values"]) if self.args["extern"]: # externed tables must contain only alphanumeric characters or underscores, # so that the names can be easily and transparently turned into code if re.search(r"\W", args["name"]): self.add_error(f"Table names may only contain alphanumeric characters \ or underscore: '{args['name']}'") def reduce(self) -> tuple: x = HeavyIrObject("__table", self.args) # ensure that __table object maintains the same id as the original # table object. The latter is referenced by id from other objects. # Consistency must be maintained. x.id = self.id return ({x}, self.get_connection_move_list(x)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2625525 hvcc-0.13.3/hvcc/core/hv2ir/HLangUnop.py0000644000000000000000000000771114677551203014601 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyLangObject import HeavyLangObject from .HeavyIrObject import HeavyIrObject from .HeavyGraph import HeavyGraph class HLangUnop(HeavyLangObject): __HEAVY_DICT = { "log": ["__log"], "log10": ["__log10"], "log2": ["__log2", "__log2~f"], "cos": ["__cos", "__cos~f"], "acos": ["__acos", "__acos~f"], "cosh": ["__cosh", "__cosh~f"], "acosh": ["__acosh", "__acosh~f"], "sin": ["__sin", "__sin~f"], "asin": ["__asin", "__asin~f"], "sinh": ["__sinh", "__sinh~f"], "asinh": ["__asinh", "__asin~f"], "tan": ["__tan", "__tan~f"], "atan": ["__atan", "__atan~f"], "tanh": ["__tanh", "__tanh~f"], "atanh": ["__atanh", "__atanh~f"], "exp": ["__exp", "__exp~f"], "sqrt": ["__sqrt", "__sqrt~f"], "abs": ["__abs", "__abs~f", "__abs~i"], "floor": ["__floor", "__floor~f"], "ceil": ["__ceil", "__ceil~f"], "cast_fi": ["__cast~fi"], "cast_if": ["__cast~if"] } def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert self.handles_type(obj_type) super().__init__(obj_type, args, graph, num_inlets=1, num_outlets=1, annotations=annotations) @classmethod def handles_type(cls, obj_type: str) -> bool: """ Returns True if this class handles the given object type. False otherwise. """ return obj_type in HLangUnop.__HEAVY_DICT def reduce(self) -> Optional[tuple]: if len(self.inlet_connections[0]) == 0: self.add_error("Unary operator objects must have an input.") # TODO(mhroth): there is no general consensus on how to handle incoming # and outgoing connections of different types, given the local let-type # definitions. if self.type == "cast_fi": x = HeavyIrObject(self.type) # is this correct? no idea what x is otherwise return ({HeavyIrObject("__cast~fi", {})}, self.get_connection_move_list(x)) elif self.type == "cast_if": x = HeavyIrObject(self.type) # is this correct? no idea what x is otherwise return ({HeavyIrObject("__cast~if", {})}, self.get_connection_move_list(x)) elif self.has_inlet_connection_format("f"): ir_type = f"__{self.type}~f" assert ir_type in HLangUnop.__HEAVY_DICT[self.type] x = HeavyIrObject(ir_type) return ({x}, self.get_connection_move_list(x, "~f>")) elif self.has_inlet_connection_format("i"): ir_type = f"__{self.type}~i" assert ir_type in HLangUnop.__HEAVY_DICT[self.type] x = HeavyIrObject(ir_type) return ({x}, self.get_connection_move_list(x, "~i>")) elif self.has_inlet_connection_format("c"): ir_type = f"__{self.type}" assert ir_type in HLangUnop.__HEAVY_DICT[self.type] x = HeavyIrObject(ir_type) return ({x}, self.get_connection_move_list(x, "-->")) else: self.add_error("Unknown inlet configuration.") return None ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2625525 hvcc-0.13.3/hvcc/core/hv2ir/HLangVar.py0000644000000000000000000000555714677551203014416 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyIrObject import HeavyIrObject from .HeavyLangObject import HeavyLangObject from .HeavyGraph import HeavyGraph class HLangVar(HeavyLangObject): def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "var" super().__init__(obj_type, args, graph, annotations=annotations) def reduce(self) -> tuple: if self.has_inlet_connection_format("_") and self.has_outlet_connection_format("f"): x = HeavyIrObject("__var_k~f", self.args) elif self.has_inlet_connection_format("_") and self.has_outlet_connection_format("i"): x = HeavyIrObject("__var_k~i", self.args) elif self.has_inlet_connection_format(["_", "c"]) and self.has_outlet_connection_format("f"): x = HeavyIrObject("__var~f", self.args) x.id = self.id y = HeavyIrObject("__varread~f", {"var_id": self.id}) move_list = [] for c in [c for cc in self.inlet_connections for c in cc]: move_list.append((c, [c.copy(to_object=x)])) for c in [c for cc in self.outlet_connections for c in cc]: move_list.append((c, [c.copy(from_object=y)])) return ({x, y}, move_list) elif self.has_inlet_connection_format(["_", "c"]) and self.has_outlet_connection_format("i"): x = HeavyIrObject("__var~i", self.args) x.id = self.id y = HeavyIrObject("__varread~i", {"var_id": self.id}) move_list = [] for c in [c for cc in self.inlet_connections for c in cc]: move_list.append((c, [c.copy(to_object=x)])) for c in [c for cc in self.outlet_connections for c in cc]: move_list.append((c, [c.copy(from_object=y)])) return ({x, y}, move_list) elif self.has_inlet_connection_format(["_", "c"]) and self.has_outlet_connection_format(["_", "c"]): x = HeavyIrObject("__var", self.args) else: raise Exception() return ({x}, self.get_connection_move_list(x)) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2635524 hvcc-0.13.3/hvcc/core/hv2ir/HLangVario.py0000644000000000000000000000505414677551203014736 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, Dict from .HeavyException import HeavyException from .HeavyIrObject import HeavyIrObject from .HeavyLangObject import HeavyLangObject from .HeavyGraph import HeavyGraph class HLangVario(HeavyLangObject): def __init__( self, obj_type: str, args: Dict, graph: 'HeavyGraph', annotations: Optional[Dict] = None ) -> None: assert obj_type == "vario" super().__init__(obj_type, args, graph, annotations=annotations) def reduce(self) -> Optional[tuple]: if self.graph is not None and self.name is not None: var_obj = self.graph.resolve_object_for_name(self.name, "var") if var_obj is None: raise HeavyException( f"No corresponding \"var\" object found for object {self} in file {self.graph.file}" ) if self.has_inlet_connection_format("f") and self.has_outlet_connection_format("_"): x = HeavyIrObject("__varwrite~f", {"var_id": var_obj.id}) return {x}, self.get_connection_move_list(x) elif self.has_inlet_connection_format("i") and self.has_outlet_connection_format("_"): x = HeavyIrObject("__varwrite~i", {"var_id": var_obj.id}) return {x}, self.get_connection_move_list(x) elif self.has_inlet_connection_format("_") and self.has_outlet_connection_format("f"): x = HeavyIrObject("__varread~f", {"var_id": var_obj.id}) return {x}, self.get_connection_move_list(x) elif self.has_inlet_connection_format("_") and self.has_outlet_connection_format("i"): x = HeavyIrObject("__varread~i", {"var_id": var_obj.id}) return {x}, self.get_connection_move_list(x) else: raise Exception() return None ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2598228 hvcc-0.13.3/hvcc/core/hv2ir/HeavyException.py0000644000000000000000000000210014735300474015661 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from hvcc.types.compiler import CompilerNotif class HeavyException(Exception): """ This exception is raised if anything goes wrong during the hv2ir compilation process. """ def __init__(self, message: str = "") -> None: super(Exception, self).__init__(message) self.message = message self.notes: CompilerNotif = CompilerNotif() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735983617.1410897 hvcc-0.13.3/hvcc/core/hv2ir/HeavyGraph.py0000644000000000000000000012565214736201001014771 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os import re from collections import Counter from typing import Optional, Union, Dict, List, Set, Tuple from .BufferPool import BufferPool from .Connection import Connection from .LocalVars import LocalVars from .HeavyException import HeavyException from .HeavyIrObject import HeavyIrObject from .HIrReceive import HIrReceive from .HeavyLangObject import HeavyLangObject from hvcc.types.compiler import CompilerNotif from hvcc.types.IR import ( IRObjectdict, IRGraph, IRName, IRInit, IRControl, IRReceiver, IRSendMessage, IROnMessage, IRSignalList, IRSignal, IRTable, IRNumTempBuffer, ) from hvcc.types.Lang import LangLetType class HeavyGraph(HeavyIrObject): """ Represents a graph. Subclasses HeavyIrObject for functionality. "__graph" does exist as a HeavyIR object, though it has no functionality and should not appear in any IR output. """ def __init__( self, graph: Optional['HeavyGraph'] = None, graph_args: Optional[Dict] = None, file: str = "", xname: str = "heavy" ) -> None: # zero inlets and outlets until inlet/outlet objects are declared super().__init__("__graph", graph_args, graph, 0, 0) # the heavy file which defines this graph self.file = file # a user-defined name of this graph self.xname = xname # the dictionary of all objects in the graph self.objs: Dict = {} # set the local arguments if graph_args is not None: self.args = graph_args else: self.args = {} # initialise the local variables self.local_vars = LocalVars() # the list of all constituent inlet and outlet objects # graphs always start with no inlet/outlets self.inlet_objs: List = [] self.outlet_objs: List = [] # the set of input/output channels that this graph writes to self.input_channel_set: set = set() self.output_channel_set: set = set() # an ordered list of signal objects to process self.signal_order: List = [] # a pool of signal buffers for use during signal ordering and buffer assignment self.buffer_pool: Optional[BufferPool] = None def resolve_arguments(self, obj_args: Dict) -> Dict: """ Resolves the object arguments based on values from the local graph. """ args = dict(obj_args) # make a copy of the input arguments for key, value in args.items(): # do any of them reference a variable input? if isinstance(value, str): if value.find("$") > -1: # is there a value provided for that key in the graph arguments? for k in self.args: # replace all instances of $k with the argument value # do this for all keys in the graph's argument dictionary dollar_key = f"${k}" if value.find(dollar_key) > -1: if value == dollar_key: value = self.args[k] # maintain the original data type break # break because all dollar arguments have by definition been replaced else: # otherwise assume a string value value = value.replace(dollar_key, str(self.args[k])) # continue around the loop in case value has multiple dollar args if isinstance(value, str) and value.find("$") > -1: # if the variable cannot be resolved, leave it alone. # When the arguments are passed to the object, they will be # set to the default value. These unset variables are simply # removed from the argument dictionary args.pop(key, None) self.add_warning(f"Variable \"{key}\":\"{value}\" could not be resolved.") else: args[key] = value return args def connect_objects(self, c: Connection, require_intra_graph_connection: bool = True) -> None: """ Establish a connection from one object to another. Typically a connection must be made within a single graph, though this requirement may be subpressed. """ if require_intra_graph_connection: assert c.from_object.graph is c.to_object.graph, \ f"Conection established between two objects not in the same graph: {c}" # add the connection from the parent to the child c.from_object.add_connection(c) # add the connection to the child from the parent c.to_object.add_connection(c) def disconnect_objects(self, c: Connection) -> None: """ Remove a connection from one object to another. """ # remove the connection from the parent to the child c.from_object.remove_connection(c) # remove the connection to the child from the parent c.to_object.remove_connection(c) def update_connection(self, c: Connection, n_list: List) -> None: """ Update the old connection (c) with the new connections (n_list). Connection order is maintained. If c is None, this method acts as connect_objects(). If n is empty, this method acts as disconnect_objects(). """ if c is not None and len(n_list) > 0: if all([c.from_object is n.from_object for n in n_list]): # connections start at the same point c.from_object.replace_connection(c, n_list) c.to_object.remove_connection(c) for n in n_list: n.to_object.add_connection(n) elif all([c.to_object is n.to_object for n in n_list]): # connections end at the same point c.to_object.replace_connection(c, n_list) c.from_object.remove_connection(c) for n in n_list: n.from_object.add_connection(n) else: raise HeavyException(f"Connections must have a common endpoint: {c} / {n_list}") elif c is not None and len(n_list) == 0: self.disconnect_objects(c) # remove connection c elif c is None and len(n_list) > 0: for n in n_list: self.connect_objects(n) # add connection n def add_object( self, obj: HeavyIrObject, obj_id: Optional[Union[int, str]] = None ) -> None: """ Add an object to the graph based on the given id. Per-object bookkeeping is performed. """ obj_id = obj_id or obj.id if obj_id not in self.objs: obj.graph = self self.objs[obj_id] = obj # some object needs to be specially handled when added to the graph if obj.type in {"inlet", "__inlet"}: self.inlet_connections.append([]) self.inlet_buffers.append(("zero", 0)) self.inlet_objs.append(obj) # sort inlet objects according to their index, ascending self.inlet_objs.sort(key=lambda o: o.args["index"]) elif obj.type in {"outlet", "__outlet"}: self.outlet_connections.append([]) self.outlet_buffers.append(("zero", 0)) self.outlet_objs.append(obj) self.outlet_objs.sort(key=lambda o: o.args["index"]) elif obj.type in {"adc"}: self.input_channel_set.update(obj.args["channels"]) elif obj.type in {"dac"}: # if the object is a dac, keep track of the output channels # that this graph is writing to self.output_channel_set.update(obj.args["channels"]) elif obj.type in {"receive", "__receive", "send", "__send"}: self.__register_named_object(obj, obj.name) elif obj.type in {"table", "__table"}: self.__register_named_object( obj, obj.name, static=obj.static, unique=True) elif obj.type in {"var"} and obj.name is not None: self.__register_named_object( obj, obj.name, static=obj.static, unique=True) else: self.add_error(f"Duplicate object id {obj_id} found in graph.") def __register_named_object( self, obj: HeavyIrObject, name: Optional[str] = None, static: bool = False, unique: bool = False ) -> None: """ Register a named object at the appropriate graph level. """ name = name or obj.name if name is not None: if obj.scope == "private" and not static: # stay at this level self.local_vars.register_object(obj, name, static, unique) elif obj.scope == "protected": # go up one level g = self.graph if self.graph is not None else self g.local_vars.register_object(obj, name, static, unique) elif obj.scope == "public" or static: self.get_root_graph().local_vars.register_object(obj, name, static, unique) else: raise HeavyException(f"Unknown scope \"{obj.scope}\" for object {obj}.") else: raise HeavyException(f"Unknown scope \"{obj.scope}\" for object {obj}.") def __unregister_named_object( self, obj: HeavyIrObject, name: Optional[str] = None, static: bool = False, unique: bool = False ) -> None: """ Unregister a named object at the appropriate graph level. """ name = name or obj.name if name is not None: if obj.scope == "private" and not static: self.local_vars.unregister_object(obj, name) elif obj.scope == "protected": # go up one level g = self.graph if self.graph is not None else self g.local_vars.unregister_object(obj, name) elif obj.scope == "public" or static: self.get_root_graph().local_vars.unregister_object(obj, name) else: raise HeavyException(f"Unknown scope \"{obj.scope}\" for object {obj}.") else: raise HeavyException(f"Unknown scope \"{obj.scope}\" for object {obj}.") def resolve_objects_for_name( self, name: str, obj_types: Union[List, str], local_graph: Optional['HeavyGraph'] = None ) -> List: """ Returns all objects with the given name and type that are visible from this graph. Returns an empty list if no objects could be found. The results are otherwise ordered from most local/private first, and the most global last. """ obj_types = obj_types if isinstance(obj_types, list) else [obj_types] local_graph = local_graph or self obj_list = [o for o in self.local_vars.get_objects_for_name(name, obj_types) if not (o.scope == "private" and o.graph is not local_graph)] if self.graph is not None: obj_list_from_super_graph = self.graph.resolve_objects_for_name(name, obj_types, local_graph) obj_list.extend(obj_list_from_super_graph) return obj_list def resolve_object_for_name( self, name: str, obj_types: Union[List, str], local_graph: Optional['HeavyGraph'] = None ) -> Optional[HeavyIrObject]: """ Returns the first object with the given name and type that is visible from this graph. Returns None if no objects are available. This is a convenience method. """ objs = self.resolve_objects_for_name(name, obj_types, local_graph) return objs[0] if len(objs) > 0 else None def is_root_graph(self) -> bool: """ Returns true if this is the top-level (i.e. root) graph. False otherwise. """ return self.graph is None def get_root_graph(self) -> 'HeavyGraph': """Returns the top-level graph. """ if self.is_root_graph(): return self elif self.graph is not None: return self.graph.get_root_graph() else: # NOTE(dromer): we should never get here raise Exception def find_path_for_abstraction(self, obj_type: str) -> Optional[str]: """ Travels up the graph heirarchy looking for a file path to an abstraction. Returns None if no abstraction is found. """ file_path = self.local_vars.find_path_for_abstraction(obj_type) if file_path is not None: return file_path else: return self.graph.find_path_for_abstraction(obj_type) if self.graph is not None else None def remove_object(self, o: HeavyIrObject, obj_id: Optional[str] = None) -> None: """ Removes an object and all of its connections from the graph. A custom id for the object to be removed can be given. """ for connections in o.inlet_connections: for c in list(connections): # make copy of connections as it will be mutated self.disconnect_objects(c) for connections in o.outlet_connections: for c in list(connections): # make copy self.disconnect_objects(c) for k, v in self.objs.items(): if o is v: del self.objs[k] break if o.type in {"receive", "__receive", "send", "__send"}: self.__unregister_named_object(o, o.name) def get_inlet_object(self, index: int) -> HeavyIrObject: """ Returns the indexed inlet object of this graph. """ return self.inlet_objs[index] def get_outlet_object(self, index: int) -> HeavyIrObject: """ Returns the indexed outlet object of this graph. """ return self.outlet_objs[index] def get_input_channel_set(self, recursive: bool = False) -> set: """ Returns the set of input channels that this graph writes to. Optionally includes all subgraphs as well. """ if recursive: channels = set(self.input_channel_set) # copy the output channel set for o in [o for o in self.objs.values() if o.type == "__graph"]: channels.update(o.get_input_channel_set(recursive=True)) return channels else: return self.input_channel_set def get_output_channel_set(self, recursive: bool = False) -> set: """ Returns the set of output channels that this graph writes to. Optionally includes all subgraphs as well. """ if recursive: channels = set(self.output_channel_set) # copy the output channel set for o in [o for o in self.objs.values() if o.type == "__graph"]: channels.update(o.get_output_channel_set(recursive=True)) return channels else: return self.output_channel_set def get_notices(self) -> CompilerNotif: notices = HeavyLangObject.get_notices(self) for o in self.objs.values(): n = o.get_notices() notices.warnings.extend(n.warnings) notices.errors.extend(n.errors) return notices def get_objects_for_type(self, obj_type: str, recursive: bool = False) -> List: """ Returns a list of all objects of a given type in this graph. The optional parameter "recursive" also includes all objects from subgraphs. """ obj_list = [] for o in self.objs.values(): if o.type == "__graph" and recursive: obj_list.extend(o.get_objects_for_type(obj_type, recursive)) elif o.type == obj_type: obj_list.append(o) return obj_list def get_object_counter(self, recursive: bool = False) -> Counter: """ Returns a counter of all object types in this graph. Graph objects are explicitly removed. "__inlet" and "__outlet" objects are renamed to "inlet" and "outlet", for clarity. An optional recursive argument includes all subgraphs. """ c: Counter = Counter() for o in self.objs.values(): if o.type == "__graph" and recursive: c += o.get_object_counter(recursive=True) elif o.type in {"__inlet", "__outlet"}: c[o.type[2:]] += 1 # remove leading "__" else: c[o.type] += 1 return c def prepare(self) -> None: """ Prepares a graph to be exported. Must be called from a root graph. """ assert self.is_root_graph() try: # apply graph transformations when all graphs have been read # All transformations must be recursive. # resolve all connection types such that all HeavyLang objects can # be correctly reduced self._resolve_connection_types() # TODO(mhroth): prune unnecessary objects and connections # All unnecessary objects and connections should be removed before the # graph is reduced. Reduction generally takes into account the existence # of connections when deciding on what HeavyIR objects to used. self._remove_unused_inlet_connections() # reconnect all send~/receive~ objects and remove them from the graph self.remap_send_receive() # now that the basic graph has been constructed, # objects are reduced to their well-defined low-level types. # Some objects may be replaced by graphs containing only low-level objects. # The graph is changed in-place and consists of only low-level # objects and subgraphs. All invalid connections are pruned. self.reduce() # +~~ expansion # ensures that there is at most one signal connection at any inlet self.cascade_expansion() # fma replacement # convert [__mul~f ~f> __add~f] into [__fma~f] self.fma_replacement() # group all control receivers with the same name under one logical receiver self.group_control_receivers() # assign signal buffers to signal objects # Buffer assignment only takes place at the very end, # and does so recursively over all objects and subgraphs. # All objects are ordered before buffers are assigned. self.assign_signal_buffers() except HeavyException as e: e.notes = self.get_notices() e.notes.has_error = True e.notes.exception = e raise e def _remove_unused_inlet_connections(self) -> None: """ Remove connections from inlet object, if there are no incoming connections to it. This is a basic approach to pruning unused or unnecessary connections, which allow further optimisation later in the pipeline. """ for i, cc in enumerate(self.inlet_connections): if len(cc) == 0: # make copy of outlet_connections list because it will be changed for c in list(self.inlet_objs[i].outlet_connections[0]): self.disconnect_objects(c) # the recursive bit for o in [o for o in self.objs.values() if (o.type == "__graph")]: o._remove_unused_inlet_connections() def _resolved_outlet_type(self, outlet_index: int = 0) -> LangLetType: # a graph's outlet type depends on the connections incident on the # corresponding outlet object connection_type_set = {c.type for c in self.outlet_objs[outlet_index].inlet_connections[0]} if len(connection_type_set) == 0: return "-->" # object has no incident connections, default to --> elif len(connection_type_set) == 1: return list(connection_type_set)[0] else: raise HeavyException(f"{self} has multiple incident connections of differing type.\ The outlet type cannot be explicitly resolved.") def _resolve_connection_types(self, obj_stack: Optional[set] = None) -> None: """ Resolves the type of all connections before reduction to IR object types. If connections incident on an object are incompatible, they are either resolved, potentially by inserting conversion objects, or pruned. If a viable resolution cannot be found, an exception may be raised. """ obj_stack = obj_stack or set() if self in obj_stack: return # ensure that each object is only resolved once (no infinite loops) else: obj_stack.add(self) # start from all roots and resolve all connections downwards for o in [o for o in self.objs.values() if o.is_root()]: o._resolve_connection_types(obj_stack) # when all internal connections have been resolved, # continue the recursion and resolve all outgoing connections for c in [c for cc in self.outlet_connections for c in cc]: if c.is_mixed: # resolve connection type and update it connection_type = self._resolved_outlet_type(c.outlet_index) self.update_connection(c, [c.copy(type=connection_type)]) c.to_object._resolve_connection_types(obj_stack) # turtle on down def remap_send_receive(self) -> None: """ Recursively finds all signal send/receive objects and for each unique send name, get all of the sends, and all of the corresponding receives. Reconnect all incoming connections to a __add~f, and fan out the results to all of receivers' connections. At most one __add~f must be added, and a lot of connections remapped. """ sends_dict = self.local_vars.get_registered_objects_for_type("send") receives_dict = self.local_vars.get_registered_objects_for_type("receive") for (name, send_objs) in sends_dict.items(): # unconnected send/receives will be removed in the reduce step, # if necessary (depending on control or signal functionality). # All signal sends will also be removed, regardless of whether they # have corresponding receives or not. So here we really only need to # be concerned with connecting "normal" signal send/receives. # get all signal sends for a name s_list = [o for o in send_objs if o.has_inlet_connection_format("f")] # assume that all similarly named receives will also be signal format r_list = [o for o in receives_dict[name]] if len(s_list) == 0: continue # there are no signals going into this send elif len(s_list) == 1: s = s_list[0] c = s.inlet_connections[0][0] # the connection ir_var = HeavyIrObject("__var~f") ir_varset = HeavyIrObject("__varwrite~f", {"var_id": ir_var.id}) s.graph.add_object(ir_var) s.graph.add_object(ir_varset) # move all connection to send object, to ir_varset for c in list(s.inlet_connections[0]): s.graph.update_connection(c, [c.copy(to_object=ir_varset)]) # move connections from receivers, to be from __var~f for o in r_list: ir_varread = HeavyIrObject("__varread~f", {"var_id": ir_var.id}) o.graph.add_object(ir_varread) for x in list(o.outlet_connections[0]): o.graph.update_connection(x, [x.copy(from_object=ir_varread)]) else: ir_vars = [HeavyIrObject("__var~f") for s in s_list] for i, o in enumerate(s_list): ir_varset = HeavyIrObject("__varwrite~f", {"var_id": ir_vars[i].id}) o.graph.add_object(ir_vars[i]) o.graph.add_object(ir_varset) for c in list(o.inlet_connections[0]): o.graph.update_connection(c, [c.copy(to_object=ir_varset, inlet_index=0)]) for r in r_list: ir_add = HeavyIrObject("__add~f") r.graph.add_object(ir_add) for i, s in enumerate(s_list): ir_varread = HeavyIrObject("__varread~f", {"var_id": ir_vars[i].id}) r.graph.add_object(ir_varread) r.graph.connect_objects(Connection( from_object=ir_varread, outlet_index=0, to_object=ir_add, inlet_index=(0 if i == 0 else 1), conn_type="~f>" )) for c in list(r.outlet_connections[0]): r.graph.update_connection(c, [c.copy(from_object=ir_add)]) # when all is said and done, remove the send and receive objects for o in s_list: o.graph.remove_object(o) for o in r_list: o.graph.remove_object(o) def reduce(self) -> Tuple[Set, List]: """ Breaks this object into low-level objects. This method returns either the object that it is called on, or a graph. In case of a graph, it contains only low-level objects. Unnecessary connections are pruned. Because this method is called on graphs while they are being constructed, returned graphs contains no sub-graphs. Thus this method does not process subgraphs. """ # refactor all constituent objects for (obj_id, o) in self.objs.copy().items(): # use items and not iteritems so that object dictionary remains mutable # break the object into atomic (i.e. low-level) objects and # update connections. Replace the new representation with the old # one in the graph. objects, connections = o.reduce() # if x is the original object (the case with low-level objects), # then no change must be made if (len(objects) == 1) and (o in objects): continue # add the new objects for x in objects: self.add_object(x) # replace existing connections # control connection order is maintained for c in connections: # c is a tuple containing the old and new connections # the new connection is a possibly empty list of new connections, # indicating that there is no replacement self.update_connection(c[0], c[1]) # remove the old object (and any remaining connections) from the graph self.remove_object(o, obj_id=obj_id) # o.id may not be the same as obj_id if the object comes from an abstraction # a graph is reduced in-place and does not change any connections return ({self}, []) def cascade_expansion(self) -> None: """ Turns implicit +~ into explicit cascading +~ trees. It is assumed that this simplification operation is run on a reduced graph. """ for o in self.objs.copy().values(): # all items in the graph for i in range(len(o.inlet_connections)): # for each inlet # if there is more than one signal connection # get all of the signal connections to an object at this inlet cc = [c for c in o.inlet_connections[i] if c.is_signal] if len(cc) > 1: oL = HeavyIrObject("__add~f") self.add_object(oL) self.update_connection( cc[0], [Connection.copy(cc[0], to_object=oL, inlet_index=0)]) self.update_connection( cc[1], [Connection.copy(cc[1], to_object=oL, inlet_index=1)]) for j in range(2, len(cc)): x = HeavyIrObject("__add~f") self.add_object(x) self.connect_objects(Connection( from_object=oL, outlet_index=0, to_object=x, inlet_index=0, conn_type="~f>")) self.update_connection( cc[j], [Connection.copy(cc[j], to_object=x, inlet_index=1)]) oL = x # add a connection from the last +~ to this inlet self.connect_objects(Connection( from_object=oL, outlet_index=0, to_object=o, inlet_index=i, conn_type="~f>")) if o.type == "__graph": o.cascade_expansion() def fma_replacement(self) -> None: """ Replace: [__mul~f] ~f> [__add~f] with [__fma~f] or [__mul~f] ~f> [__sub~f] with [__fms~f] """ # for all __mul~f objects for o in self.objs.copy().values(): if o.type == "__mul~f" \ and len(o.inlet_connections[0]) == 1 \ and len(o.inlet_connections[1]) == 1 \ and len(o.outlet_connections[0]) == 1 \ and (o.outlet_connections[0][0].to_object.type == "__add~f" or (o.outlet_connections[0][0].to_object.type == "__sub~f" and o.outlet_connections[0][0].inlet_index == 0)) \ and len(o.outlet_connections[0][0].to_object.inlet_connections[0]) == 1 \ and len(o.outlet_connections[0][0].to_object.inlet_connections[1]) == 1 \ and len(o.outlet_connections[0][0].to_object.outlet_connections[0]) > 0: fma_type = "__fma~f" if o.outlet_connections[0][0].to_object.type == "__add~f" else "__fms~f" fma = HeavyIrObject(fma_type) self.add_object(fma) # move connection to left inlet of fma~ c = o.inlet_connections[0][0] self.update_connection(c, [c.copy(to_object=fma)]) # move connection to right inlet of fma~ c = o.inlet_connections[1][0] self.update_connection(c, [c.copy(to_object=fma)]) o_add = o.outlet_connections[0][0].to_object # move connection to third inlet of fma~ from +~ (not connected to *~) i = o.outlet_connections[0][0].inlet_index # i is either 0 or 1 # i ^ 1 # use the other inlet; 0 > 1, 1 > 0 c = o_add.inlet_connections[i ^ 1][0] self.update_connection(c, [c.copy(to_object=fma, inlet_index=2)]) # move all +~ outlet connections to fma~ outlet for c in o_add.outlet_connections[0]: self.connect_objects(c.copy(from_object=fma)) # remove old *~ and +~ objects from the graph # (along with any remaining connections) o.graph.remove_object(o) # *~ o_add.graph.remove_object(o_add) # +~ elif o.type == "__graph": o.fma_replacement() # recurse through all subgraphs def group_control_receivers(self) -> None: """ Group all control receivers with the same name under one receiver with that name. This way only one message must be scheduled to hit all receivers. """ for name, receivers in self.local_vars.get_registered_objects_for_type("__receive").items(): # ensure that all receiver arguments are consistent extern = list(set([r.args["extern"] for r in receivers]) - set([None])) attributes = [r.args["attributes"] for r in receivers if len(r.args["attributes"]) > 0] scope = list(set([r.annotations["scope"] for r in receivers])) if len(extern) > 1: self.add_error(f"Parameter \"{name}\" has conflicting extern types: {extern[0]} != {extern[1]}") # NOTE(mhroth): not checking for conflicting scope types right now. Not sure what to do with it. if not all(attributes[0] == a for a in attributes): self.add_error(f"Conflicting min/max/default values for parameter \"{name}\"") # create a new receiver recv = HIrReceive("__receive", args={ "name": name, "extern": extern[0] if len(extern) > 0 else None, "attributes": attributes[0] if len(attributes) > 0 else {}, }, annotations={"scope": scope[0]}) # add new receiver to the top level graph self.add_object(recv) # sort receivers by priority receivers.sort(key=lambda x: x.args["priority"], reverse=True) # move all connections to new receiver for r in receivers: for c in r.outlet_connections[0]: self.connect_objects(c.copy(from_object=recv), require_intra_graph_connection=False) # remove old receivers for r in receivers: r.graph.remove_object(r) @property def does_process_signal(self) -> bool: # this graph processes a signal if it contains any adc~ (__inlet # objects with index > 127) return any(o.does_process_signal for o in self.objs.values()) or \ any(o.args["index"] > 127 for o in self.inlet_objs) def order_signal_objects(self) -> None: """ Places the signal objects in the correct order to be processed. Only the objects in this graph are ordered, stopping at the inlet objects. """ # for all leaves of graph, get the parent objects and combine the lists self.signal_order = [] # ordered objects for o in [o for o in self.objs.values() if o.is_leaf()]: self.signal_order.extend(o.get_parent_order()) # retain only objects that process a signal self.signal_order = [o for o in self.signal_order if o.does_process_signal] def assign_signal_buffers(self, buffer_pool: Optional[BufferPool] = None) -> None: # the top-level graph owns the buffer pool if buffer_pool is not None: self.buffer_pool = buffer_pool else: self.buffer_pool = BufferPool() # before signal buffers can be assigned, the objects must be ordered self.order_signal_objects() for c_list in self.inlet_connections: c_list = [c for c in c_list if c.is_signal] # only consider signal connections to inlet if len(c_list) == 0: continue # no connections at this inlet, it already contains the zero buffer if len(c_list) == 1: c = c_list[0] # get the connection # get the buffer at the outlet of the connected object buf = c.from_object.outlet_buffers[c.outlet_index] # assign the buffer to the outlet of the corresponding inlet object inlet_obj = self.inlet_objs[c.inlet_index] inlet_obj.outlet_buffers[0] = buf # ensure that the retain count is accurately reflected by the inlet's connections # some inlets are mixed with both signal and control connections, count only the signal connections self.buffer_pool.retain_buffer(buf, len([c for c in inlet_obj.outlet_connections[0] if c.is_signal]) - 1) else: raise HeavyException( f"Object {inlet_obj} in graph {inlet_obj.graph.file} has {len(c_list)} (> 1) signal inputs.") # for all objects in the signal order for o in self.signal_order: o.assign_signal_buffers(self.buffer_pool) # assign the output buffers for i, outlet_obj in enumerate(self.outlet_objs): # only assign signal buffers to outlets that have incoming signal connections c_list = [c for c in outlet_obj.inlet_connections[0] if c.is_signal] if len(c_list) == 0: continue if len(c_list) == 1: c = c_list[0] # get the connection buf = c.from_object.outlet_buffers[c.outlet_index] self.outlet_buffers[i] = buf self.buffer_pool.retain_buffer(buf, len(self.outlet_connections[i]) - 1) else: raise HeavyException( f"Object {outlet_obj} in graph {outlet_obj.graph.file} has {len(c_list)} (> 1) signal inputs.") def __repr__(self) -> str: if self.xname is not None: # TODO(mhroth): does not handle nested subgraph return f"__graph.{self.id}({os.path.basename(self.file)}/{self.xname})" else: return f"__graph.{self.id}({os.path.basename(self.file)})" # # Intermediate Representation generators # def to_ir(self) -> Optional[IRGraph]: """ Returns Heavy intermediate representation. """ # the set of all input/output signal channels used by the graph input_channel_set = self.get_input_channel_set(recursive=True) output_channel_set = self.get_output_channel_set(recursive=True) if self.buffer_pool is not None: return IRGraph( name=IRName( escaped=re.sub(r"\W", "_", self.xname), display=self.xname ), objects=self.get_object_dict(), init=IRInit( order=self.get_ir_init_list() ), tables=self.get_ir_table_dict(), control=IRControl( receivers=self.get_ir_receiver_dict(), sendMessage=self.get_ir_control_list() ), signal=IRSignal( numInputBuffers=max(input_channel_set) if len(input_channel_set) > 0 else 0, numOutputBuffers=max(output_channel_set) if len(output_channel_set) > 0 else 0, numTemporaryBuffers=IRNumTempBuffer( float=self.buffer_pool.num_buffers("~f>"), integer=self.buffer_pool.num_buffers("~i>") ), processOrder=self.get_ir_signal_list() ) ) else: # we should never get here raise Exception def get_object_dict(self) -> Dict[str, IRObjectdict]: # d = {o.id: o.get_object_dict() for o in self.objs.values() if o.type not in # ["inlet", "__inlet", "outlet", "__outlet"]} d = {} for o in self.objs.values(): # NOTE(mhroth): a bit of a hack to remove unnecessary inlet and outlet ir objects if o.type not in ["inlet", "__inlet", "outlet", "__outlet"]: d.update(o.get_object_dict()) return d def get_ir_init_list(self) -> List[str]: """ Init list is returned with all signal objects at the front, in the order that they are processed. This is to reduce cache misses on the signal object state as the process function is executed. """ init_list = [x for o in self.objs.values() for x in o.get_ir_init_list()] signal_list = self.get_ir_signal_list() s_init_list = [x.id for x in signal_list if x.id in init_list] i_init_list = [o_id for o_id in init_list if o_id not in s_init_list] ordered_init_list = s_init_list + i_init_list # ordered_init_list = list(OrderedDict.fromkeys(s_init_list + i_init_list)) return ordered_init_list def get_ir_on_message(self, inlet_index: int = 0) -> List[IROnMessage]: # pass the method through the inlet object, but only follow control connections x = [] for c in self.inlet_objs[inlet_index].outlet_connections[0]: if c.is_control: x.extend(c.to_object.get_ir_on_message(c.inlet_index)) return x def get_ir_table_dict(self) -> Dict[str, IRTable]: """ Returns a dictionary of all publicly visible tables at the root graph and their ids. """ assert self.is_root_graph(), "This function should only be called from the root graph." d = self.local_vars.get_registered_objects_for_type("__table") # update(), because tables can be registered either as Heavy tables # or HeavyIr __tables. We need to be able to handle them both. d.update(self.local_vars.get_registered_objects_for_type("table")) e = {} for k, v in d.items(): # escape table key to be used as the value for code stubs key = (f"_{k}") if re.match(r"\d", k) else k if key not in e: e[key] = IRTable( id=v[0].id, display=k, hash=f"0x{HeavyLangObject.get_hash(k):X}", extern=v[0].args["extern"] ) return e def get_ir_control_list(self) -> List[IRSendMessage]: return [x for o in self.objs.values() for x in o.get_ir_control_list()] def get_ir_receiver_dict(self) -> Dict[str, IRReceiver]: # NOTE(mhroth): this code assumes that v is always an array of length 1, # as the grouping of control receivers should have grouped all same-named # receivers into one logical receiver. # NOTE(mhroth): a code-compatible name is only necessary for externed receivers return {((f"_{k}") if re.match(r"\d", k) else k): IRReceiver( display=k, hash=f"0x{HeavyLangObject.get_hash(k):X}", extern=v[0].args["extern"], attributes=v[0].args["attributes"], ids=[v[0].id] ) for k, v in self.local_vars.get_registered_objects_for_type("__receive").items()} def get_ir_signal_list(self) -> List[IRSignalList]: return [x for o in self.signal_order for x in o.get_ir_signal_list()] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.260823 hvcc-0.13.3/hvcc/core/hv2ir/HeavyIrObject.py0000644000000000000000000002451614735300474015443 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import json import os from typing import Dict, List, Optional, TYPE_CHECKING from .Connection import Connection from .HeavyException import HeavyException from .HeavyLangObject import HeavyLangObject from .BufferPool import BufferPool from hvcc.types.IR import HeavyIRType, IRNode, IRObjectdict, IRSendMessage, IROnMessage, IRSignalList, IRBuffer from hvcc.types.Lang import LangLetType if TYPE_CHECKING: from .HeavyGraph import HeavyGraph class HeavyIrObject(HeavyLangObject): """ Intermediate Representation (IR) objects are atomic and have strictly defined interfaces and types. These are generally defined in the file heavy.ir.json. """ # load the HeavyIR object definitions with open(os.path.join(os.path.dirname(__file__), "../json/heavy.ir.json"), "r") as f: __HEAVY_OBJS_IR_DICT = HeavyIRType(**json.load(f)).root def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional['HeavyGraph'] = None, num_inlets: int = -1, num_outlets: int = -1, annotations: Optional[Dict] = None ) -> None: # allow the number of inlets and outlets to be overridden num_inlets = (len(self.__HEAVY_OBJS_IR_DICT[obj_type].inlets) if num_inlets < 0 else num_inlets) num_outlets = (len(self.__HEAVY_OBJS_IR_DICT[obj_type].outlets) if num_outlets < 0 else num_outlets) super().__init__(obj_type, args, graph, num_inlets, num_outlets, annotations) # resolve arguments and fill in missing defaults for HeavyIR objects self.__resolve_default_ir_args() # the list of signal buffers at the inlets and outlets # these are filled in by HeavyGraph.assign_signal_buffers() self.inlet_buffers = [("zero", 0)] * self.num_inlets self.outlet_buffers = [("zero", 0)] * self.num_outlets # True if this object has already been ordered in the signal chain self.__is_ordered = False def __resolve_default_ir_args(self) -> None: """ Resolves missing default arguments. Also checks to make sure that all required arguments are present. """ if self.type in self.__HEAVY_OBJS_IR_DICT.keys(): for arg in self.__obj_desc.args: if arg.name not in self.args: # if a defined argument is not in the argument dictionary if not arg.required: # if the argument is not required, use the default self.args[arg.name] = arg.default else: self.add_error(f"Required argument \"{arg.name}\" not present for object {self}.") else: # enforce argument types. # if the default argument is null, don't worry about about the arg if arg.default is not None: self.args[arg.name] = self.force_arg_type( self.args[arg.name], arg.value_type, self.graph) @classmethod def is_ir(cls, obj_type: str) -> bool: """Returns true if the type is an IR object. False otherwise. """ return obj_type in cls.__HEAVY_OBJS_IR_DICT.keys() @property def does_process_signal(self) -> bool: """Returns True if this object processes a signal. False otherwise. """ return self.__obj_desc.ir.signal @property def __obj_desc(self) -> IRNode: """ Returns the original HeavyIR object description. """ return self.__HEAVY_OBJS_IR_DICT[self.type] def inlet_requires_signal(self, inlet_index: int = 0) -> bool: """ Returns True if the indexed inlet requires a signal connection. False otherwise. """ return self.__obj_desc.inlets[inlet_index] in {"~i>", "~f>"} def outlet_requires_signal(self, inlet_index: int = 0) -> bool: """ Returns True if the indexed outlet requires a signal connection. False otherwise. """ return self.__obj_desc.outlets[inlet_index] in {"~i>", "~f>"} def reduce(self) -> Optional[tuple]: # A Heavy IR object is already reduced. Returns itself and no connection changes. return ({self}, []) def get_parent_order(self) -> List: """ Returns a list of all objects in process order, with this object at the end. """ if self.__is_ordered: return [] else: self.__is_ordered = True if self.is_root(): return [self] else: order_list = [] for c in [c for inlet in self.inlet_connections for c in inlet]: order_list.extend(c.from_object.get_parent_order()) order_list.append(self) return order_list def assign_signal_buffers(self, buffer_pool: Optional[BufferPool]) -> None: if buffer_pool is not None: # assign the inlet buffers for cc in self.inlet_connections: cc = [c for c in cc if c.is_signal] # only need to deal with signal connections if len(cc) == 0: continue if len(cc) == 1: c = cc[0] # get the connection # get the buffer at the outlet of the connected object buf = c.from_object.outlet_buffers[c.outlet_index] # assign the buffer to the inlet of this object self.inlet_buffers[c.inlet_index] = buf # decrease the retain count of the buffer buffer_pool.release_buffer(buf) else: raise HeavyException(f"This object has {len(cc)} (> 1) signal inputs.") # assign the output buffers exclude_set: set = set() for i in range(self.num_outlets): # buffers are assigned even if the outlet has no connections. # The buffer will still be filled. However, if the buffer has already # been set (i.e. non-zero) (e.g. in the case of dac~), # then we skip this set connection_type = self._resolved_outlet_type(outlet_index=i) if Connection.is_signal_type(connection_type) and self.outlet_buffers[i][0] == "zero" \ and connection_type is not None: b = buffer_pool.get_buffer( connection_type, len(self.outlet_connections[i]), exclude_set) self.outlet_buffers[i] = b # if the buffer has no dependencies, make sure that it isn't reused # right away. All outlets should have independent buffers. if len(self.outlet_connections[i]) == 0: exclude_set.add(b) def _resolved_outlet_type(self, outlet_index: int = 0) -> Optional[LangLetType]: """ Returns the connection type at the given outlet. This information is always well-defined for IR objects. """ return self.__obj_desc.outlets[outlet_index] # # Intermediate Representation generators # def get_object_dict(self) -> Dict[str, IRObjectdict]: """ Returns a dictionary of all constituent low-level objects, indexed by id, including their arguments and type. """ return { self.id: IRObjectdict( args=self.args, type=self.type ) } def get_ir_init_list(self) -> List[str]: """ Returns a list of all object id for obejcts that need initialisation. """ return [self.id] if self.__obj_desc.ir.init else [] def get_ir_on_message(self, inlet_index: int = 0) -> List[IROnMessage]: """ Returns an array of dictionaries containing the information for the corresponding on_message call. """ return [IROnMessage( id=self.id, inletIndex=inlet_index )] def get_ir_control_list(self) -> List[IRSendMessage]: """ Returns the intermediate representation for object control functions. Basically, does sendMessage() need to be written? """ if self.__obj_desc.ir.control: on_message_list = [] for connections in self.outlet_connections: on_messages_let = [] # only look at control connections for c in [c for c in connections if c.is_control]: on_messages_let.extend(c.to_object.get_ir_on_message(c.inlet_index)) on_message_list.append(on_messages_let) return [IRSendMessage( id=self.id, onMessage=on_message_list )] else: return [] def get_ir_signal_list(self) -> List[IRSignalList]: """ Returns the intermediate representation for object process functions. Only outputs buffer information for lets that require a signal. """ # we assume that this method will only be called on signal objects assert self.__obj_desc.ir.signal return [IRSignalList( id=self.id, inputBuffers=[ IRBuffer(type=b[0], index=b[1]) for i, b in enumerate(self.inlet_buffers) if self.inlet_requires_signal(i) ], outputBuffers=[ IRBuffer(type=b[0], index=b[1]) for i, b in enumerate(self.outlet_buffers) if self.outlet_requires_signal(i) ] )] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.260823 hvcc-0.13.3/hvcc/core/hv2ir/HeavyLangObject.py0000644000000000000000000004126614735300474015753 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import decimal import json import os import random import string from struct import unpack, pack from typing import Optional, Union, List, Dict, Any, TYPE_CHECKING from .Connection import Connection from .HeavyException import HeavyException from hvcc.types.compiler import CompilerMsg, CompilerNotif from hvcc.types.Lang import HeavyLangType, LangNode, LangLet, LangLetType, LangValueType if TYPE_CHECKING: from .HeavyGraph import HeavyGraph from .HeavyIrObject import HeavyIrObject class HeavyLangObject: """ This is the base Heavy object class. """ __RANDOM = random.Random() __ID_CHARS = string.ascii_letters + string.digits # load the Heavy object definitions with open(os.path.join(os.path.dirname(__file__), "../json/heavy.lang.json"), "r") as f: _HEAVY_LANG_DICT = HeavyLangType(**json.load(f)).root def __init__( self, obj_type: str, args: Optional[Dict] = None, graph: Optional['HeavyGraph'] = None, num_inlets: int = -1, num_outlets: int = -1, annotations: Optional[Dict] = None ) -> None: # set the object type self.type = obj_type # generate a unique id for this object self.id = "".join(self.__RANDOM.choice(self.__ID_CHARS) for _ in range(8)) # assign the parent graph self.graph = graph # set local arguments self.args: Dict = args or {} # set local annotations self.annotations: Dict = annotations or {} # a list of locally generated warnings and errors (notifications) self.warnings: List[CompilerMsg] = [] self.errors: List[CompilerMsg] = [] # resolve arguments and fill in missing defaults for HeavyLang objects self.__resolve_default_lang_args() # the list of connections at each inlet num_inlets = num_inlets if num_inlets >= 0 else len(self._obj_desc.inlets) self.inlet_connections: List = [[] for _ in range(num_inlets)] # the list of connections at each outlet num_outlets = num_outlets if num_outlets >= 0 else len(self._obj_desc.outlets) self.outlet_connections: List = [[] for _ in range(num_outlets)] @property def scope(self) -> str: """ Returns the scope of this object, private by default. Scope may be public, protected, private. """ return self.annotations.get("scope", "private") @property def static(self) -> bool: """ Returns true of this object is marked as static. False by default. """ return self.annotations.get("static", False) @property def const(self) -> bool: """ Returns true of this object is marked as constant. False by default. """ return self.annotations.get("const", False) @property def name(self) -> Optional[str]: """ Returns the name of this object. Returns None if there is no name. """ return self.args.get("name", None) @property def _obj_desc(self) -> LangNode: """ Returns the HeavyLang object description. """ return self._HEAVY_LANG_DICT[self.type] def inlet_connection_type(self, index: int) -> LangLet: return self._obj_desc.inlets[index] def outlet_connection_type(self, index: int) -> LangLet: return self._obj_desc.outlets[index] def name_for_arg(self, index: int = 0) -> str: """ Returns the name of the argument at the given index. """ return self._obj_desc.args[index].name def add_warning(self, warning: str) -> None: """ Add a warning to this object. """ self.warnings.append(CompilerMsg(message=warning)) def add_error(self, error: str) -> None: """ Add an error to this object and raise an exception. """ self.errors.append(CompilerMsg(message=error)) raise HeavyException(error) def get_notices(self) -> CompilerNotif: """ Returns a dictionary of all warnings and errors at this object. """ return CompilerNotif( has_error=len(self.errors) > 0, warnings=[CompilerMsg(message=f"{self}: {n.message}") for n in self.warnings], errors=[CompilerMsg(message=f"{self}: {n.message}") for n in self.errors], ) @classmethod def force_arg_type( cls, value: LangValueType, value_type: Optional[str] = None, graph: Optional['HeavyGraph'] = None ) -> Any: """ Attempts to convert a value to a given value type. Raises an Exception otherwise. If the value_type is unknown and a graph is provided, a warning will be registered. """ if value_type == "float": try: return float(value) except Exception: raise Exception(f"Cannot convert argument \"{value}\" into float.") elif value_type == "int": return int(decimal.Decimal(value)) elif value_type == "string": return str(value) if value is not None else None elif value_type == "bool": if isinstance(value, str): return value.strip().lower() not in ["false", "f", "0"] else: return bool(value) elif value_type == "floatarray": if isinstance(value, list): return [float(v) for v in value] if isinstance(value, str): return [float(v) for v in value.split()] else: raise HeavyException(f"Cannot convert value to type floatarray: {value}") elif value_type == "intarray": if isinstance(value, list): return [int(v) for v in value] if isinstance(value, str): return [int(v) for v in value.split()] else: raise HeavyException(f"Cannot convert value to type intarray: {value}") elif value_type == "stringarray": if isinstance(value, list): return [str(v) for v in value] if isinstance(value, str): return [str(v) for v in value.split()] else: raise HeavyException(f"Cannot convert value to type stringarray: {value}") else: # NOTE(mhroth): if value_type is not a known type or None, that is # not necessarily an error. It may simply be that the value should # not be resolved to anything other than what it already is. # This happens most often with message objects. # if graph is not None: # graph.add_warning(f"Unknown value type \"{value_type}\" for value: {value}") return value def __resolve_default_lang_args(self) -> None: """ Resolves missing default arguments. Also checks to make sure that all required arguments are present. Does nothing if the object is IR. """ if self.type in self._HEAVY_LANG_DICT.keys(): for arg in self._obj_desc.args: if arg.name not in self.args: # if a defined argument is not in the argument dictionary if not arg.required: # if the argument is not required, use the default self.args[arg.name] = arg.default else: self.add_error(f"Required argument \"{arg.name}\" not present for object {self}.") else: # enforce argument types self.args[arg.name] = self.force_arg_type( self.args[arg.name], arg.value_type, self.graph) @property def num_inlets(self) -> int: return len(self.inlet_connections) @property def num_outlets(self) -> int: return len(self.outlet_connections) def add_connection(self, c: Connection) -> None: """ Add a connection to this object. """ try: if c.to_object is self: self.inlet_connections[c.inlet_index].append(c) elif c.from_object is self: self.outlet_connections[c.outlet_index].append(c) else: raise HeavyException(f"Connection {c} does not connect to this object {self}.") except Exception: raise HeavyException(f"Connection {c} connects to out-of-range let.") def remove_connection(self, c: Connection) -> None: """ Remove a connection to this object. """ if c.to_object is self: self.inlet_connections[c.inlet_index].remove(c) elif c.from_object is self: self.outlet_connections[c.outlet_index].remove(c) else: raise HeavyException(f"Connection {c} does not connect to this object {self}.") def replace_connection(self, c: Connection, n_list: List) -> None: """ Replaces connection c with connection list n_list, maintaining connection order """ if c.from_object is self: cc = self.outlet_connections[c.outlet_index] # NOTE(mhroth): this will throw an exception if c does not exist # if a heavy object connects to itself, such as through a [t a] # or directly, there may be an error here, i = cc.index(c) self.outlet_connections[c.outlet_index] = cc[0:i] + n_list + cc[i + 1:] elif c.to_object is self: # connection order doesn't matter at the inlet self.inlet_connections[c.inlet_index].remove(c) self.inlet_connections[c.inlet_index].extend(n_list) else: raise HeavyException(f"Connections must have a common endpoint: {c} / {n_list}") def get_connection_move_list(self, o: 'HeavyIrObject', connection_type_filter: str = "-~>") -> List: """ Create a list of commands to move all connections from this object to the given object o. """ m = [] for c in [c for cc in self.inlet_connections for c in cc]: m.append((c, [c.copy(to_object=o)])) for c in [c for cc in self.outlet_connections for c in cc]: m.append((c, [c.copy(from_object=o)])) return m def _get_connection_format(self, connections_list: List) -> str: fmt = [] for cc in connections_list: s = {c.type for c in cc} if len(s) == 0: fmt.append("_") elif len(s) == 1: if "-->" in s: fmt.append("c") elif "~f>" in s: fmt.append("f") elif "~i>" in s: fmt.append("i") else: raise Exception(f"Unknown connection type in set {cc} in file {cc[0].from_object.graph.file}.") elif s in [{"~f>", "-->"}, {"~i>", "-->"}]: fmt.append("m") else: fmt.append("m") return "".join(fmt) def has_inlet_connection_format(self, fmts: Optional[Union[str, List]] = None) -> bool: """ Returns true if the object has given format at its inlets. """ fmts = fmts if isinstance(fmts, list) else [fmts] return self._get_connection_format(self.inlet_connections) in fmts def has_outlet_connection_format(self, fmts: Optional[Union[str, List]] = None) -> bool: """ Returns true if the object has given format at its outlets. Take either litteral or list as input. """ fmts = fmts if isinstance(fmts, list) else [fmts] return self._get_connection_format(self.outlet_connections) in fmts def is_leaf(self) -> bool: """ Returns True if this object is a leaf in the graph. False otherwise. """ return all(len(c) == 0 for c in self.outlet_connections) def is_root(self) -> bool: """ Returns True if this object is a root in the graph. False otherwise. """ return all(len(c) == 0 for c in self.inlet_connections) def _resolved_outlet_type(self, outlet_index: int = 0) -> Optional[LangLetType]: """ Returns the connection type expected at the given outlet. The result may be influenced by the state of the input connections. """ # get the defined connection type connection_type = self._obj_desc.outlets[outlet_index].connectionType if connection_type == "-~>" and self.graph is not None: # if the connection type is defined as mixed, # use the default approach to resolve it connection_type_set = {c.type for c in self.inlet_connections[0]} if len(connection_type_set) == 0: return "-->" elif len(connection_type_set) == 1: return list(connection_type_set)[0] elif len(connection_type_set) == 2: if {"-->", "~f>"} == connection_type_set: return "~f>" elif {"-->", "~i>"} == connection_type_set: return "~i>" # if the connection type cannot be resolved to a well-defined type self.graph.add_error("Connection type cannot be resolved." f"Unknown inlet connection type configuration: {connection_type_set}") else: return connection_type return None def _resolve_connection_types(self, obj_stack: Optional[set] = None) -> None: """ Resolves the type of all connections before reduction to IR object types. If connections incident on an object are incompatible, they are either resolved, potentially by inserting conversion objects, or pruned. If a viable resolution cannot be found, an exception may be raised. """ obj_stack = obj_stack or set() if self in obj_stack: return else: obj_stack.add(self) # for all outgoing connections if self.graph is not None: for c in [c for cc in self.outlet_connections for c in cc]: if c.is_mixed: connection_type = self._resolved_outlet_type(outlet_index=c.outlet_index) if connection_type == "-~>": self.graph.add_error("Cannot resolve connection type from -~>.") else: self.graph.update_connection(c, [c.copy(type=connection_type)]) c.to_object._resolve_connection_types(obj_stack) # turtle all the way down @classmethod def get_hash(cls, x: str) -> int: """ Compute the message element hash used by msg_getHash(). Returns a 32-bit integer. """ if isinstance(x, float) or isinstance(x, int): # interpret the float bytes as an unsigned integer return unpack("@I", pack("@f", float(x)))[0] elif x == "bang": return 0xFFFFFFFF elif isinstance(x, str): # this hash is based MurmurHash2 # http://en.wikipedia.org/wiki/MurmurHash # https://sites.google.com/site/murmurhash/ x = str(x) m = 0x5bd1e995 r = 24 h = len(x) i = 0 while i < len(x) & ~0x3: k = unpack("@I", bytes(x[i:i + 4], "utf-8"))[0] k = (k * m) & 0xFFFFFFFF k ^= k >> r k = (k * m) & 0xFFFFFFFF h = (h * m) & 0xFFFFFFFF h ^= k i += 4 n = len(x) & 0x3 x = x[i:i + n] if n >= 3: h ^= (ord(x[2]) << 16) & 0xFFFFFFFF if n >= 2: h ^= (ord(x[1]) << 8) & 0xFFFFFFFF if n >= 1: h ^= ord(x[0]) h = (h * m) & 0xFFFFFFFF h ^= h >> 13 h = (h * m) & 0xFFFFFFFF h ^= h >> 15 return h else: raise Exception("Message element hashes can only be computed for float and string types.") def __repr__(self) -> str: arg_str = " ".join([f"{k}:{o}" for (k, o) in self.args.items()]) return f"{self.type} {{{arg_str}}}" if len(arg_str) > 0 else self.type ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735983617.1410897 hvcc-0.13.3/hvcc/core/hv2ir/HeavyParser.py0000644000000000000000000002702114736201001015153 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import json import random import os from typing import Any, Dict, List, Optional, Set, Tuple from .HIrConvolution import HIrConvolution from .HIrInlet import HIrInlet from .HIrLorenz import HIrLorenz from .HIrOutlet import HIrOutlet from .HIrPack import HIrPack from .HIrSwitchcase import HIrSwitchcase from .HIrTabhead import HIrTabhead from .HIrTabread import HIrTabread from .HIrTabwrite import HIrTabwrite from .HLangAdc import HLangAdc from .HLangBinop import HLangBinop from .HLangBiquad import HLangBiquad from .HLangDac import HLangDac from .HLangDelay import HLangDelay # from .HLangIf import HLangIf # circular import. moved here from .HeavyException import HeavyException from .HeavyIrObject import HeavyIrObject from .HeavyLangObject import HeavyLangObject from .HLangLine import HLangLine from .HLangMessage import HLangMessage # from .HLangNoise import HLangNoise # circular import. moved here from .HLangPhasor import HLangPhasor from .HLangPrint import HLangPrint from .HLangReceive import HLangReceive from .HLangRandom import HLangRandom from .HLangSend import HLangSend from .HLangSequence import HLangSequence from .HLangSlice import HLangSlice from .HLangSystem import HLangSystem from .HLangTable import HLangTable from .HLangUnop import HLangUnop from .HLangVar import HLangVar from .HLangVario import HLangVario from .HeavyGraph import HeavyGraph from .Connection import Connection class HeavyParser: @classmethod def graph_from_file( cls, hv_file: str, graph: Optional[HeavyGraph] = None, graph_args: Optional[Dict] = None, path_stack: Optional[set] = None, xname: Optional[str] = None ) -> HeavyGraph: """ Read a graph object from a file. @param graph The parent graph of this graph. @param graph_args The arguments to this graph, in the form of a completely resolved dictionary. @param path_stack The path_stack is the current stack of resolved abstractions. It prevents infinite recursion when reading many abstractions deep. """ # ensure that we have an absolute path to the hv_file hv_file = os.path.abspath(os.path.expanduser(hv_file)) # copy the path stack such that no changes are made to the calling stack path_stack = path_stack or set() if hv_file in path_stack: raise HeavyException(f"Abstraction recursion detected. Rereading {hv_file} on stack {path_stack}.") else: path_stack.add(hv_file) # open and parse the heavy file with open(hv_file, "r") as f: json_heavy = json.load(f) return cls.graph_from_object(hv_file, json_heavy, path_stack, graph, graph_args, xname) @classmethod def graph_from_object( cls, hv_file: str, json_heavy: Dict, path_stack: set, graph: Optional[HeavyGraph] = None, graph_args: Optional[Dict] = None, xname: Optional[str] = None ) -> HeavyGraph: """ Parse a graph object. @param graph The parent graph. @param graph_args The resolved arguments to this graph, in the form of a dictionary. @param hv_file The Heavy file where this graph can be found. """ # resolve default graph arguments graph_args = graph_args or {} for a in json_heavy["args"]: if a["name"] not in graph_args: if a["required"]: raise HeavyException(f"Required argument \"{a['name']}\" not present.") else: graph_args[a["name"]] = a["default"] else: # just to be safe, ensure that the argument type is correct graph_args[a["name"]] = HeavyLangObject.force_arg_type( graph_args[a["name"]], a["value_type"], graph=graph) # create a new graph subpatch_name = json_heavy.get("annotations", {}).get("name", xname) g = HeavyGraph(graph, graph_args, file=hv_file, xname=subpatch_name) # add the import paths to the global vars g.local_vars.add_import_paths(json_heavy.get("imports", [])) # add the file's relative directory to global vars g.local_vars.add_import_paths([os.path.dirname(hv_file)]) # instantiate all objects try: for obj_id, o in json_heavy["objects"].items(): if o["type"] == "comment": continue # first and foremost, ignore comment objects elif o["type"] == "graph": # inline HeavyGraph objects (i.e. subgraphs) # require a different set of initialisation arguments x: Any = cls.graph_from_object(hv_file, o, path_stack, g, g.args, xname) else: # resolve the arguments dictionary based on the graph args args = g.resolve_arguments(o["args"]) # before anything, search for an abstraction # in case we want to override default functionality # However, if we are in an abstraction that has the same # name as the type that we are looking for, don't recurse! abs_path = g.find_path_for_abstraction(o["type"]) if abs_path is not None and abs_path not in path_stack: x = cls.graph_from_file( hv_file=abs_path, graph=g, graph_args=args, path_stack=path_stack) # if we know how to handle this object type natively # either as a custom type or as a generic IR object elif HeavyParser.get_class_for_type(o["type"]) is not None: obj_cls = HeavyParser.get_class_for_type(o["type"]) x = obj_cls(o["type"], args, g, o.get("annotations", {})) # handle generic IR objects elif HeavyIrObject.is_ir(o["type"]): x = HeavyIrObject(o["type"], args, g, annotations=o.get("annotations", {})) # an object definition can't be found else: g.add_error(f"Object type \"{o['type']}\" cannot be found.") # note that add_error() raises an exception. So really, there is no continue. continue # add the new object to the graph's object dictionary g.add_object(x, obj_id) # parse all of the connections for c in json_heavy["connections"]: g.connect_objects(Connection( g.objs[c["from"]["id"]], c["from"]["outlet"], g.objs[c["to"]["id"]], c["to"]["inlet"], c["type"])) except HeavyException as e: if g.is_root_graph(): # add the notification dictionary at the top level e.notes = g.get_notices() e.notes.has_error = True e.notes.exception = e raise e if (g.graph is None) or (g.graph.file != g.file): # remove this graph from the stack when finished. # Subpatches should not remove themselves. path_stack.remove(g.file) return g @classmethod def get_class_for_type(cls, obj_type: str) -> Any: """ Returns the class which can handle the given object type. """ if HLangUnop.handles_type(obj_type): return HLangUnop elif HLangBinop.handles_type(obj_type): return HLangBinop elif obj_type in LANG_CLASS_DICT: return LANG_CLASS_DICT[obj_type] else: return None class HLangIf(HeavyLangObject): """ Translates HeavyLang object [if] to HeavyIR [if] or [if~]. """ def __init__( self, obj_type: str, args: Dict, graph: HeavyGraph, annotations: Optional[Dict] = None ) -> None: assert obj_type == "if" super().__init__("if", args, graph, num_inlets=2, num_outlets=2, annotations=annotations) def reduce(self) -> Tuple[Set, List]: if self.has_inlet_connection_format(["cc", "_c", "c_", "__"]): x = HeavyIrObject("__if", self.args) elif self.has_inlet_connection_format("ff"): # TODO(mhroth): implement this x = HeavyParser.graph_from_file("./hvlib/if~f.hv.json") elif self.has_inlet_connection_format("ii"): # TODO(mhroth): implement this x = HeavyParser.graph_from_file("./hvlib/if~i.hv.json") else: fmt = self._get_connection_format(self.inlet_connections) raise HeavyException(f"Unhandled connection configuration to object [if]: {fmt}") return ({x}, self.get_connection_move_list(x)) class HLangNoise(HeavyLangObject): """ Handles the HeavyLang "noise" object. """ def __init__( self, obj_type: str, args: Dict, graph: HeavyGraph, annotations: Optional[Dict] = None ) -> None: assert obj_type == "noise" super().__init__("noise", args, graph, num_inlets=1, num_outlets=1, annotations=annotations) def reduce(self) -> Tuple[Set, List]: seed = int(random.uniform(1, 2147483647)) # assign a random 32-bit seed noise_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "./hvlib/noise.hv.json") x = HeavyParser.graph_from_file(noise_path, graph_args={"seed": seed}) x.reduce() # TODO(mhroth): deal with control input return ({x}, self.get_connection_move_list(x)) # A list of all of the HeavyLang objects and the classes # that will translate them into HeavyIR objects. LANG_CLASS_DICT = { "__conv~f": HIrConvolution, "biquad": HLangBiquad, "if": HLangIf, "inlet": HIrInlet, "var": HLangVar, "vario": HLangVario, "outlet": HIrOutlet, "__lorenz~f": HIrLorenz, "print": HLangPrint, "sequence": HLangSequence, "adc": HLangAdc, "dac": HLangDac, "message": HLangMessage, "noise": HLangNoise, "system": HLangSystem, "phasor": HLangPhasor, "line": HLangLine, "random": HLangRandom, "delay": HLangDelay, "table": HLangTable, "slice": HLangSlice, "__tabread~if": HIrTabread, "__tabread~f": HIrTabread, "__tabread_stoppable~f": HIrTabread, "__tabreadu~f": HIrTabread, "__tabread": HIrTabread, "__tabhead~f": HIrTabhead, "__tabhead": HIrTabhead, "__tabwrite~f": HIrTabwrite, "__tabwrite_stoppable~f": HIrTabwrite, "__tabwrite": HIrTabwrite, "receive": HLangReceive, "send": HLangSend, "__switchcase": HIrSwitchcase, "switchcase": HIrSwitchcase, "__pack": HIrPack } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2635524 hvcc-0.13.3/hvcc/core/hv2ir/LocalVars.py0000644000000000000000000000756214677551203014640 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os from collections import defaultdict from typing import Optional, Union, Dict, List from .HeavyException import HeavyException from .HeavyLangObject import HeavyLangObject class LocalVars: """ A set of scoped objects. """ def __init__(self, stdlib_dir: str = "./") -> None: # a dictionary of name-registered objects # the data structure is a list map # key is the name under which the object is registered, value is a # list of all objects who are registered with that name self.__REGISTERED_OBJ_DICT: Dict = defaultdict(list) # the list of globally declared paths self.declared_paths = [stdlib_dir] # initialise with the standard library directory def find_path_for_abstraction(self, name: str) -> Optional[str]: # the file name based on the abstraction name file_name = f"{name}.hv.json" # iterate in order through the declared paths in order to find the file for d in self.declared_paths: file_path = os.path.join(d, file_name) if os.path.exists(file_path): return file_path # if a matching abstraction is found, return the path return None # otherwise return None def add_import_paths(self, path_list: List) -> None: """ Add import paths. Paths are expanded and made as explicit as possible. """ self.declared_paths.extend([os.path.abspath(os.path.expanduser(p)) for p in path_list]) def register_object(self, obj: HeavyLangObject, name: str, static: bool = False, unique: bool = False) -> None: """ Registers a named object. """ objs = self.get_objects_for_name(name, obj.type) if (unique and len(objs) > 0) or (static and len(objs) > 1): # if there is already a registered object of this type and the new # object is not declared as static, throw an error raise HeavyException(f"Object {obj} with name \"{name}\" already exists, " "and the new object is static or unique.") elif len(objs) == 1 and static: pass # the static object has already been registered, move on else: self.__REGISTERED_OBJ_DICT[name].append(obj) def unregister_object(self, obj: HeavyLangObject, name: str) -> None: """ Unregisters a named object. """ self.__REGISTERED_OBJ_DICT[name].remove(obj) def get_objects_for_name(self, name: str, obj_types: Union[str, List]) -> List: """ Returns a list of objects registered under a name in this scope. """ obj_types = obj_types if isinstance(obj_types, list) else [obj_types] return [o for o in self.__REGISTERED_OBJ_DICT[name] if o.type in obj_types] def get_registered_objects_for_type(self, obj_type: str) -> Dict: """ Returns a list-dictionary for all objects of the given type, indexed by name. """ d = defaultdict(list) for k, v in self.__REGISTERED_OBJ_DICT.items(): x = [o for o in v if o.type == obj_type] if len(x) > 0: # only return names that actually have associated objects d[k].extend(x) return d ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7492065 hvcc-0.13.3/hvcc/core/hv2ir/__init__.py0000644000000000000000000000000014435670357014471 0ustar00././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.261823 hvcc-0.13.3/hvcc/core/hv2ir/hv2ir.py0000644000000000000000000001275214735300474013776 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import argparse import json import os import time from typing import Optional from .HeavyException import HeavyException from .HeavyParser import HeavyParser from hvcc.types.compiler import CompilerResp, CompilerNotif, CompilerMsg class hv2ir: @classmethod def compile( cls, hv_file: str, ir_file: str, patch_name: Optional[str] = None, verbose: bool = False ) -> CompilerResp: """ Compiles a HeavyLang file into a HeavyIR file. Returns a tuple of compile time in seconds, a notification dictionary, and a heavy object counter. """ # keep track of the total compile time tick = time.time() hv_file = os.path.abspath(os.path.expanduser(hv_file)) ir_file = os.path.abspath(os.path.expanduser(ir_file)) try: # parse heavy file hv_graph = HeavyParser.graph_from_file(hv_file=hv_file, xname=patch_name) except HeavyException as e: return CompilerResp( stage="hv2ir", compile_time=time.time() - tick, notifs=CompilerNotif( has_error=True, exception=e, errors=[CompilerMsg(message=e.message)], warnings=[] ), in_file=os.path.basename(hv_file), in_dir=os.path.dirname(hv_file), out_file=os.path.basename(ir_file), out_dir=os.path.dirname(ir_file) ) try: # get a counter of all heavy objects hv_counter = hv_graph.get_object_counter(recursive=True) # prepare the graph for exporting hv_graph.prepare() # ensure that the output directory exists if not os.path.exists(os.path.dirname(ir_file)): os.makedirs(os.path.dirname(ir_file)) # generate Heavy.IR ir = hv_graph.to_ir() except HeavyException as e: return CompilerResp( stage="hv2ir", compile_time=time.time() - tick, notifs=CompilerNotif( has_error=True, exception=e, errors=[CompilerMsg(message=e.message)], warnings=[] ), in_file=os.path.basename(hv_file), in_dir=os.path.dirname(hv_file), out_file=os.path.basename(ir_file), out_dir=os.path.dirname(ir_file), obj_counter=hv_counter ) if ir is not None: # write the hv.ir file with open(ir_file, "w") as f: if verbose: json.dump( ir.model_dump(), f, sort_keys=True, indent=2, separators=(",", ": ")) else: json.dump(ir.model_dump(), f) if verbose and ir is not None: if len(ir.signal.processOrder) > 0: print("") print("=== Signal Order ===") for so in ir.signal.processOrder: o = ir.objects[so.id] if len(o.args) > 0: print("{0} {{{1}}}".format( o.type, " ".join([f"{k}:{v}" for k, v in o.args.items()]))) else: print(o.type) return CompilerResp( stage="hv2ir", compile_time=time.time() - tick, # record the total compile time notifs=hv_graph.get_notices(), in_file=os.path.basename(hv_file), in_dir=os.path.dirname(hv_file), out_file=os.path.basename(ir_file), out_dir=os.path.dirname(ir_file), obj_counter=hv_counter, ir=ir ) def main() -> None: parser = argparse.ArgumentParser( description="A C-language compiler for the Heavy audio programming language.") parser.add_argument( "hv_path", help="The patch to the top-level patch to compile.") parser.add_argument( "--hv_ir_path", default="./heavy.hv.ir.json", help="The output path of the hv.ir.json file.") parser.add_argument( "--name", default="heavy", help="") parser.add_argument("-v", "--verbose", action="count") args = parser.parse_args() d = hv2ir.compile( hv_file=args.hv_path, ir_file=args.hv_ir_path, patch_name=args.name, verbose=args.verbose) if args.verbose: print(f"Total hv2ir time: {(d.compile_time * 1000):.2f}ms") if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735983617.1410897 hvcc-0.13.3/hvcc/core/json/heavy.ir.json0000644000000000000000000014235114736201001014713 0ustar00{ "__^": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__^_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__abs": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__neg~f": { "inlets": [ "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "perf": { "avx": 0.5, "sse": 0.5 }, "args": [ ] }, "__abs~f": { "inlets": [ "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "perf": { "avx": 0.5, "sse": 0.5 }, "args": [ ] }, "__abs~i": { "inlets": [ "~i>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~i>" ] }, "__acos": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__acosh": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__acosh~f": { "inlets": [ "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ] }, "__acos~f": { "inlets": [ "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ] }, "__add": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__add_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__add~f": { "ir": { "control": false, "signal": true, "init": false }, "inlets": [ "~f>", "~f>" ], "outlets": [ "~f>" ], "perf": { "avx": 3, "sse": 3 }, "args": [ ] }, "__add~i": { "ir": { "control": false, "signal": true, "init": false }, "inlets": [ "~i>", "~i>" ], "outlets": [ "~i>" ], "perf": { "avx": 2, "sse": 0.5 }, "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__and": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "int", "name": "k", "description": "constant", "required": false }] }, "__and_k": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "int", "name": "k", "description": "constant", "required": false }] }, "__and~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 0.5, "sse": 0.5 } }, "__andnot~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 0.5, "sse": 0.5 } }, "__asin": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ] }, "__asinh": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ] }, "__atan": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__atan2": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 1, "value_type": "float", "name": "y", "description": "", "required": false }] }, "__atan2_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "float", "name": "y", "description": "", "required": false }] }, "__atan2~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ] }, "__atanh": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__bimod": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [ ] }, "__bimod_k": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__biquad_k~f": { "inlets": [ "~f>", "-->", "-->", "-->", "-->", "-->" ], "args": [{ "name": "ff0", "value_type": "float", "description": "", "default": 1, "required": false }, { "name": "ff1", "value_type": "float", "description": "", "default": 0, "required": false }, { "name": "ff2", "value_type": "float", "description": "", "default": 0, "required": false }, { "name": "fb1", "value_type": "float", "description": "", "default": 0, "required": false }, { "name": "fb2", "value_type": "float", "description": "", "default": 0, "required": false }], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>" ], "perf": { "avx": 30, "sse": 15 } }, "__biquad~f": { "inlets": [ "~f>", "~f>", "~f>", "~f>", "~f>", "~f>" ], "args": [ ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>" ], "perf": { } }, "__cast_b": { "inlets": [ "-->" ], "args": [ ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ] }, "__cast_f": { "inlets": [ "-->" ], "args": [ ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ] }, "__cast_s": { "inlets": [ "-->" ], "args": [ ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ] }, "__cast~fi": { "args": [ ], "inlets": [ "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~i>" ], "perf": { "avx": 1, "sse": 1 } }, "__cast~if": { "args": [ ], "inlets": [ "~i>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "perf": { "avx": 1, "sse": 1 } }, "__ceil": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__ceil~f": { "inlets": [ "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "perf": { "avx": 1, "sse": 1 } }, "__conv~f": { "inlets": [ "~f>", "-->", "-->" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>" ], "args": [{ "name": "table", "value_type": "string", "description": "", "default": "", "required": true }, { "name": "size", "value_type": "float", "description": "", "default": 0, "required": true }], "perf": { "avx": 0, "sse": 0 } }, "__cos": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__cosh": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__cosh~f": { "inlets": [ "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ] }, "__cos~f": { "inlets": [ "~f>" ], "args": [ ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ] }, "__cpole~f": { "inlets": [ "~f>", "~f>", "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>", "~f>" ], "args": [ ], "perf": { "avx": 143, "sse": 53 } }, "__del1~f": { "inlets": [ "~f>" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 5, "sse": 2 } }, "__delay": { "inlets": [ "-->", "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "float", "name": "delay", "description": "The message delay in milliseconds.", "required": false }] }, "__div": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__div_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__div~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }], "perf": { "avx": 25, "sse": 25 } }, "__div~i": { "inlets": [ "~i>", "~i>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~i>" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__env~f": { "inlets": [ "~f>" ], "ir": { "control": true, "signal": true, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "windowSize", "value_type": "float", "description": "", "default": 1024, "required": false }, { "name": "period", "value_type": "float", "description": "", "default": 512, "required": false }], "perf": { "avx": 9, "sse": 9 } }, "__eq": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "float", "name": "k", "description": "constant", "required": false }] }, "__eq_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "float", "name": "k", "description": "constant", "required": false }] }, "__eq~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 3, "sse": 3 } }, "__exp": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__floor": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__floor~f": { "args": [ ], "inlets": [ "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "perf": { "avx": 5, "sse": 5 } }, "__fma~f": { "inlets": [ "~f>", "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "perf": { "avx": 5, "sse": 5 }, "args": [ ] }, "__fms~f": { "inlets": [ "~f>", "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "perf": { "avx": 5, "sse": 5 }, "args": [ ] }, "__gt": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__gt_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__gte": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__gte_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__gte~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 1, "sse": 1 } }, "__gt~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 1, "sse": 1 } }, "__if": { "args": [{ "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false }], "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->", "-->" ] }, "__inlet": { "inlets": [ ], "ir": { "control": false, "signal": false, "init": false }, "outlets": [ "-->" ] }, "__intdiv": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 1, "required": false }] }, "__intdiv_k": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 1, "required": false }] }, "__line~f": { "inlets": [ "-->", "-->" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 5.5, "sse": 3.5 } }, "__log": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__log10": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__log2": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__log2~f": { "inlets": [ "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "args": [ ] }, "__logand": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "float", "name": "k", "description": "constant", "required": false }] }, "__logand_k": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "float", "name": "k", "description": "constant", "required": false }] }, "__logor": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "float", "name": "k", "description": "constant", "required": false }] }, "__logor_k": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "float", "name": "k", "description": "constant", "required": false }] }, "__lorenz~f": { "inlets": [ "~f>", "~f>", "~f>", "~f>", "-->" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>", "~f>", "~f>" ], "args": [{ "name": "x", "value_type": "float", "description": "Initial x output value", "default": 0, "required": false }, { "name": "y", "value_type": "float", "description": "Initial y output value", "default": 0, "required": false }, { "name": "z", "value_type": "float", "description": "Initial z output value", "default": 0, "required": false }] }, "__lt": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__lt_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__lte": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__lte_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__lt~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 1, "sse": 1 } }, "__lte~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 1, "sse": 1 } }, "__max": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__max_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__max~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 3, "sse": 3 } }, "__max~i": { "inlets": [ "~i>", "~i>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~i>" ], "args": [{ "name": "k", "value_type": "int", "description": "", "default": 0, "required": false }] }, "__message": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ] }, "__min": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__min_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__min~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "perf": { "avx": 3, "sse": 3 }, "args": [ ] }, "__min~i": { "inlets": [ "~i>", "~i>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~i>" ], "perf": { "sse": 0.5 }, "args": [{ "name": "k", "value_type": "int", "description": "", "default": 0, "required": false }] }, "__mul": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__mul_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__mul~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "perf": { "avx": 5, "sse": 5 }, "args": [ ] }, "__mul~i": { "inlets": [ "~i>", "~i>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~i>" ], "perf": { "avx": 3, "sse": 1 }, "args": [{ "name": "k", "value_type": "int", "description": "", "default": 0, "required": false }] }, "__neq": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "float", "name": "k", "description": "constant", "required": false }] }, "__neq_k": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "float", "name": "k", "description": "constant", "required": false }] }, "__neq~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 3, "sse": 3 } }, "__or": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "float", "name": "k", "description": "constant", "required": false }] }, "__or_k": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": 0, "value_type": "int", "name": "k", "description": "constant", "required": false }] }, "__or~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 1, "sse": 1 } }, "__outlet": { "inlets": [ "-->" ], "ir": { "control": false, "signal": false, "init": false }, "outlets": [ ] }, "__pack": { "inlets": [ ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "values", "value_type": "floatarray", "description": "The preset values to this pack object.", "default": [0.0, 0.0], "required": false }] }, "__phasor_k~f": { "inlets": [ "-->", "-->" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>" ], "args": [{ "default": 440, "value_type": "float", "name": "frequency", "description": "", "required": false }, { "default": 0, "value_type": "float", "name": "phase", "description": "", "required": false }], "perf": { "avx": 13, "sse": 10 } }, "__phasor~f": { "inlets": [ "~f>", "-->" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 38, "sse": 26 } }, "__pow": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ] }, "__pow_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ] }, "__pow~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ] }, "__print": { "inlets": [ "-->" ], "ir": { "control": false, "signal": false, "init": false }, "outlets": [ ] }, "__random": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "range", "value_type": "float", "description": "", "default": 2, "required": false }, { "name": "seed", "value_type": "float", "description": "", "default": 1, "required": false }] }, "__receive": { "inlets": [ ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ] }, "__rpole~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 143, "sse": 53 } }, "__rsqrt~f": { "inlets": [ "~f>" ], "args": [ ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ] }, "__samphold~f": { "inlets": [ "~f>", "~f>" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>" ], "args": [ ], "perf": { "avx": 0, "sse": 3 } }, "__sample~f": { "inlets": [ "~f>", "-->" ], "ir": { "control": true, "signal": true, "init": true }, "outlets": [ "-->" ], "args": [ ], "perf": { "avx": 1, "sse": 1 } }, "__send": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ ], "args": [{ "name": "name", "value_type": "string", "description": "", "default": null, "required": true }, { "name": "hash", "value_type": "string", "description": "The 32-bit hash of the \"name\" argument in \"0x00000000\" format.", "default": null, "required": true }] }, "__shiftleft": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "int", "description": "", "default": 0, "required": false }] }, "__shiftleft_k": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "int", "description": "", "default": 0, "required": false }] }, "__shiftright": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "int", "description": "", "default": 0, "required": false }] }, "__shiftright_k": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "int", "description": "", "default": 0, "required": false }] }, "__sin": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__sinh": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ] }, "__sin~f": { "inlets": [ "~f>" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ] }, "__slice": { "description": "", "ir": { "control": true, "signal": false, "init": true }, "inlets": [ "-->", "-->", "-->" ], "outlets": [ "-->", "-->" ], "args": [{ "name": "index", "value_type": "float", "description": "The start index of the slice.", "default": 0, "required": false }, { "name": "length", "value_type": "float", "description": "The number of elements to include in the slice.", "default": 1, "required": false }], "alias": [ ], "tags": [ ] }, "__sqrt": { "inlets": [ "-->" ], "args": [ ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ] }, "__sqrt~f": { "inlets": [ "~f>" ], "args": [ ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ] }, "__sub": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__sub_k": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__sub~f": { "ir": { "control": false, "signal": true, "init": false }, "inlets": [ "~f>", "~f>" ], "outlets": [ "~f>" ], "perf": { "avx": 3, "sse": 3 } }, "__sub~i": { "ir": { "control": false, "signal": true, "init": false }, "inlets": [ "~i>", "~i>" ], "outlets": [ "~i>" ], "perf": { "avx": 3, "sse": 1 }, "args": [{ "name": "k", "value_type": "float", "description": "", "default": 0, "required": false }] }, "__switchcase": { "ir": { "control": true, "signal": false, "init": false }, "inlets": [ "-->" ], "outlets": [ ], "args": [{ "default": [ ], "value_type": "mixedarray", "name": "cases", "description": "", "required": false }] }, "__system": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ] }, "__tabhead": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "default": null, "value_type": "string", "name": "table", "description": "The name of the table to reference.", "required": true }] }, "__tabhead~f": { "inlets": [ "-->" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>" ], "args": [{ "default": null, "value_type": "string", "name": "table", "description": "The name of the table to reference.", "required": true }], "perf": { "avx": 0.5, "sse": 0.5 } }, "__table": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "name", "value_type": "string", "description": "", "default": null, "required": true }, { "name": "size", "value_type": "int", "description": "The number of samples in this table.", "default": 0, "required": false }, { "name": "values", "value_type": "floatarray", "description": "The preset values in this table. The length of this list overrides the \"size\" argument.", "default": [ ], "required": false }] }, "__tabread": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "table", "value_type": "string", "description": "", "default": null, "required": true }] }, "__tabreadu~f": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": true, "init": true }, "outlets": [ "~f>", "-->" ], "args": [{ "default": null, "value_type": "string", "name": "table", "description": "The name of the table to reference.", "required": true }], "perf": { "avx": 2, "sse": 2 } }, "__tabread~f": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": true, "init": true }, "outlets": [ "~f>", "-->" ], "args": [{ "default": null, "value_type": "string", "name": "table", "description": "The name of the table to reference.", "required": true }], "perf": { "avx": 1, "sse": 1 } }, "__tabread_stoppable~f": { "inlets": [ "-->", "-->", "-->" ], "ir": { "control": true, "signal": true, "init": true }, "outlets": [ "~f>", "-->", "-->" ], "args": [{ "default": null, "value_type": "string", "name": "table", "description": "The name of the table to reference.", "required": true }], "perf": { "avx": 1, "sse": 1 } }, "__tabread~if": { "inlets": [ "~i>", "-->" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ "~f>" ], "args": [{ "default": null, "value_type": "string", "name": "table", "description": "The name of the table to reference.", "required": true }], "perf": { "avx": 4, "sse": 2 } }, "__tabwrite": { "inlets": [ "-->", "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "table", "value_type": "string", "description": "", "default": null, "required": true }] }, "__tabwrite_stoppable~f": { "inlets": [ "~f>", "-->", "-->" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ ], "args": [{ "default": null, "value_type": "string", "name": "table", "description": "The name of the table to reference.", "required": true }], "perf": { "avx": 2, "sse": 2 } }, "__tabwrite~f": { "inlets": [ "~f>", "-->", "-->" ], "ir": { "control": false, "signal": true, "init": true }, "outlets": [ ], "args": [{ "default": null, "value_type": "string", "name": "table", "description": "The name of the table to reference.", "required": true }], "perf": { "avx": 1, "sse": 1 } }, "__tan": { "inlets": [ "-->" ], "args": [ ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ] }, "__tanh": { "inlets": [ "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__unimod": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [ ] }, "__unimod_k": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": false }, "outlets": [ "-->" ], "args": [ ] }, "__var": { "inlets": [ "-->", "-->" ], "ir": { "control": true, "signal": false, "init": true }, "outlets": [ "-->" ], "args": [{ "name": "k", "value_type": "auto", "description": "", "default": 0, "required": false }] }, "__var_k~f": { "ir": { "control": false, "signal": true, "init": false }, "inlets": [ ], "args": [{ "default": 0, "value_type": "float", "name": "k", "description": "The value of this variable.", "required": false }, { "default": 0, "value_type": "float", "name": "step", "description": "The value step increment.", "required": false }, { "default": false, "value_type": "boolean", "name": "reverse", "description": "True if the value and step increments should be reversed.", "required": false }], "outlets": [ "~f>" ], "keywords": [ ], "perf": { "avx": 0.5, "sse": 0.5 } }, "__var_k~i": { "ir": { "control": false, "signal": true, "init": false }, "inlets": [ ], "args": [{ "default": 0, "value_type": "int", "name": "k", "description": "The value of this variable.", "required": false }, { "default": 0, "value_type": "int", "name": "step", "description": "The value step increment.", "required": false }, { "default": false, "value_type": "boolean", "name": "reverse", "description": "True if the value and step increments should be reversed.", "required": false }], "outlets": [ "~i>" ], "keywords": [ ], "perf": { "avx": 0.5, "sse": 0.5 } }, "__varread~f": { "ir": { "control": false, "signal": true, "init": false }, "inlets": [ ], "args": [{ "default": null, "value_type": "string", "name": "var_id", "description": "The id the of the var object to read from.", "required": true }], "outlets": [ "~f>" ], "perf": { "avx": 1, "sse": 1 } }, "__varread~i": { "ir": { "control": false, "signal": true, "init": false }, "inlets": [ ], "args": [{ "default": null, "value_type": "string", "name": "var_id", "description": "The id the of the var object to read from.", "required": true }], "outlets": [ "~i>" ], "perf": { "avx": 1, "sse": 1 } }, "__varwrite~f": { "ir": { "control": false, "signal": true, "init": false }, "inlets": [ "~f>" ], "args": [{ "default": null, "value_type": "string", "name": "var_id", "description": "The id the of the var object to write to.", "required": true }], "outlets": [ ], "perf": { "avx": 1, "sse": 1 } }, "__varwrite~i": { "ir": { "control": false, "signal": true, "init": false }, "inlets": [ "~i>" ], "args": [{ "default": null, "value_type": "string", "name": "var_id", "description": "The id the of the var object to write to.", "required": true }], "outlets": [ ], "perf": { "avx": 1, "sse": 1 } }, "__var~f": { "ir": { "control": false, "signal": false, "init": true }, "inlets": [ "-->" ], "args": [{ "default": 0, "value_type": "float", "name": "k", "description": "The value of this variable.", "required": false }, { "default": 0, "value_type": "float", "name": "step", "description": "The value step increment.", "required": false }, { "default": false, "value_type": "boolean", "name": "reverse", "description": "True if the value and step increments should be reversed.", "required": false }], "outlets": [ "~f>" ], "keywords": [ "static" ], "perf": { "avx": 0, "sse": 0, "neon": 0 } }, "__var~i": { "ir": { "control": false, "signal": false, "init": true }, "inlets": [ "-->" ], "args": [{ "default": 0, "value_type": "int", "name": "k", "description": "The value of this variable.", "required": false }, { "default": 0, "value_type": "int", "name": "step", "description": "The value step increment.", "required": false }, { "default": false, "value_type": "boolean", "name": "reverse", "description": "True if the value and step increments should be reversed.", "required": false }], "outlets": [ "~i>" ], "perf": { "avx": 0, "sse": 0, "neon": 0 } }, "asinh~": { "inlets": [ "signal" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "signal" ], "args": [ ] }, "asin~": { "inlets": [ "signal" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "signal" ] }, "atanh~": { "inlets": [ "signal" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "signal" ] }, "atan~": { "inlets": [ "signal" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "signal" ] }, "__exp~f": { "inlets": [ "~f>" ], "args": [], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "~f>" ], "perf": { "avx": 0, "sse": 0, "neon": 0 } }, "sinh~": { "inlets": [ "signal" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "signal" ], "args": [ ] }, "tanh~": { "inlets": [ "signal" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "signal" ] }, "tan~": { "inlets": [ "signal" ], "ir": { "control": false, "signal": true, "init": false }, "outlets": [ "signal" ] } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.261823 hvcc-0.13.3/hvcc/core/json/heavy.lang.json0000644000000000000000000012361114735300474015235 0ustar00{ "!=": { "description": "Output = (bool) (Input != k)", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ "ne" ], "tags": [ "math", "logical" ] }, "%": { "description": "Output = Input % k", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 1, "required": false } ], "alias": [ "mod" ], "tags": [ "math", "logical" ] }, "&": { "description": "Binary AND operation.", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "int", "description": "constant", "default": 0, "required": false } ], "alias": [ "binaryand" ], "tags": [ "math", "bitwise" ] }, "&&": { "description": "Logical AND operation.", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ "logicaland" ], "tags": [ "math", "logical" ] }, "*": { "description": "Output = Input * k", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ "divide" ], "tags": [ "math", "arithmetic" ] }, "+": { "description": "Output = Input + k", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ "sub" ], "tags": [ "math", "arithmetic" ] }, "-": { "description": "Output = Input - k", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ "mult" ], "tags": [ "math", "arithmetic" ] }, "/": { "description": "Output = Input / k", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 1, "required": false } ], "alias": [ "add" ], "tags": [ "math", "arithmetic" ] }, "<": { "description": "Output = (bool) (Input < k)", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ "lt" ], "tags": [ "math", "logical" ] }, "<<": { "description": "Output = (Input << k)", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "int", "description": "constant", "default": 0, "required": false } ], "alias": [ "leftshift" ], "tags": [ "math", "bitwise" ] }, "<=": { "description": "Output = (bool) (Input <= k)", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ "lte" ], "tags": [ "math", "logical" ] }, "==": { "description": "Output = (bool) (Input == k)", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ "eq" ], "tags": [ "math", "logical" ] }, ">": { "description": "Output = (bool) (Input > k)", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ "gt" ], "tags": [ "math", "logical" ] }, ">=": { "description": "Output = (bool) (Input >= k)", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ "gte" ], "tags": [ "math", "logical" ] }, ">>": { "description": "Output = (Input >> k)", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "int", "description": "constant", "default": 0, "required": false } ], "alias": [ "rightshift" ], "tags": [ "math", "bitwise" ] }, "^": { "description": "Output = (Input ^ k)", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ "xor" ], "tags": [ "math", "bitwise" ] }, "abs": { "description": "Output = abs(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math" ] }, "acos": { "description": "Output = acos(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math", "trigonometric" ] }, "acosh": { "description": "Output = acosh(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math", "trigonometric" ] }, "adc": { "description": "", "inlets": [ ], "outlets": [ { "name": "", "connectionType": "~f>", "description": "" } ], "args": [ { "name": "channels", "value_type": "intarray", "description": "Channels from input.", "default": [ 1, 2 ], "required": false } ], "alias": [ ], "tags": [ ] }, "asin": { "description": "Output = asin(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math", "trigonometric" ] }, "asinh": { "description": "Output = asinh(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math", "trigonometric" ] }, "atan": { "description": "Output = atan(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math", "trigonometric" ] }, "atan2": { "description": "Output = atan2(x, y)", "inlets": [ { "name": "x", "connectionType": "-~>", "description": "Set x" }, { "name": "y", "connectionType": "-~>", "description": "Set y" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "y", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ ], "tags": [ "math", "trigonometric" ] }, "atanh": { "description": "Output = atanh(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math", "trigonometric" ] }, "biquad": { "description": "out = in[0]*x0 + in[-1]*x1 + in[-2]*x2 - out[-1]*y1 - out[-2]*y2", "inlets": [ { "name": "input", "connectionType": "~f>", "description": "Filter input." }, { "name": "x0", "connectionType": "-~>", "description": "" }, { "name": "x1", "connectionType": "-~>", "description": "" }, { "name": "x2", "connectionType": "-~>", "description": "" }, { "name": "y1", "connectionType": "-~>", "description": "" }, { "name": "y2", "connectionType": "-~>", "description": "" } ], "outlets": [ { "name": "output", "connectionType": "~f>", "description": "Filter output." } ], "args": [ { "name": "ff0", "value_type": "float", "description": "", "default": 1, "required": false }, { "name": "ff1", "value_type": "float", "description": "", "default": 0, "required": false }, { "name": "ff2", "value_type": "float", "description": "", "default": 0, "required": false }, { "name": "fb1", "value_type": "float", "description": "", "default": 0, "required": false }, { "name": "fb2", "value_type": "float", "description": "", "default": 0, "required": false } ], "alias": [ ], "tags": [ "filters" ] }, "ceil": { "description": "", "inlets": [ { "name": "k", "connectionType": "-~>", "description": "" } ], "outlets": [ { "name": "", "connectionType": "-~>", "description": "ceil(k)" } ], "args": [ ], "alias": [ ], "tags": [ ] }, "comment": { "description": "A text comment.", "inlets": [ ], "outlets": [ ], "args": [ { "name": "text", "value_type": "string", "description": "The comment string.", "default": null, "required": true }, { "name": "mime", "value_type": "string", "description": "The MIME type of this comment.", "default": "text/plain", "required": false } ], "alias": [ ], "tags": [ ] }, "cos": { "description": "Output = cos(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math", "trigonometric" ] }, "dac": { "description": "", "inlets": [ { "name": "", "connectionType": "~f>", "description": "" } ], "outlets": [ ], "args": [ { "name": "channels", "value_type": "intarray", "description": "Channels to output.", "default": [ 1, 2 ], "required": false } ], "alias": [ ], "tags": [ ] }, "delay": { "description": "", "inlets": [ { "name": "message", "connectionType": "-->", "description": "The message to delay." }, { "name": "delay", "connectionType": "-->", "description": "The delay is milliseconds." } ], "outlets": [ { "name": "outlet", "connectionType": "-->", "description": "The delayed message." } ], "args": [ { "name": "delay", "value_type": "float", "description": "The message delay in milliseconds.", "default": 0, "required": false } ], "alias": [ ], "tags": [ ] }, "env~": { "description": "", "inlets": [ { "name": "", "connectionType": "~f>", "description": "" } ], "outlets": [ { "name": "", "connectionType": "-->", "description": "" } ], "args": [ { "name": "windowSize", "value_type": "float", "description": "", "default": 1024, "required": false }, { "name": "period", "value_type": "float", "description": "", "default": 512, "required": false } ], "alias": [ "envelope" ], "tags": [ ] }, "exp": { "description": "Output = exp(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math" ] }, "floor": { "description": "", "inlets": [ { "name": "k", "connectionType": "-~>", "description": "" } ], "outlets": [ { "name": "", "connectionType": "-~>", "description": "floor(k)" } ], "args": [ ], "alias": [ ], "tags": [ ] }, "graph": { "description": "", "inlets": [ ], "outlets": [ ], "args": [ ], "alias": [ ], "tags": [ ] }, "if": { "description": "Input to the first inlet is routed to the first outlet if k == 0, else it's routed to the second outlet.", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "k is False", "connectionType": "-~>", "description": "Output." }, { "name": "k is True", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ ], "tags": [ "sequencing" ] }, "inlet": { "description": "", "inlets": [ ], "outlets": [ { "name": "", "connectionType": "-~>", "description": "" } ], "args": [ { "name": "name", "value_type": "string", "description": "inlet name", "default": "", "required": false }, { "name": "index", "value_type": "int", "description": "Determines the inlet position within an abstraction/sub-graph", "default": 0, "required": true }, { "name": "type", "value_type": "string", "description": "Specifies the inlet connection type", "default": null, "required": true } ], "alias": [ ], "tags": [ ] }, "line": { "description": "", "inlets": [ { "name": "", "connectionType": "-->", "description": "" }, { "name": "", "connectionType": "-->", "description": "" } ], "outlets": [ { "name": "", "connectionType": "-~>", "description": "" } ], "args": [ ], "alias": [ ], "tags": [ ] }, "loadbang": { "description": "Triggers an event once the patch is initialised", "inlets": [ ], "outlets": [ { "name": "outlet", "connectionType": "-->", "description": "Bang output." } ], "args": [ { "name": "priority", "value_type": "int", "description": "Relative priority for when this loadbang should fire. Higher executes sooner.", "default": 0, "required": false } ], "alias": [ ], "tags": [ "sequencing" ] }, "log": { "description": "Output = round(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math" ] }, "log10": { "description": "Output = log10(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math" ] }, "log2": { "description": "Output = log2(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math" ] }, "max": { "description": "Finds the maximum of the two inputs.", "inlets": [ { "name": "", "connectionType": "-~>", "description": "" }, { "name": "", "connectionType": "-~>", "description": "" } ], "outlets": [ { "name": "", "connectionType": "-~>", "description": "" } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ ], "tags": [ "math" ] }, "message": { "description": "", "inlets": [ { "name": "", "connectionType": "-->", "description": "" } ], "outlets": [ { "name": "", "connectionType": "-->", "description": "" } ], "args": [ { "name": "local", "value_type": null, "description": "A list of message lists to send.", "default": null, "required": true }, { "name": "remote", "value_type": null, "description": "A list of message lists to send.", "default": [ ], "required": false } ], "alias": [ ], "tags": [ ] }, "min": { "description": "Finds the minimum of the two inputs.", "inlets": [ { "name": "", "connectionType": "-~>", "description": "" }, { "name": "", "connectionType": "-~>", "description": "" } ], "outlets": [ { "name": "", "connectionType": "-~>", "description": "" } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ ], "tags": [ "math" ] }, "mod": { "description": "Output = Input % k, (always positive)", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 1, "required": false } ], "alias": [ ], "tags": [ "math", "arithmetic" ] }, "noise": { "description": "White noise signal generator.", "inlets": [ { "name": "seed", "connectionType": "-->", "description": "Currently unused." } ], "outlets": [ { "name": "Output", "connectionType": "~f>", "description": "White noise." } ], "args": [ { "name": "noise", "value_type": "string", "description": "The type of noise to produce. Currently only `uniform` is supported.", "default": "uniform", "required": false }, { "name": "seed", "value_type": "float", "description": "The seed for the random number generator (RNG).", "default": 0, "required": false } ], "alias": [ ], "tags": [ "~f>", "generators" ] }, "outlet": { "description": "", "inlets": [ { "name": "", "connectionType": "-~>", "description": "" } ], "outlets": [ ], "args": [ { "name": "name", "value_type": "string", "description": "outlet name", "default": "", "required": false }, { "name": "index", "value_type": "int", "description": "Determines the outlet position within an abstraction/sub-graph", "default": 0, "required": true }, { "name": "type", "value_type": "string", "description": "specifies the outlet connection type", "default": null, "required": true } ], "alias": [ ], "tags": [ ] }, "phasor": { "description": "", "inlets": [ { "name": "frequency", "connectionType": "-~>", "description": "" }, { "name": "phase", "connectionType": "-->", "description": "" } ], "outlets": [ { "name": "~f>", "connectionType": "~f>", "description": "" } ], "args": [ { "name": "frequency", "value_type": "float", "description": "", "default": 0, "required": false }, { "name": "phase", "value_type": "float", "description": "", "default": 0, "required": false } ], "alias": [ ], "tags": [ ] }, "pow": { "description": "Output = pow(Input, k)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" }, { "name": "constant", "connectionType": "-~>", "description": "set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ ], "tags": [ "math" ] }, "print": { "description": "", "inlets": [ { "name": "", "connectionType": "-->", "description": "" } ], "outlets": [ ], "args": [ { "name": "label", "value_type": "string", "description": "", "default": "print", "required": false } ], "alias": [ ], "tags": [ "debugging" ] }, "random": { "description": "Random number generator", "inlets": [ { "name": "trigger", "connectionType": "-->", "description": "Outputs random number when triggered." }, { "name": "range", "connectionType": "-->", "description": "Generated number will be in the range [0.0, 1.0)." } ], "outlets": [ { "name": "outlet", "connectionType": "-->", "description": "Output." } ], "args": [ { "name": "seed", "value_type": "int", "description": "seed", "default": -1, "required": false } ], "alias": [ ], "tags": [ "math" ] }, "receive": { "description": "", "inlets": [ ], "outlets": [ { "name": "", "connectionType": "-->", "description": "" } ], "args": [ { "name": "name", "value_type": "string", "description": "The name of this receiver.", "default": null, "required": true }, { "name": "priority", "value_type": "int", "description": "Higher priority receivers will be executed first.", "default": 0, "required": false }, { "name": "extern", "value_type": "string", "description": "If the receiver should be exposed to external (user) interfaces, 'param' or 'event'.", "default": null, "required": false }, { "name": "attributes", "value_type": "dict", "description": "Variable argument information depending on the extern type.", "default": {}, "required": false } ], "alias": [ "r" ], "tags": [ ] }, "send": { "description": "", "inlets": [ { "name": "", "connectionType": "-->", "description": "" } ], "outlets": [ ], "args": [ { "name": "name", "value_type": "string", "description": "", "default": null, "required": true } ], "alias": [ "s" ], "tags": [ ] }, "sequence": { "description": "", "inlets": [ { "name": "", "connectionType": "-->", "description": "" } ], "outlets": [ { "name": "value", "connectionType": "-->", "description": "" } ], "args": [ { "name": "casts", "value_type": "stringarray", "description": "Sequence and cast types.", "default": null, "required": true } ], "alias": [ "seq" ], "tags": [ "sequencing" ] }, "sin": { "description": "Output = sin(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math", "trigonometric" ] }, "sinh": { "description": "Output = sinh(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math", "trigonometric" ] }, "slice": { "description": "", "inlets": [ { "name": "", "connectionType": "-->", "description": "" }, { "name": "", "connectionType": "-->", "description": "" }, { "name": "", "connectionType": "-->", "description": "" } ], "outlets": [ { "name": "", "connectionType": "-->", "description": "The sliced output." }, { "name": "", "connectionType": "-->", "description": "If no slice is possible, a bang is emitted." } ], "args": [ { "name": "index", "value_type": "int", "description": "The start index of the slice.", "default": 0, "required": false }, { "name": "length", "value_type": "int", "description": "The number of elements to include in the slice.", "default": 1, "required": false } ], "alias": [ ], "tags": [ ] }, "sqrt": { "description": "Output = sqrt(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math" ] }, "system": { "description": "Returns system properties such as samplerate or block size.", "inlets": [ { "name": "parameter", "connectionType": "-->", "description": "The requested system parameter." } ], "outlets": [ { "name": "value", "connectionType": "-->", "description": "The system parameter value." } ], "args": [ ], "alias": [ ], "tags": [ ] }, "table": { "description": "", "inlets": [ { "name": "", "connectionType": "-->", "description": "" } ], "outlets": [ { "name": "", "connectionType": "-->", "description": "" } ], "args": [ { "name": "name", "value_type": "string", "description": "", "default": null, "required": true }, { "name": "size", "value_type": "int", "description": "The number of samples in this table.", "default": 256, "required": false }, { "name": "values", "value_type": "floatarray", "description": "The preset values in this table. The length of this list overrides the \"size\" argument.", "default": [], "required": false }, { "name": "extern", "value_type": "bool", "description": "Determines if the table should be publicly exposed in a framework.", "default": false, "required": false } ], "alias": [ ], "tags": [ ] }, "tabread": { "description": "", "inlets": [ { "name": "", "connectionType": "-~>", "description": "" } ], "outlets": [ { "name": "", "connectionType": "-~>", "description": "output = table[input]" }, { "name": "", "connectionType": "-~>", "description": "output = table[input+1]" } ], "args": [ { "name": "table", "value_type": "string", "description": "The name of the table to read from.", "default": null, "required": true }, { "name": "delay", "value_type": "float", "description": "", "default": 0, "required": false } ], "alias": [ ], "tags": [ ] }, "tabwrite": { "description": "", "inlets": [ { "name": "", "connectionType": "-->", "description": "" } ], "outlets": [ { "name": "", "connectionType": "~f>", "description": "" } ], "args": [ { "name": "name", "value_type": "string", "description": "The name of the table to read from.", "default": null, "required": true }, { "name": "loop", "value_type": "bool", "description": "If the object should continue writing to the table when the end is reached.", "default": true, "required": false } ], "alias": [ ], "tags": [ ] }, "tan": { "description": "Output = tan(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math", "trigonometric" ] }, "tanh": { "description": "Output = tanh(Input)", "inlets": [ { "name": "inlet", "connectionType": "-~>", "description": "Input" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ ], "alias": [ ], "tags": [ "math", "trigonometric" ] }, "var": { "description": "", "inlets": [ { "name": "", "connectionType": "-~>", "description": "" } ], "outlets": [ { "name": "", "connectionType": "-~>", "description": "" } ], "args": [ { "default": 0, "value_type": "float", "name": "k", "description": "The value of this variable.", "required": false }, { "default": 0, "value_type": "float", "name": "step", "description": "The value step increment.", "required": false }, { "default": false, "value_type": "bool", "name": "reverse", "description": "True if the value and step increments should be reversed.", "required": false }, { "default": null, "value_type": "string", "name": "name", "description": "The variable may be named, which is especially useful when used in conjunction with the __varset~f object.", "required": false } ], "alias": [ ], "tags": [ ] }, "vario": { "description": "", "inlets": [ { "name": "", "connectionType": "-~>", "description": "" } ], "outlets": [ { "name": "", "connectionType": "-~>", "description": "" } ], "args": [ { "default": null, "value_type": "string", "name": "name", "description": "The named variable which will be manipulated.", "required": true } ], "alias": [ ], "tags": [ ] }, "|": { "description": "Binary OR operation.", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "int", "description": "constant", "default": 0, "required": false } ], "alias": [ "binaryor" ], "tags": [ "math", "bitwise" ] }, "||": { "description": "Logical OR operation.", "inlets": [ { "name": "Input", "connectionType": "-~>", "description": "Set input" }, { "name": "k", "connectionType": "-~>", "description": "Set k" } ], "outlets": [ { "name": "outlet", "connectionType": "-~>", "description": "Output." } ], "args": [ { "name": "k", "value_type": "float", "description": "constant", "default": 0, "required": false } ], "alias": [ "logicalor" ], "tags": [ "math", "logical" ] } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7502067 hvcc-0.13.3/hvcc/generators/__init__.py0000644000000000000000000000000014435670357014660 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7502067 hvcc-0.13.3/hvcc/generators/c2daisy/__init__.py0000644000000000000000000000000014435670357016216 0ustar00././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.261823 hvcc-0.13.3/hvcc/generators/c2daisy/c2daisy.py0000644000000000000000000001410414735300474016020 0ustar00import jinja2 import os import shutil import time import json2daisy # type: ignore from typing import Any, Dict, Optional from ..copyright import copyright_manager from . import parameters from hvcc.interpreters.pd2hv.NotificationEnum import NotificationEnum from hvcc.types.compiler import Generator, CompilerResp, CompilerNotif, CompilerMsg, ExternInfo from hvcc.types.meta import Meta, Daisy hv_midi_messages = { "__hv_noteout", "__hv_ctlout", "__hv_polytouchout", "__hv_pgmout", "__hv_touchout", "__hv_bendout", "__hv_midiout", "__hv_midioutport" } class c2daisy(Generator): """ Generates a Daisy wrapper for a given patch. """ @classmethod def compile( cls, c_src_dir: str, out_dir: str, externs: ExternInfo, patch_name: Optional[str] = None, patch_meta: Meta = Meta(), num_input_channels: int = 0, num_output_channels: int = 0, copyright: Optional[str] = None, verbose: Optional[bool] = False ) -> CompilerResp: tick = time.time() out_dir = os.path.join(out_dir, "daisy") daisy_meta: Daisy = patch_meta.daisy board = daisy_meta.board copyright_c = copyright_manager.get_copyright_for_c(copyright) try: # ensure that the output directory does not exist out_dir = os.path.abspath(out_dir) if os.path.exists(out_dir): shutil.rmtree(out_dir) # copy over static files shutil.copytree(os.path.join(os.path.dirname(__file__), "static"), out_dir) # copy over generated C source files source_dir = os.path.join(out_dir, "source") shutil.copytree(c_src_dir, source_dir) if daisy_meta.board_file is not None: header, board_info = json2daisy.generate_header_from_file(daisy_meta.board_file) else: header, board_info = json2daisy.generate_header_from_name(board) # remove heavy out params from externs externs.parameters.outParam = [ t for t in externs.parameters.outParam if not any(x == y for x in hv_midi_messages for y in t)] component_glue = parameters.parse_parameters( externs.parameters, board_info['components'], board_info['aliases'], 'hardware') component_glue['class_name'] = board_info['name'] component_glue['patch_name'] = patch_name component_glue['header'] = f"HeavyDaisy_{patch_name}.hpp" component_glue['max_channels'] = board_info['channels'] component_glue['num_output_channels'] = num_output_channels component_glue['has_midi'] = board_info['has_midi'] component_glue['displayprocess'] = board_info['displayprocess'] component_glue['debug_printing'] = daisy_meta.debug_printing component_glue['usb_midi'] = daisy_meta.usb_midi component_glue['pool_sizes_kb'] = externs.memoryPoolSizesKb # samplerate samplerate = daisy_meta.samplerate if samplerate >= 96000: component_glue['samplerate'] = 96000 elif samplerate >= 48000: component_glue['samplerate'] = 48000 elif samplerate >= 32000: component_glue['samplerate'] = 32000 elif samplerate >= 16000: component_glue['samplerate'] = 16000 else: component_glue['samplerate'] = 8000 # blocksize blocksize = daisy_meta.blocksize if blocksize is not None: component_glue['blocksize'] = max(min(256, blocksize), 1) else: component_glue['blocksize'] = None component_glue['copyright'] = copyright_c daisy_h_path = os.path.join(source_dir, f"HeavyDaisy_{patch_name}.hpp") with open(daisy_h_path, "w") as f: f.write(header) loader = jinja2.FileSystemLoader(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')) env = jinja2.Environment(loader=loader, trim_blocks=True, lstrip_blocks=True) daisy_cpp_path = os.path.join(source_dir, f"HeavyDaisy_{patch_name}.cpp") rendered_cpp = env.get_template('HeavyDaisy.cpp').render(component_glue) with open(daisy_cpp_path, 'w') as f: f.write(rendered_cpp) makefile_replacements: Dict[str, Any] = {'name': patch_name} makefile_replacements['linker_script'] = daisy_meta.linker_script # libdaisy path path = daisy_meta.libdaisy_path if isinstance(path, int): makefile_replacements['libdaisy_path'] = f'{"../" * path}libdaisy' elif isinstance(path, str): makefile_replacements['libdaisy_path'] = path makefile_replacements['bootloader'] = daisy_meta.bootloader makefile_replacements['debug_printing'] = daisy_meta.debug_printing rendered_makefile = env.get_template('Makefile').render(makefile_replacements) with open(os.path.join(source_dir, "Makefile"), "w") as f: f.write(rendered_makefile) # ====================================================================================== return CompilerResp( stage="c2daisy", in_dir=c_src_dir, out_dir=out_dir, out_file=os.path.basename(daisy_h_path), compile_time=time.time() - tick ) except Exception as e: return CompilerResp( stage="c2daisy", notifs=CompilerNotif( has_error=True, exception=e, warnings=[], errors=[CompilerMsg( enum=NotificationEnum.ERROR_EXCEPTION, message=str(e) )] ), in_dir=c_src_dir, out_dir=out_dir, compile_time=time.time() - tick ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2628229 hvcc-0.13.3/hvcc/generators/c2daisy/parameters.py0000644000000000000000000002233114735300474016626 0ustar00 from copy import deepcopy from typing import Any, Dict, Optional from hvcc.types.compiler import ExternParams def filter_match( set: Dict, key: str, match: str, key_exclude: Optional[str] = None, match_exclude: Optional[str] = None ) -> filter: if (key_exclude is not None and match_exclude is not None): return filter(lambda x: x.get(key, '') == match and x.get(key_exclude, '') != match_exclude, set) else: return filter(lambda x: x.get(key, '') == match, set) def verify_param_exists(name: str, original_name: str, components: Dict, input: bool = True) -> Any: for comp in components: # Dealing with the cvouts the way we have it set up is really annoying if comp['component'] == 'CVOuts': if name == comp['name']: if input: raise TypeError( f'Parameter "{original_name}" cannot be used as an {"input" if input else "output"}') return else: variants = [mapping['name'].format_map( {'name': comp['name']}) for mapping in comp['mapping']] if name in variants: if input and comp['direction'] == 'output' or not input and comp['direction'] == 'input': raise TypeError( f'Parameter "{original_name}" cannot be used as an {"input" if input else "output"}') return raise NameError(f'Unknown parameter "{original_name}"') def verify_param_direction(name: str, components: Dict) -> bool: for comp in components: if comp['component'] == 'CVOuts': if name == comp['name']: return True else: variants = [mapping['name'].format_map( {'name': comp['name']}) for mapping in comp['mapping']] if name in variants: return True return False def get_root_component(variant: str, original_name: str, components: Dict) -> str: for comp in components: if comp['component'] == 'CVOuts': if variant == comp['name']: return variant else: variants = [mapping['name'].format_map( {'name': comp['name']}) for mapping in comp['mapping']] if variant in variants: return comp['name'] raise NameError(f'Unknown parameter "{original_name}"') def get_component_mapping( component_variant: str, original_name: str, component: Dict, components: Dict ) -> Dict: for variant in component['mapping']: if component['component'] == 'CVOuts': stripped = variant['name'].format_map({'name': ''}) if stripped in component['name']: return variant elif variant['name'].format_map({'name': component['name']}) == component_variant: return variant raise NameError(f'Unknown parameter "{original_name}"') def verify_param_used( component: Dict, params_in: Dict, params_out: Dict, params_in_original_name: Dict, params_out_original_name: Dict, components: Dict ) -> bool: # Exclude parents, since they don't have 1-1 i/o mapping if component.get('is_parent', False): return True for param in {**params_in, **params_out}: root = get_root_component( param, ({**params_in_original_name, **params_out_original_name})[param], components) if root == component['name']: return True return False def de_alias( name: str, aliases: Dict, components: Dict ) -> str: low = name.lower() # simple case if low in aliases: return aliases[low] # aliased variant potential_aliases = list(filter(lambda x: x in low, aliases)) for alias in potential_aliases: try: target_component = list(filter_match( components, 'name', aliases[alias]))[0] # The CVOuts setup really bothers me if target_component['component'] != 'CVOuts': for mapping in target_component['mapping']: if mapping['name'].format_map({'name': alias}) == low: return mapping['name'].format_map({'name': aliases[alias]}) except IndexError: # No matching alias from filter pass # otherwise, it's a direct parameter or unkown one return low def parse_parameters( parameters: ExternParams, components: Dict, aliases: Dict, object_name: str ) -> Dict: """ Parses the `parameters` passed from hvcc and generates getters and setters according to the info in `components`. The `aliases` help disambiguate parameters and the `object_name` sets the identifier for the generated Daisy hardware class, in this case `hardware`. """ # Verify that the params are valid and remove unused components replacements: Dict = {} params_in: Dict = {} params_in_original_names: Dict = {} for key, recv in parameters.inParam: de_aliased = de_alias(key, aliases, components) params_in[de_aliased] = recv params_in_original_names[de_aliased] = key params_out = {} params_out_original_names = {} for key, msg in parameters.outParam: de_aliased = de_alias(key, aliases, components) params_out[de_aliased] = msg params_out_original_names[de_aliased] = key [verify_param_exists(key, params_in_original_names[key], components, input=True) for key in params_in] [verify_param_exists(key, params_out_original_names[key], components, input=False) for key in params_out] for i in range(len(components) - 1, -1, -1): if not verify_param_used( components[i], params_in, params_out, params_in_original_names, params_out_original_names, components): components.pop(i) out_idx = 0 replacements['parameters'] = [] replacements['output_parameters'] = [] replacements['loop_write_in'] = [] replacements['callback_write_out'] = [] replacements['loop_write_out'] = [] replacements['hook_write_out'] = [] replacements['callback_write_in'] = [] for param_name, param in params_in.items(): root = get_root_component( param_name, params_in_original_names[param_name], components) component = list(filter_match(components, 'name', root))[0] param_struct = { "hash_enum": params_in_original_names[param_name], 'name': root, 'type': component['component'].upper()} replacements['parameters'].append(param_struct) mapping = get_component_mapping( param_name, params_in_original_names[param_name], component, components) write_location = 'callback_write_in' if mapping.get( 'where', 'callback') == 'callback' else 'loop_write_in' component_info = deepcopy(component) component_info['name'] = root component_info['class_name'] = object_name # A bit of a hack to get cv_1, etc to be written as CV_1 component_info['name_upper'] = root.upper() component_info['value'] = f'output_data[{out_idx}]' component_info['default_prefix'] = component.get( "default_prefix", '') if component.get('default', False) else '' process = mapping["get"].format_map(component_info) replacements[write_location].append( {"process": process, "bool": mapping.get('bool', False), "hash_enum": params_in_original_names[param_name]}) for param_name, param in params_out.items(): root = get_root_component( param_name, params_out_original_names[param_name], components) component = list(filter_match(components, 'name', root))[0] mapping = get_component_mapping( param_name, params_out_original_names[param_name], component, components) default_prefix = component.get( "default_prefix", '') if component.get('default', False) else '' write_locations = {'callback': 'callback_write_out', 'loop': 'loop_write_out', 'hook': 'hook_write_out'} write_location = write_locations.get(mapping.get('where', 'callback'), 'callback_write_out') param_struct = { 'hash_enum': params_out_original_names[param_name], 'index': out_idx, 'name': param_name, 'hook': write_location == 'hook_write_out'} replacements['output_parameters'].append(param_struct) component_info = deepcopy(component) component_info['hash_enum'] = params_out_original_names[param_name] component_info['name'] = root component_info['class_name'] = object_name component_info['value'] = f'output_data[{out_idx}]' if \ write_location != 'hook_write_out' else 'sig' component_info['default_prefix'] = default_prefix write = mapping["set"].format_map(component_info) replacements[write_location].append( {"name": param_name, "process": write, "bool": mapping.get('bool', False), "value": component_info['value']}) out_idx += 1 replacements['output_comps'] = len(replacements['output_parameters']) return replacements ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7502067 hvcc-0.13.3/hvcc/generators/c2daisy/static/README.md0000644000000000000000000001725314435670357016675 0ustar00# Daisy To build this code, navigate into the source folder and run `make`. Flashing can be done over USB with `make program-dfu`. Make sure your Daisy is in DFU mode ([check this out if you're not sure how to do that](https://github.com/electro-smith/DaisyWiki/wiki/1.-Setting-Up-Your-Development-Environment#4-Run-the-Blink-Example)). If you have an ST-Link or other JTAG programmer, you can use `make program`. If you've made hardware based on the Daisy Seed or Patch Submodule, you can supply custom json for the board description. # Interacting with the Daisy I/O Each board has a selection of physical I/O that can interact with your PD patch. Most components have an _alias_, which allows you to refer to the same input/output by different names if you have a preference. All names and aliases are _case insensitive_, so you can style them however you like (e.g. `GateIn`). Some components have _variants_, which allow you to interact with them in multiple ways. For example, you can receive a bang from a `Gate In` instead of a float if you add `_trig` to the end of the gate's name (or any of its aliases). So, if a `Gate In`'s name is `gatein1`, you would use `gatein1_trig`. Here's what each component expects for its default behavior and variants: | Type (_variant) | Behavior | | --- | --- | | **Inputs** | --- | | Voltage Input | Returns a floating point representation of the voltage at its input. The typical range is 0-5 V, which is represented as 0-1. | | Bipolar Voltage Input | Similar to a regular voltage input, but can represent negative voltages. | | Switch | Returns a bang on the signal's rising edge (i.e. when the switch is actuated). | | Switch (_press) | Returns a float representing the current state (1 = pressed, 0 = not pressed) | | Switch (_fall) | Returns a bang on the signal's falling edge (i.e. when the switch is released). | | Switch (_seconds) | Returns a float representing the number of seconds the switch has been held down. | | SPDT Switch | Returns a float representing the current state, either 0 or 1. | | Encoder | Returns a 1 if turned one direction, -1 if turned in the other, and 0 otherwise. | | Encoder (\_rise) | Returns a bang when the encoder is pressed. The special alias _EncSwitch_ is always bound to this. | | Encoder (_press) | Same as switch _press. | | Encoder (_fall) | Same as switch _fall. | | Encoder (_seconds) | Same as switch _seconds. | | Gate In | Returns a float representing the current gate voltage, where a _high_ voltage is 1 and a _low_ voltage is 0. | | Gate In (_trig) | Returns a bang on the rising edge of the gate signal. | | **Outputs** | --- | | CV Out | Expects a floating point value from 0-1, usually converted to 0-5V. | | Gate Out | Expects a floating point value from 0-1. 0 sets the output low, and 1 sets it high. | | LED | Expects a floating point value from 0-1. The brightness is PWM modulated to match the input. | | RGB LED | Expects a floating point value from 0-1. The default behavior sets all three colors to the same brightness. | | RGB LED (_white) | Same as default. | | RGB LED (_red) | Expects a floating point value from 0-1. Sets the brightness of the red LED only. | | RGB LED (_green) | Expects a floating point value from 0-1. Sets the brightness of the green LED only. | | RGB LED (_blue) | Expects a floating point value from 0-1. Sets the brightness of the blue LED only. | # Daisy Board I/O ## patch | Name | Aliases | Type | Variants | | --- | --- | --- | --- | | knob1 | knob, ctrl, ctrl1 | Voltage Input | --- | | knob2 | ctrl2 | Voltage Input | --- | | knob3 | ctrl3 | Voltage Input | --- | | knob4 | ctrl4 | Voltage Input | --- | | encoder | --- | Encoder | encoder_press, encoder_rise, encoder_fall, encoder_seconds | | gateout | --- | Gate Out | --- | | cvout1 | cvout | CV Out | --- | | cvout2 | --- | CV Out | --- | | gatein1 | gate, gate1 | Gate In | gatein1_trig | | gatein2 | gate2 | Gate In | gatein2_trig | ## patch_init | Name | Aliases | Type | Variants | | --- | --- | --- | --- | | cv_1 | knob, knob1, ctrl, ctrl1 | Voltage Input | --- | | cv_2 | knob2, ctrl2 | Voltage Input | --- | | cv_3 | knob3, ctrl3 | Voltage Input | --- | | cv_4 | knob4, ctrl4 | Voltage Input | --- | | cv_5 | knob5, ctrl5 | Voltage Input | --- | | cv_6 | knob6, ctrl6 | Voltage Input | --- | | cv_7 | knob7, ctrl7 | Voltage Input | --- | | cv_8 | knob8, ctrl8 | Voltage Input | --- | | adc_9 | --- | Voltage Input | --- | | adc_10 | --- | Voltage Input | --- | | adc_11 | --- | Voltage Input | --- | | adc_12 | --- | Voltage Input | --- | | gate_out_1 | gateout, gateout1 | Gate Out | --- | | gate_out_2 | gateout2 | Gate Out | --- | | cvout1 | cvout, cv_out_1 | CV Out | --- | | cvout2 | cv_out_2 | CV Out | --- | | gate_in_1 | gate, gate1 | Gate In | gate_in_1_trig | | gate_in_2 | gate2 | Gate In | gate_in_2_trig | | sw1 | switch, switch1, button | Switch | sw1_press, sw1_fall, sw1_seconds | | sw2 | switch2, toggle | Switch | sw2_press, sw2_fall, sw2_seconds | ## petal | Name | Aliases | Type | Variants | | --- | --- | --- | --- | | sw1 | switch, switch1 | Switch | sw1_press, sw1_fall, sw1_seconds | | sw2 | switch2 | Switch | sw2_press, sw2_fall, sw2_seconds | | sw3 | switch3 | Switch | sw3_press, sw3_fall, sw3_seconds | | sw4 | switch4 | Switch | sw4_press, sw4_fall, sw4_seconds | | sw5 | switch5 | Switch | sw5_press, sw5_fall, sw5_seconds | | sw6 | switch6 | Switch | sw6_press, sw6_fall, sw6_seconds | | sw7 | switch7 | Switch | sw7_press, sw7_fall, sw7_seconds | | encoder | --- | Encoder | encoder_press, encoder_rise, encoder_fall, encoder_seconds | | knob1 | knob, ctrl, ctrl1 | Voltage Input | --- | | knob2 | ctrl2 | Voltage Input | --- | | knob3 | ctrl3 | Voltage Input | --- | | knob4 | ctrl4 | Voltage Input | --- | | knob5 | ctrl5 | Voltage Input | --- | | knob6 | ctrl6 | Voltage Input | --- | | expression | --- | Voltage Input | --- | | led_ring_1 ... led_ring_8 | --- | RGB LED | led_ring_1_red, led_ring_1_green, led_ring_1_blue, led_ring_1_white | | led_fs_1 | --- | LED | --- | | led_fs_2 | --- | LED | --- | | led_fs_3 | --- | LED | --- | | led_fs_4 | --- | LED | --- | ## pod | Name | Aliases | Type | Variants | | --- | --- | --- | --- | | sw1 | switch, button, switch1, button1 | Switch | sw1_press, sw1_fall, sw1_seconds | | sw2 | switch2, button2 | Switch | sw2_press, sw2_fall, sw2_seconds | | knob1 | knob, ctrl, ctrl1 | Voltage Input | --- | | knob2 | ctrl2 | Voltage Input | --- | | encoder | --- | Encoder | encoder_press, encoder_rise, encoder_fall, encoder_seconds | | led1 | led | RGB LED | led1_red, led1_green, led1_blue, led1_white | | led2 | --- | RGB LED | led2_red, led2_green, led2_blue, led2_white | | led3 | --- | LED | --- | | cvout1 | cvout | CV Out | --- | | gatein | gate, gate1 | Gate In | gatein_trig | | sw3 | switch3 | SPDT Switch | --- | ## field | Name | Aliases | Type | Variants | | --- | --- | --- | --- | | sw1 | switch, button, switch1, button1 | Switch | sw1_press, sw1_fall, sw1_seconds | | sw2 | switch2, button2 | Switch | sw2_press, sw2_fall, sw2_seconds | | cv1 | --- | Bipolar Voltage Input | --- | | cv2 | --- | Bipolar Voltage Input | --- | | cv3 | --- | Bipolar Voltage Input | --- | | cv4 | --- | Bipolar Voltage Input | --- | | knob1 | knob, ctrl, ctrl1 | Voltage Input | --- | | knob2 | ctrl2 | Voltage Input | --- | | knob3 ... knob8 | --- | Voltage Input | --- | | cvout1 | cvout | CV Out | --- | | cvout2 | --- | CV Out | --- | | gatein | --- | Gate In | gatein_trig | | gateout | --- | Gate Out | --- | | pada1 ... pada8 | --- | Switch | pada1_press, pada1_fall | | padb1 ... padb8 | --- | Switch | padb1_press, padb1_fall | | led_key_a1 ... led_key_a8 | --- | LED | --- | | led_key_b1 ... led_key_b8 | --- | LED | --- | | led_knob_1 ... led_knob_8 | --- | LED | --- | | led_sw_1 | --- | LED | --- | | led_sw_2 | --- | LED | --- | ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739952989.4286463 hvcc-0.13.3/hvcc/generators/c2daisy/templates/HeavyDaisy.cpp0000644000000000000000000003655514755311535020700 0ustar00{{copyright}} #include "Heavy_{{patch_name}}.h" #include "Heavy_{{patch_name}}.hpp" #include "HeavyDaisy_{{patch_name}}.hpp" #define SAMPLE_RATE {{samplerate}}.f {% if (has_midi is sameas true) or (usb_midi is sameas true) %} #define HV_HASH_NOTEIN 0x67E37CA3 #define HV_HASH_CTLIN 0x41BE0f9C #define HV_HASH_POLYTOUCHIN 0xBC530F59 #define HV_HASH_PGMIN 0x2E1EA03D #define HV_HASH_TOUCHIN 0x553925BD #define HV_HASH_BENDIN 0x3083F0F7 #define HV_HASH_MIDIIN 0x149631bE #define HV_HASH_MIDIREALTIMEIN 0x6FFF0BCF #define HV_HASH_NOTEOUT 0xD1D4AC2 #define HV_HASH_CTLOUT 0xE5e2A040 #define HV_HASH_POLYTOUCHOUT 0xD5ACA9D1 #define HV_HASH_PGMOUT 0x8753E39E #define HV_HASH_TOUCHOUT 0x476D4387 #define HV_HASH_BENDOUT 0xE8458013 #define HV_HASH_MIDIOUT 0x6511DE55 #define HV_HASH_MIDIOUTPORT 0x165707E4 #define MIDI_RT_CLOCK 0xF8 #define MIDI_RT_START 0xFA #define MIDI_RT_CONTINUE 0xFB #define MIDI_RT_STOP 0xFC #define MIDI_RT_ACTIVESENSE 0xFE #define MIDI_RT_RESET 0xFF #define MIDI_OUT_FIFO_SIZE 128 {% endif %} using namespace daisy; json2daisy::Daisy{{ class_name|capitalize }} hardware; Heavy_{{patch_name}}* hv; void audiocallback(daisy::AudioHandle::InputBuffer in, daisy::AudioHandle::OutputBuffer out, size_t size); static void sendHook(HeavyContextInterface *c, const char *receiverName, uint32_t receiverHash, const HvMessage * m); {% if debug_printing is sameas true %} static void printHook(HeavyContextInterface *c, const char *printLabel, const char *msgString, const HvMessage *m); /** FIFO to hold messages as we're ready to print them */ FIFO, 64> event_log; {% elif usb_midi is sameas true %} daisy::MidiUsbHandler midiusb; {% endif %} {% if (has_midi is sameas true) or (usb_midi is sameas true) %} FIFO midi_tx_fifo; {% endif %} // int midiOutCount; // uint8_t* midiOutData; void CallbackWriteIn(Heavy_{{patch_name}}* hv); void LoopWriteIn(Heavy_{{patch_name}}* hv); void CallbackWriteOut(); void LoopWriteOut(); void PostProcess(); void Display(); {% if output_parameters|length > 0 %} constexpr int DaisyNumOutputParameters = {{output_parameters|length}}; /** This array holds the output values received from PD hooks. These values are * then written at the appropriate time in the following callback or loop. */ float output_data[DaisyNumOutputParameters]; struct DaisyHvParamOut { uint32_t hash; uint32_t index; void (*hook_write_out)(float); void Process(float sig) { output_data[index] = sig; if (hook_write_out) (*hook_write_out)(sig); } }; {% for param in hook_write_out %} void {{param.name}}_hook(float sig) { {{param.process}} }; {% endfor %} DaisyHvParamOut DaisyOutputParameters[DaisyNumOutputParameters] = { {% for param in output_parameters %} {% if param.hook %} { (uint32_t) HV_{{patch_name|upper}}_PARAM_OUT_{{param.hash_enum|upper}}, {{param.index}}, &{{param.name}}_hook }, // {{param.name}} {% else %} { (uint32_t) HV_{{patch_name|upper}}_PARAM_OUT_{{param.hash_enum|upper}}, {{param.index}}, nullptr }, // {{param.name}} {% endif %} {% endfor %} }; {% endif %} {% if (has_midi is sameas true) or (usb_midi is sameas true) %} // Typical Switch case for Message Type. void HandleMidiMessage(MidiEvent m) { ScopedIrqBlocker block; //< Disables interrupts while in scope for (int i = 0; i <= 2; ++i) { hv->sendMessageToReceiverV(HV_HASH_MIDIIN, 0, "ff", (float) m.data[i], (float) m.channel); } switch(m.type) { case SystemRealTime: { float srtType; switch(m.srt_type) { case TimingClock: srtType = MIDI_RT_CLOCK; break; case Start: srtType = MIDI_RT_START; break; case Continue: srtType = MIDI_RT_CONTINUE; break; case Stop: srtType = MIDI_RT_STOP; break; case ActiveSensing: srtType = MIDI_RT_ACTIVESENSE; break; case Reset: srtType = MIDI_RT_RESET; break; } hv->sendMessageToReceiverV(HV_HASH_MIDIREALTIMEIN, 0, "ff", (float) srtType); break; } case NoteOff: { NoteOnEvent p = m.AsNoteOn(); hv->sendMessageToReceiverV(HV_HASH_NOTEIN, 0, "fff", (float) p.note, // pitch (float) 0, // velocity (float) p.channel); break; } case NoteOn: { NoteOnEvent p = m.AsNoteOn(); hv->sendMessageToReceiverV(HV_HASH_NOTEIN, 0, "fff", (float) p.note, // pitch (float) p.velocity, // velocity (float) p.channel); break; } case PolyphonicKeyPressure: { // polyphonic aftertouch PolyphonicKeyPressureEvent p = m.AsPolyphonicKeyPressure(); hv->sendMessageToReceiverV(HV_HASH_POLYTOUCHIN, 0, "fff", (float) p.pressure, // pressure (float) p.note, // note (float) p.channel); break; } case ControlChange: { ControlChangeEvent p = m.AsControlChange(); hv->sendMessageToReceiverV(HV_HASH_CTLIN, 0, "fff", (float) p.value, // value (float) p.control_number, // cc number (float) p.channel); break; } case ProgramChange: { ProgramChangeEvent p = m.AsProgramChange(); hv->sendMessageToReceiverV(HV_HASH_PGMIN, 0, "ff", (float) p.program, (float) p.channel); break; } case ChannelPressure: { ChannelPressureEvent p = m.AsChannelPressure(); hv->sendMessageToReceiverV(HV_HASH_TOUCHIN, 0, "ff", (float) p.pressure, (float) p.channel); break; } case PitchBend: { PitchBendEvent p = m.AsPitchBend(); // combine 7bit lsb and msb into 32bit int hv_uint32_t value = (((hv_uint32_t) m.data[1]) << 7) | ((hv_uint32_t) m.data[0]); hv->sendMessageToReceiverV(HV_HASH_BENDIN, 0, "ff", (float) value, (float) p.channel); break; } default: break; } } {% endif %} int main(void) { hardware.Init(true); hv = new Heavy_{{patch_name}}(SAMPLE_RATE, {{pool_sizes_kb.internal}}, {{pool_sizes_kb.inputQueue}}, {{pool_sizes_kb.outputQueue}}); {% if samplerate %} hardware.SetAudioSampleRate({{samplerate}}); {% endif %} {% if blocksize %} hardware.SetAudioBlockSize({{blocksize}}); {% endif %} {% if has_midi is sameas true %} MidiUartHandler::Config midi_config; hardware.midi.Init(midi_config); hardware.midi.StartReceive(); {% endif %} {% if (debug_printing is not sameas true) and (usb_midi is sameas true) %} MidiUsbHandler::Config midiusb_config; midiusb.Init(midiusb_config); midiusb.StartReceive(); {% endif %} hardware.StartAudio(audiocallback); {% if debug_printing is sameas true %} hardware.som.StartLog(); hv->setPrintHook(printHook); uint32_t now = System::GetNow(); uint32_t log_time = System::GetNow(); {% endif %} hv->setSendHook(sendHook); for(;;) { {% if debug_printing %} now = System::GetNow(); {% endif %} hardware.LoopProcess(); {% if has_midi %} hardware.midi.Listen(); while(hardware.midi.HasEvents()) { HandleMidiMessage(hardware.midi.PopEvent()); } {% endif %} {% if (debug_printing is not sameas true) and (usb_midi is sameas true) %} midiusb.Listen(); while(midiusb.HasEvents()) { HandleMidiMessage(midiusb.PopEvent()); } {% endif %} Display(); {% if loop_write_in|length > 0 %} LoopWriteIn(hv); {% endif %} {% if output_parameters|length > 0 %} LoopWriteOut(); {% endif %} {% if (has_midi is sameas true) or (usb_midi is sameas true) %} uint8_t midiData[MIDI_OUT_FIFO_SIZE]; size_t numElements = 0; while(!midi_tx_fifo.IsEmpty() && numElements < MIDI_OUT_FIFO_SIZE) { midiData[numElements++] = midi_tx_fifo.PopFront(); } if(numElements > 0) { {% if has_midi is sameas true %} hardware.midi.SendMessage(midiData, numElements); {% endif %} {% if (debug_printing is not sameas true) and (usb_midi is sameas true) %} midiusb.SendMessage(midiData, numElements); {% endif %} } {% endif %} {% if debug_printing is sameas true %} /** Now separately, every 5ms we'll print the top message in our queue if there is one */ if(now - log_time > 5) { log_time = now; if(!event_log.IsEmpty()) { auto msg = event_log.PopFront(); hardware.som.PrintLine(msg); } } {% endif %} } } /** The audio processing function. At the standard 48KHz sample rate and a block * size of 48, this will fire every millisecond. */ void audiocallback(daisy::AudioHandle::InputBuffer in, daisy::AudioHandle::OutputBuffer out, size_t size) { {% if num_output_channels == 0 %} // A zero fill to keep I/O quiet for a patch lacking ADC~/DAC~ for (size_t chn = 0; chn < {{max_channels}}; chn++) { for (size_t i = 0; i < size; i++) out[chn][i] = 0; } {% endif %} {% if parameters|length > 0 %} hardware.ProcessAllControls(); CallbackWriteIn(hv); {% endif %} hv->process((float**)in, (float**)out, size); {% if output_parameters|length > 0 %} CallbackWriteOut(); {% endif %} hardware.PostProcess(); } {% if (has_midi is sameas true) or (usb_midi is sameas true) %} void HandleMidiOut(uint8_t *midiData, const uint8_t numElements) { for (int i = 0; i < numElements; i++) { midi_tx_fifo.PushBack(midiData[i]); } } void HandleMidiSend(uint32_t sendHash, const HvMessage *m) { switch(sendHash){ case HV_HASH_NOTEOUT: // __hv_noteout { uint8_t note = hv_msg_getFloat(m, 0); uint8_t velocity = hv_msg_getFloat(m, 1); uint8_t ch = hv_msg_getFloat(m, 2); ch %= 16; // drop any pd "ports" const uint8_t numElements = 3; uint8_t midiData[numElements]; if (velocity > 0){ midiData[0] = 0x90 | ch; // noteon } else { midiData[0] = 0x80 | ch; // noteoff } midiData[1] = note; midiData[2] = velocity; HandleMidiOut(midiData, numElements); break; } case HV_HASH_POLYTOUCHOUT: { uint8_t value = hv_msg_getFloat(m, 0); uint8_t note = hv_msg_getFloat(m, 1); uint8_t ch = hv_msg_getFloat(m, 2); ch %= 16; // drop any pd "ports" const uint8_t numElements = 3; uint8_t midiData[numElements]; midiData[0] = 0xA0 | ch; // send Poly Aftertouch midiData[1] = note; midiData[2] = value; HandleMidiOut(midiData, numElements); break; } case HV_HASH_CTLOUT: { uint8_t value = hv_msg_getFloat(m, 0); uint8_t cc = hv_msg_getFloat(m, 1); uint8_t ch = hv_msg_getFloat(m, 2); ch %= 16; const uint8_t numElements = 3; uint8_t midiData[numElements]; midiData[0] = 0xB0 | ch; // send CC midiData[1] = cc; midiData[2] = value; HandleMidiOut(midiData, numElements); break; } case HV_HASH_PGMOUT: { uint8_t pgm = hv_msg_getFloat(m, 0); uint8_t ch = hv_msg_getFloat(m, 1); ch %= 16; const uint8_t numElements = 2; uint8_t midiData[numElements]; midiData[0] = 0xC0 | ch; // send Program Change midiData[1] = pgm; HandleMidiOut(midiData, numElements); break; } case HV_HASH_TOUCHOUT: { uint8_t value = hv_msg_getFloat(m, 0); uint8_t ch = hv_msg_getFloat(m, 1); ch %= 16; const uint8_t numElements = 2; uint8_t midiData[numElements]; midiData[0] = 0xD0 | ch; // send Touch midiData[1] = value; HandleMidiOut(midiData, numElements); break; } case HV_HASH_BENDOUT: { uint16_t value = hv_msg_getFloat(m, 0); uint8_t lsb = value & 0x7F; uint8_t msb = (value >> 7) & 0x7F; uint8_t ch = hv_msg_getFloat(m, 1); ch %= 16; const uint8_t numElements = 3; uint8_t midiData[numElements]; midiData[0] = 0xE0 | ch; // send Bend midiData[1] = lsb; midiData[2] = msb; HandleMidiOut(midiData, numElements); break; } // not functional yet // case HV_HASH_MIDIOUT: // __hv_midiout // { // if (midiOutCount == 0 ) { // uint8_t midiOutData[3]; // } // midiOutData[midiOutCount] = hv_msg_getFloat(m, 0); // if (midiOutCount < 2) { // midiOutCount++; // break; // } // HandleMidiOut(midiOutData, 3); // midiOutCount = 0; // break; // } default: break; } } {% endif %} /** Receives messages from PD and writes them to the appropriate * index in the `output_data` array, to be written later. */ static void sendHook(HeavyContextInterface *c, const char *receiverName, uint32_t receiverHash, const HvMessage * m) { {% if output_parameters|length > 0 %} for (int i = 0; i < DaisyNumOutputParameters; i++) { if (DaisyOutputParameters[i].hash == receiverHash) { DaisyOutputParameters[i].Process(msg_getFloat(m, 0)); } } {% endif %} {% if (has_midi is sameas true) or (usb_midi is sameas true) %} HandleMidiSend(receiverHash, m); {% endif %} } {% if debug_printing is sameas true %} /** Receives messages from the PD [print] object and writes them to the serial console. * */ static void printHook(HeavyContextInterface *c, const char *printLabel, const char *msgString, const HvMessage *m) { char buf[64]; char *dst = buf; int len = strnlen(printLabel, 48); dst = stpncpy(dst, printLabel, len); dst = stpcpy(dst, " "); dst = stpncpy(dst, msgString, 63-len); /** Regardless of message, let's add the message data to our queue to output */ event_log.PushBack(buf); } {% endif %} /** Sends signals from the Daisy hardware to the PD patch via the receive objects during the main loop * */ void LoopWriteIn(Heavy_{{patch_name}}* hv) { ScopedIrqBlocker block; //< Disables interrupts while in scope {% for param in loop_write_in %} {% if param.bool %} if ({{param.process}}) hv->sendBangToReceiver((uint32_t) HV_{{patch_name|upper}}_PARAM_IN_{{param.hash_enum|upper}}); {% else %} hv->sendFloatToReceiver((uint32_t) HV_{{patch_name|upper}}_PARAM_IN_{{param.hash_enum|upper}}, {{param.process}}); {% endif %} {% endfor %} } /** Sends signals from the Daisy hardware to the PD patch via the receive objects during the audio callback * */ void CallbackWriteIn(Heavy_{{patch_name}}* hv) { {% for param in callback_write_in %} {% if param.bool %} if ({{param.process}}) hv->sendBangToReceiver((uint32_t) HV_{{patch_name|upper}}_PARAM_IN_{{param.hash_enum|upper}}); {% else %} hv->sendFloatToReceiver((uint32_t) HV_{{patch_name|upper}}_PARAM_IN_{{param.hash_enum|upper}}, {{param.process}}); {% endif %} {% endfor %} } /** Writes the values sent to PD's receive objects to the Daisy hardware during the main loop * */ void LoopWriteOut() { ScopedIrqBlocker block; //< Disables interrupts while in scope {% for param in loop_write_out %} {% if param.bool %} if ({{param.value}}) {{param.process}} {% else %} {{param.process}} {% endif %} {% endfor %} } /** Writes the values sent to PD's receive objects to the Daisy hardware during the audio callback * */ void CallbackWriteOut() { {% for param in callback_write_out %} {% if param.bool %} if ({{param.value}}) {{param.process}} {% else %} {{param.process}} {% endif %} {% endfor %} } /** Handles the display code if the hardware defines a display * */ void Display() { {{displayprocess}} } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.263823 hvcc-0.13.3/hvcc/generators/c2daisy/templates/Makefile0000644000000000000000000000077714735300474017561 0ustar00# Project Name TARGET = HeavyDaisy_{{name}} # Library Locations LIBDAISY_DIR = {{libdaisy_path}} {% if linker_script != '' %} LDSCRIPT = {{linker_script}} {% endif %} {% if bootloader != None %} APP_TYPE = {{bootloader}} {% endif %} {% if debug_printing is sameas true %} LDFLAGS += -u _printf_float {% endif %} # Project Source C_SOURCES = $(wildcard *.c) CPP_SOURCES = $(wildcard *.cpp) # Core location, and generic makefile. SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core include $(SYSTEM_FILES_DIR)/Makefile ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7512066 hvcc-0.13.3/hvcc/generators/c2dpf/__init__.py0000644000000000000000000000000014435670357015656 0ustar00././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.263823 hvcc-0.13.3/hvcc/generators/c2dpf/c2dpf.py0000644000000000000000000001446414735300474015131 0ustar00# Copyright (C) 2021-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os import shutil import time import jinja2 from typing import Optional from ..copyright import copyright_manager from ..filters import filter_uniqueid from hvcc.interpreters.pd2hv.NotificationEnum import NotificationEnum from hvcc.types.compiler import Generator, CompilerResp, CompilerMsg, CompilerNotif, ExternInfo from hvcc.types.meta import Meta, DPF class c2dpf(Generator): """ Generates a DPF wrapper for a given patch. """ @classmethod def compile( cls, c_src_dir: str, out_dir: str, externs: ExternInfo, patch_name: Optional[str] = None, patch_meta: Meta = Meta(), num_input_channels: int = 0, num_output_channels: int = 0, copyright: Optional[str] = None, verbose: Optional[bool] = False ) -> CompilerResp: tick = time.time() out_dir = os.path.join(out_dir, "plugin") receiver_list = externs.parameters.inParam sender_list = externs.parameters.outParam dpf_meta: DPF = patch_meta.dpf dpf_path = dpf_meta.dpf_path copyright_c = copyright_manager.get_copyright_for_c(copyright) try: # ensure that the output directory does not exist out_dir = os.path.abspath(out_dir) if os.path.exists(out_dir): shutil.rmtree(out_dir) # copy over static files shutil.copytree(os.path.join(os.path.dirname(__file__), "static"), out_dir) shutil.copy(os.path.join(os.path.dirname(__file__), "static/README.md"), f'{out_dir}/../') # copy over generated C source files source_dir = os.path.join(out_dir, "source") shutil.copytree(c_src_dir, source_dir) # initialize the jinja template environment env = jinja2.Environment() env.filters["uniqueid"] = filter_uniqueid env.loader = jinja2.FileSystemLoader( os.path.join(os.path.dirname(os.path.abspath(__file__)), "templates")) # generate DPF wrapper from template dpf_h_path = os.path.join(source_dir, f"HeavyDPF_{patch_name}.hpp") with open(dpf_h_path, "w") as f: f.write(env.get_template("HeavyDPF.hpp").render( name=patch_name, meta=dpf_meta, class_name=f"HeavyDPF_{patch_name}", num_input_channels=num_input_channels, num_output_channels=num_output_channels, receivers=receiver_list, senders=sender_list, copyright=copyright_c)) dpf_cpp_path = os.path.join(source_dir, f"HeavyDPF_{patch_name}.cpp") with open(dpf_cpp_path, "w") as f: f.write(env.get_template("HeavyDPF.cpp").render( name=patch_name, meta=dpf_meta, class_name=f"HeavyDPF_{patch_name}", num_input_channels=num_input_channels, num_output_channels=num_output_channels, receivers=receiver_list, senders=sender_list, pool_sizes_kb=externs.memoryPoolSizesKb, copyright=copyright_c)) if dpf_meta.enable_ui: dpf_ui_path = os.path.join(source_dir, f"HeavyDPF_{patch_name}_UI.cpp") with open(dpf_ui_path, "w") as f: f.write(env.get_template("HeavyDPF_UI.cpp").render( name=patch_name, meta=dpf_meta, class_name=f"HeavyDPF_{patch_name}", receivers=receiver_list, senders=sender_list, copyright=copyright_c)) dpf_h_path = os.path.join(source_dir, "DistrhoPluginInfo.h") with open(dpf_h_path, "w") as f: f.write(env.get_template("DistrhoPluginInfo.h").render( name=patch_name, meta=dpf_meta, class_name=f"HeavyDPF_{patch_name}", num_input_channels=num_input_channels, num_output_channels=num_output_channels, pool_sizes_kb=externs.memoryPoolSizesKb, copyright=copyright_c)) # plugin makefile with open(os.path.join(source_dir, "Makefile"), "w") as f: f.write(env.get_template("Makefile_plugin").render( name=patch_name, meta=dpf_meta, nosimd=patch_meta.nosimd, dpf_path=dpf_path)) # project makefile with open(os.path.join(source_dir, "../../Makefile"), "w") as f: f.write(env.get_template("Makefile_project").render( name=patch_name, meta=dpf_meta, dpf_path=dpf_path)) return CompilerResp( stage="c2dpf", in_dir=c_src_dir, out_dir=out_dir, out_file=os.path.basename(dpf_h_path), compile_time=time.time() - tick ) except Exception as e: return CompilerResp( stage="c2dpf", notifs=CompilerNotif( has_error=True, exception=e, warnings=[], errors=[CompilerMsg( enum=NotificationEnum.ERROR_EXCEPTION, message=str(e) )] ), in_dir=c_src_dir, out_dir=out_dir, compile_time=time.time() - tick ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2655523 hvcc-0.13.3/hvcc/generators/c2dpf/static/README.md0000644000000000000000000000205714677551203016325 0ustar00# Distrho Plugin Format This output is for the Distrho Plugin Format ([DPF](https://github.com/DISTRHO/DPF)), and can be used to build LV2, VST2 and jack standalone versions of your Heavy code. # Build Instructions Make sure you have a (recent) DPF in the root of your output directory ```bash $ cd $ git clone https://github.com/DISTRHO/DPF.git dpf ``` Then compile the plugins from the source folder: ```bash $ make ``` This will result in an `bin/` folder with all binary assets. * LV2 - move `bin/.lv2/` folder to your local `~/.lv2/` dir * VST2 - move `bin/-vst.so`, can be placed directly into your `~/.vst/` dir ## Metadata You will likely want to add more configuration options to your project. Create a json file as described in the [documentation](https://wasted-audio.github.io/hvcc/docs/03.gen.dpf.html#metadata). ## Jack The Jack binary can be executed in place and used to test functionality `./bin/`. Currently there is no UI, so this is not recommended. You will have to be running jack in order to use this. ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.263823 hvcc-0.13.3/hvcc/generators/c2dpf/templates/DistrhoPluginInfo.h0000644000000000000000000000454214735300474021333 0ustar00{{copyright}} #pragma once #define DISTRHO_PLUGIN_NAME "{{name.replace('_', ' ')}}" {%- if meta.plugin_uri != None %} #define DISTRHO_PLUGIN_URI "{{meta.plugin_uri}}" {% else %} #define DISTRHO_PLUGIN_URI "urn:hvcc:{{name}}" {%- endif %} {%- if meta.plugin_clap_id != None %} #define DISTRHO_PLUGIN_CLAP_ID "{{meta.plugin_clap_id}}" {% else %} #define DISTRHO_PLUGIN_CLAP_ID "urn.hvcc.{{name}}" {%- endif %} #define DISTRHO_PLUGIN_NUM_INPUTS {{num_input_channels}} #define DISTRHO_PLUGIN_NUM_OUTPUTS {{num_output_channels}} #define DISTRHO_PLUGIN_IS_SYNTH {{1 if num_output_channels > 0 and meta.midi_input > 0 else 0}} #define DISTRHO_PLUGIN_HAS_UI {{1 if meta.enable_ui is sameas true else 0}} #define DISTRHO_PLUGIN_IS_RT_SAFE 1 #define DISTRHO_PLUGIN_WANT_PROGRAMS 0 #define DISTRHO_PLUGIN_WANT_STATE 0 #define DISTRHO_PLUGIN_WANT_TIMEPOS 1 #define DISTRHO_PLUGIN_WANT_FULL_STATE 0 #define DISTRHO_PLUGIN_WANT_MIDI_INPUT {{1 if meta.midi_input is sameas true else 0}} #define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT {{1 if meta.midi_output is sameas true else 0}} {%- if meta.lv2_info != None %} #define DISTRHO_PLUGIN_LV2_CATEGORY "{{meta.lv2_info}}" {%- endif %} {%- if meta.vst3_info != None %} #define DISTRHO_PLUGIN_VST3_CATEGORIES "{{meta.vst3_info}}" {%- endif %} {%- if meta.clap_info|length > 0 %} #define DISTRHO_PLUGIN_CLAP_FEATURES "{{ meta.clap_info|join('", "') }}" {%- endif %} // for level monitoring #define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0 {% if meta.enable_ui is sameas true %} // if you are using a UI you'll probably want to modify these settings to your needs #define DISTRHO_UI_USE_CUSTOM 1 #define DISTRHO_UI_CUSTOM_INCLUDE_PATH "DearImGui.hpp" #define DISTRHO_UI_CUSTOM_WIDGET_TYPE DGL_NAMESPACE::ImGuiTopLevelWidget {%- if meta.ui_size != None %} #define DISTRHO_UI_DEFAULT_WIDTH {{meta.ui_size.width}} #define DISTRHO_UI_DEFAULT_HEIGHT {{meta.ui_size.height}} {% else %} #define DISTRHO_UI_DEFAULT_WIDTH 400 #define DISTRHO_UI_DEFAULT_HEIGHT 400 {%- endif %} {%- endif %} {%- if meta.enable_modgui is sameas true %} #undef DISTRHO_PLUGIN_USES_MODGUI #define DISTRHO_PLUGIN_USES_MODGUI 1 {%- endif %} ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.264823 hvcc-0.13.3/hvcc/generators/c2dpf/templates/HeavyDPF.cpp0000644000000000000000000001504114735300474017661 0ustar00{{copyright}} #include "Heavy_{{name}}.h" #include "{{class_name}}.hpp" #include {% if meta.denormals is sameas false %} #include "extra/ScopedDenormalDisable.hpp" {% endif %} #define HV_DPF_NUM_PARAMETER {{receivers|length + senders|length}} #define HV_HASH_NOTEIN 0x67E37CA3 #define HV_HASH_CTLIN 0x41BE0f9C #define HV_HASH_POLYTOUCHIN 0xBC530F59 #define HV_HASH_PGMIN 0x2E1EA03D #define HV_HASH_TOUCHIN 0x553925BD #define HV_HASH_BENDIN 0x3083F0F7 #define HV_HASH_MIDIIN 0x149631bE #define HV_HASH_MIDIREALTIMEIN 0x6FFF0BCF #define HV_HASH_NOTEOUT 0xD1D4AC2 #define HV_HASH_CTLOUT 0xE5e2A040 #define HV_HASH_POLYTOUCHOUT 0xD5ACA9D1 #define HV_HASH_PGMOUT 0x8753E39E #define HV_HASH_TOUCHOUT 0x476D4387 #define HV_HASH_BENDOUT 0xE8458013 #define HV_HASH_MIDIOUT 0x6511DE55 #define HV_HASH_MIDIOUTPORT 0x165707E4 #define MIDI_RT_CLOCK 0xF8 #define MIDI_RT_START 0xFA #define MIDI_RT_CONTINUE 0xFB #define MIDI_RT_STOP 0xFC #define MIDI_RT_ACTIVESENSE 0xFE #define MIDI_RT_RESET 0xFF #define HV_HASH_DPF_BPM 0xDF8C2721 // midi realtime messages std::set mrtSet { MIDI_RT_CLOCK, MIDI_RT_START, MIDI_RT_CONTINUE, MIDI_RT_STOP, MIDI_RT_RESET }; START_NAMESPACE_DISTRHO // ------------------------------------------------------------------- // Heavy Send and Print hooks static void hvSendHookFunc(HeavyContextInterface *c, const char *sendName, uint32_t sendHash, const HvMessage *m) { {{class_name}}* plugin = ({{class_name}}*)c->getUserData(); if (plugin != nullptr) { plugin->setOutputParameter(sendHash, m); {%- if meta.midi_output is sameas true %} #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT plugin->handleMidiSend(sendHash, m); #endif {% endif %} } } static void hvPrintHookFunc(HeavyContextInterface *c, const char *printLabel, const char *msgString, const HvMessage *m) { char buf[64]; char* dst = buf; int len = strnlen(printLabel, 48); dst = strncpy(dst, printLabel, len); dst = strcpy(dst, " "); dst = strncpy(dst, msgString, 63-len); printf("> %s \n", buf); } // ------------------------------------------------------------------- // Main DPF plugin class {{class_name}}::{{class_name}}() : Plugin(HV_DPF_NUM_PARAMETER, 0, 0) { {% for k, v in receivers + senders -%} _parameters[{{loop.index-1}}] = {{v.attributes.default}}f; {% endfor %} _context = hv_{{name}}_new_with_options(getSampleRate(), {{pool_sizes_kb.internal}}, {{pool_sizes_kb.inputQueue}}, {{pool_sizes_kb.outputQueue}}); _context->setUserData(this); _context->setSendHook(&hvSendHookFunc); _context->setPrintHook(&hvPrintHookFunc); {% if receivers|length > 0 %} // ensure that the new context has the current parameters for (int i = 0; i < HV_DPF_NUM_PARAMETER; ++i) { setParameterValue(i, _parameters[i]); } {%- endif %} } {{class_name}}::~{{class_name}}() { hv_{{name}}_free(_context); } {%- if meta.port_groups != None %} {% include 'portGroups.cpp' %} {%- endif %} void {{class_name}}::initParameter(uint32_t index, Parameter& parameter) { {%- if (receivers|length > 0) or (senders|length > 0) -%} // initialise parameters with defaults switch (index) { {% for k, v in receivers + senders %} {% include 'initParameter.cpp' %} {% endfor -%} } {% endif %} } // ------------------------------------------------------------------- // Internal data float {{class_name}}::getParameterValue(uint32_t index) const { {%- if (receivers|length > 0) or (senders|length > 0) %} return _parameters[index]; {% else %} return 0.0f; {%- endif %} } void {{class_name}}::setParameterValue(uint32_t index, float value) { {%- if receivers|length > 0 %} switch (index) { {% for k, v in receivers -%} case {{loop.index-1}}: { _context->sendFloatToReceiver( Heavy_{{name}}::Parameter::In::{{k|upper}}, value); break; } {% endfor %} default: return; } _parameters[index] = value; {% else %} // nothing to do {%- endif %} } void {{class_name}}::setOutputParameter(uint32_t sendHash, const HvMessage *m) { {%- if senders|length > 0 %} switch (sendHash) { {% for k, v in senders -%} case {{v.hash}}: // {{v.display}} _parameters[param{{v.display}}] = hv_msg_getFloat(m, 0); break; {% endfor %} } {%- endif %} } // ------------------------------------------------------------------- // Process // void {{class_name}}::activate() // { // } // void {{class_name}}::deactivate() // { // } {%- if meta.midi_input is sameas true %} #if DISTRHO_PLUGIN_WANT_MIDI_INPUT {% include 'midiInput.cpp' %} #endif {% endif %} {%- if meta.midi_output is sameas true %} #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT {% include 'midiOutput.cpp' %} #endif {% endif %} {% include 'hostTransportEvents.cpp' %} // ------------------------------------------------------------------- // DPF Plugin run() loop #if DISTRHO_PLUGIN_WANT_MIDI_INPUT void {{class_name}}::run(const float** inputs, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) { handleMidiInput(frames, midiEvents, midiEventCount); #else void {{class_name}}::run(const float** inputs, float** outputs, uint32_t frames) { #endif hostTransportEvents(frames); {% if meta.denormals is sameas false %} const ScopedDenormalDisable sdd; {% endif %} const TimePosition& timePos(getTimePosition()); if (timePos.playing && timePos.bbt.valid) _context->sendMessageToReceiverV(HV_HASH_DPF_BPM, 0, "f", timePos.bbt.beatsPerMinute); _context->process((float**)inputs, outputs, frames); } // ------------------------------------------------------------------- // Callbacks void {{class_name}}::sampleRateChanged(double newSampleRate) { hv_{{name}}_free(_context); _context = hv_{{name}}_new_with_options(getSampleRate(), {{pool_sizes_kb.internal}}, {{pool_sizes_kb.inputQueue}}, {{pool_sizes_kb.outputQueue}}); _context->setUserData(this); _context->setSendHook(&hvSendHookFunc); _context->setPrintHook(&hvPrintHookFunc); {% if receivers|length > 0 -%} // ensure that the new context has the current parameters for (int i = 0; i < HV_DPF_NUM_PARAMETER; ++i) { setParameterValue(i, _parameters[i]); } {%- endif %} } // ----------------------------------------------------------------------- /* Plugin entry point, called by DPF to create a new plugin instance. */ Plugin* createPlugin() { return new {{class_name}}(); } // ----------------------------------------------------------------------- END_NAMESPACE_DISTRHO ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.264823 hvcc-0.13.3/hvcc/generators/c2dpf/templates/HeavyDPF.hpp0000644000000000000000000001036114735300474017666 0ustar00{{copyright}} #ifndef _HEAVY_LV2_{{name|upper}}_ #define _HEAVY_LV2_{{name|upper}}_ #include "DistrhoPlugin.hpp" #include "DistrhoPluginInfo.h" #include "Heavy_{{name}}.hpp" START_NAMESPACE_DISTRHO static void hvSendHookFunc(HeavyContextInterface *c, const char *sendName, uint32_t sendHash, const HvMessage *m); static void hvPrintHookFunc(HeavyContextInterface *c, const char *printLabel, const char *msgString, const HvMessage *m); class {{class_name}} : public Plugin { public: enum Parameters { {% for k, v in receivers -%} param{{v.display}}, {% endfor %} {% for k, v in senders -%} param{{v.display}}, {% endfor %} }; {% if meta.port_groups != None %} enum PortGroups { {%- if meta.port_groups.input|length %} {%- for group, value in meta.port_groups.input.items() %} kPortGroup{{group}}, {%- endfor %} {%- endif %} {%- if meta.port_groups.output|length %} {%- for group, value in meta.port_groups.output.items() %} kPortGroup{{group}}, {%- endfor %} {%- endif %} kPortGroupCount }; {%- endif %} {{class_name}}(); ~{{class_name}}() override; void handleMidiInput(uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount); void handleMidiSend(uint32_t sendHash, const HvMessage *m); void hostTransportEvents(uint32_t frames); void setOutputParameter(uint32_t sendHash, const HvMessage *m); protected: // ------------------------------------------------------------------- // Information const char* getLabel() const noexcept override { return "{{name}}"; } {%- if meta.description != None %} const char* getDescription() const override { return "{{meta.description}}"; } {%- endif %} const char* getMaker() const noexcept override { {%- if meta.maker != None %} return "{{meta.maker}}"; {% else %} return "Wasted Audio"; {%- endif %} } {%- if meta.homepage != None %} const char* getHomePage() const override { return "{{meta.homepage}}"; } {%- endif %} const char* getLicense() const noexcept override { {%- if meta.license != None %} return "{{meta.license}}"; {% else %} return "GPL v3+"; {%- endif %} } uint32_t getVersion() const noexcept override { {%- if meta.version != None %} return d_version({{meta.version}}); {% else %} return d_version(0, 0, 1); {%- endif %} } int64_t getUniqueId() const noexcept override { return int64_t( {{class_name|uniqueid}} ); } // ------------------------------------------------------------------- // Init void initParameter(uint32_t index, Parameter& parameter) override; {% if meta.port_groups != None %} void initAudioPort(bool input, uint32_t index, AudioPort& port) override; void initPortGroup(uint32_t groupId, PortGroup& portGroup) override; {%- endif %} // ------------------------------------------------------------------- // Internal data float getParameterValue(uint32_t index) const override; void setParameterValue(uint32_t index, float value) override; // ------------------------------------------------------------------- // Process // void activate() override; // void deactivate() override; #if DISTRHO_PLUGIN_WANT_MIDI_INPUT void run(const float** inputs, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) override; #else void run(const float** inputs, float** outputs, uint32_t frames) override; #endif // ------------------------------------------------------------------- // Callbacks void sampleRateChanged(double newSampleRate) override; // ------------------------------------------------------------------- private: {%- if (receivers|length > 0) or senders|length > 0 %} // parameters float _parameters[{{receivers|length + senders|length}}]; // in range of [0,1] {%- endif %} // transport values bool wasPlaying = false; double nextClockTick = 0.0; double sampleAtCycleStart = 0.0; // midi out buffer int midiOutCount; MidiEvent midiOutEvent; // heavy context HeavyContextInterface *_context; // {{class_name}} f{{name}}; DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR({{class_name}}) }; // ----------------------------------------------------------------------- END_NAMESPACE_DISTRHO #endif // _HEAVY_LV2_{{name|upper}}_ {# newline #} ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.264823 hvcc-0.13.3/hvcc/generators/c2dpf/templates/HeavyDPF_UI.cpp0000644000000000000000000001313714735300474020262 0ustar00{{copyright}} #include "DistrhoUI.hpp" #include "ResizeHandle.hpp" START_NAMESPACE_DISTRHO // -------------------------------------------------------------------------------------------------------------------- {%- if (receivers|length > 0) or (senders|length > 0) %} enum HeavyParams { {%- for k, v in receivers + senders -%} {{v.display|upper}}, {%- endfor %} }; {%- endif %} class ImGuiPluginUI : public UI { {% for k, v in receivers + senders -%} {%- if v.attributes.type == 'bool': %} bool f{{v.display|lower}} = {{v.attributes.default}}f != 0.0f; {%- elif v.attributes.type == 'int': %} int f{{v.display|lower}} = {{v.attributes.default}}; {%- else %} float f{{v.display|lower}} = {{v.attributes.default}}f; {%- endif %} {%- endfor %} ResizeHandle fResizeHandle; // ---------------------------------------------------------------------------------------------------------------- public: /** UI class constructor. The UI should be initialized to a default state that matches the plugin side. */ ImGuiPluginUI() : UI(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT), fResizeHandle(this) { setGeometryConstraints(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT, true); // hide handle if UI is resizable if (isResizable()) fResizeHandle.hide(); } protected: // ---------------------------------------------------------------------------------------------------------------- // DSP/Plugin Callbacks /** A parameter has changed on the plugin side.@n This is called by the host to inform the UI about parameter changes. */ void parameterChanged(uint32_t index, float value) override { {%- if (receivers|length > 0) or (senders|length > 0) %} switch (index) { {% for k, v in receivers + senders -%} case {{v.display|upper}}: {%- if v.attributes.type == 'bool': %} f{{v.display|lower}} = value != 0.0f; {%- else %} f{{v.display|lower}} = value; {%- endif %} break; {% endfor %} default: return; } {% else %} // nothing to do {%- endif %} repaint(); } // ---------------------------------------------------------------------------------------------------------------- // Widget Callbacks /** ImGui specific onDisplay function. */ void onImGuiDisplay() override { const float width = getWidth(); const float height = getHeight(); const float margin = 20.0f * getScaleFactor(); ImGui::SetNextWindowPos(ImVec2(margin, margin)); ImGui::SetNextWindowSize(ImVec2(width - 2 * margin, height - 2 * margin)); if (ImGui::Begin("{{name.replace('_', ' ')}}", nullptr, ImGuiWindowFlags_NoResize + ImGuiWindowFlags_NoCollapse)) { {%- for k, v in receivers + senders %} {%- set v_display = v.display|lower %} {%- if meta.enumerators != None and meta.enumerators[v.display] is defined -%} {%- set enums = meta.enumerators[v.display] -%} {%- set enumlen = enums|length %} {%- set enum_list = v_display + "_list" %} const char* {{enum_list}}[{{enumlen}}] = { {%- for i in enums %} "{{i}}", {%- endfor %} }; if (ImGui::BeginCombo("{{v.display.replace('_', ' ')}}", {{enum_list}}[f{{v_display}}])) { for (int n = 0; n < {{enumlen}}; n++) { bool is_selected = (f{{v_display}} == n); if (ImGui::Selectable({{enum_list}}[n], is_selected)) { f{{v_display}} = n; editParameter({{v.display|upper}}, true); setParameterValue({{v.display|upper}}, f{{v_display}}); } if (is_selected) ImGui::SetItemDefaultFocus(); } ImGui::EndCombo(); } {%- else %} {%- if v.attributes.type == 'bool': %} if (ImGui::Toggle("{{v.display.replace('_', ' ')}}", &f{{v_display}})) {%- elif v.attributes.type == 'int' %} if (ImGui::SliderInt("{{v.display.replace('_', ' ')}}", &f{{v_display}}, {{v.attributes.min}}f, {{v.attributes.max}}f)) {%- else %} if (ImGui::SliderFloat("{{v.display.replace('_', ' ')}}", &f{{v_display}}, {{v.attributes.min}}f, {{v.attributes.max}}f)) {%- endif %} { {%- if not v.type == "send" %} if (ImGui::IsItemActivated()) { editParameter({{v.display|upper}}, true); } setParameterValue({{v.display|upper}}, f{{v_display}}); {%- endif %} } {%- endif %} {% endfor %} if (ImGui::IsItemDeactivated()) { {% for k, v in receivers + senders -%} editParameter({{v.display|upper}}, false); {% endfor -%} } } ImGui::End(); } DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImGuiPluginUI) }; // -------------------------------------------------------------------------------------------------------------------- UI* createUI() { return new ImGuiPluginUI(); } // -------------------------------------------------------------------------------------------------------------------- END_NAMESPACE_DISTRHO ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.264823 hvcc-0.13.3/hvcc/generators/c2dpf/templates/Makefile_plugin0000644000000000000000000000262414735300474020570 0ustar00NAME = {{name}} {%- if meta.enable_modgui is sameas true %} MODGUI_CLASS_NAME = hv_{{name}} {%- endif %} {%- if meta.enable_ui is sameas true %} FILES_DSP = $(filter-out HeavyDPF_{{name}}_UI.cpp, $(wildcard *.cpp)) {%- else %} FILES_DSP = $(wildcard *.cpp) {%- endif %} FILES_DSP += $(wildcard *.c) {%- if meta.enable_ui is sameas true %} FILES_UI = HeavyDPF_{{name}}_UI.cpp FILES_UI += ../../{{dpf_path}}dpf-widgets/opengl/DearImGui.cpp {%- endif %} DPF_TARGET_DIR = ../../bin DPF_BUILD_DIR = ../../build DPF_PATH = ../../{{dpf_path}}dpf include ../../{{dpf_path}}dpf/Makefile.plugins.mk {%- if meta.enable_ui is sameas true %} BUILD_CXX_FLAGS += -I ../../{{dpf_path}}dpf-widgets/generic BUILD_CXX_FLAGS += -I ../../{{dpf_path}}dpf-widgets/opengl {%- endif %} {%- if meta.makefile_dep|length > 0 %} {%- for dependency in meta.makefile_dep %} BUILD_CXX_FLAGS += -I ../../{{dpf_path}}{{dependency}} {%- endfor %} {%- endif %} BUILD_C_FLAGS += -Wno-unused-parameter -std=c11 -fno-strict-aliasing -pthread BUILD_CXX_FLAGS += -Wno-unused-parameter -fno-strict-aliasing -pthread LINK_FLAGS += -pthread {%- if nosimd is sameas true %} BUILD_C_FLAGS += -DHV_SIMD_NONE BUILD_CXX_FLAGS += -DHV_SIMD_NONE {%- endif %} {% if meta.plugin_formats|length > 0 %} {%- for format in meta.plugin_formats %} TARGETS += {{format}} {%- endfor %} {% else %} TARGETS += jack TARGETS += lv2_dsp TARGETS += vst {%- endif %} all: $(TARGETS) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2655523 hvcc-0.13.3/hvcc/generators/c2dpf/templates/Makefile_project0000644000000000000000000000156214677551203020743 0ustar00#!/usr/bin/make -f # Makefile for DISTRHO Plugins # # ---------------------------- # # Created by falkTX # # Modified by Wasted Audio # include {{dpf_path}}dpf/Makefile.base.mk all: plugin gen # -------------------------------------------------------------- dgl: # ifeq ($(HAVE_CAIRO_OR_OPENGL),true) # $(MAKE) -C {{dpf_path}}dpf/dgl FILE_BROWSER_DISABLED=true # endif plugin: dgl $(MAKE) all -C plugin/source ifneq ($(CROSS_COMPILING),true) gen: plugin lv2_ttl_generator @$(CURDIR)/{{dpf_path}}dpf/utils/generate-ttl.sh lv2_ttl_generator: $(MAKE) -C {{dpf_path}}dpf/utils/lv2-ttl-generator else gen: endif # -------------------------------------------------------------- clean: $(MAKE) clean -C {{dpf_path}}dpf/utils/lv2-ttl-generator $(MAKE) clean -C plugin/source rm -rf bin build # -------------------------------------------------------------- .PHONY: plugin ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.264823 hvcc-0.13.3/hvcc/generators/c2dpf/templates/hostTransportEvents.cpp0000644000000000000000000000365414735300474022341 0ustar00// ------------------------------------------------------------------- // Host Transport Events handler void {{class_name}}::hostTransportEvents(uint32_t frames) { // Realtime events const TimePosition& timePos(getTimePosition()); bool reset = false; if (timePos.playing) { if (timePos.frame == 0) { _context->sendMessageToReceiverV(HV_HASH_MIDIREALTIMEIN, 0, "ff", (float) MIDI_RT_RESET, 0.0); reset = true; } if (! this->wasPlaying) { if (timePos.frame == 0) { _context->sendMessageToReceiverV(HV_HASH_MIDIREALTIMEIN, 0, "ff", (float) MIDI_RT_START, 0.0); } if (! reset) { _context->sendMessageToReceiverV(HV_HASH_MIDIREALTIMEIN, 0, "ff", (float) MIDI_RT_CONTINUE, 0.0); } } } else if (this->wasPlaying) { _context->sendMessageToReceiverV(HV_HASH_MIDIREALTIMEIN, 0, "ff", (float) MIDI_RT_STOP, 0.0); } this->wasPlaying = timePos.playing; // sending clock ticks if (timePos.playing && timePos.bbt.valid) { float samplesPerBeat = 60 * getSampleRate() / timePos.bbt.beatsPerMinute; float samplesPerTick = samplesPerBeat / 24.0; /* get state */ double nextClockTick = this->nextClockTick; double sampleAtCycleStart = this->sampleAtCycleStart; double sampleAtCycleEnd = sampleAtCycleStart + frames; if (nextClockTick >= 0 && sampleAtCycleStart >= 0 && sampleAtCycleEnd > sampleAtCycleStart) { while (nextClockTick < sampleAtCycleEnd) { double delayMs = 1000*(nextClockTick - sampleAtCycleStart)/getSampleRate(); if (delayMs >= 0.0) { _context->sendMessageToReceiverV(HV_HASH_MIDIREALTIMEIN, delayMs, "ff", (float) MIDI_RT_CLOCK, 0.0); } nextClockTick += samplesPerTick; } } /* save variables for next cycle */ this->sampleAtCycleStart = sampleAtCycleEnd; this->nextClockTick = nextClockTick; } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.265823 hvcc-0.13.3/hvcc/generators/c2dpf/templates/initParameter.cpp0000644000000000000000000000405414735300474021061 0ustar00 case param{{v.display}}: parameter.name = "{{v.display.replace('_', ' ')}}"; parameter.symbol = "{{v.display|lower}}"; {%- if v.attributes.type == 'db': %} parameter.unit = "dB"; {%- elif v.attributes.type in ['hz', 'log_hz']: %} parameter.unit = "Hz"; {%- endif %} {%- if v.type == "send" %} parameter.hints = kParameterIsOutput {%- else %} parameter.hints = kParameterIsAutomatable {%- endif %} {%- if v.attributes.type == 'bool': %} | kParameterIsBoolean {%- elif v.attributes.type == 'trig': -%} | kParameterIsTrigger {%- elif v.attributes.type == 'int': -%} | kParameterIsInteger {%- elif v.attributes.type in ['log', 'log_hz']: -%} | kParameterIsLogarithmic {%- endif %}; parameter.ranges.min = {{v.attributes.min}}f; parameter.ranges.max = {{v.attributes.max}}f; parameter.ranges.def = {{v.attributes.default}}f; {%- if v.attributes.type == 'db' and not (meta.enumerators != None and meta.enumerators[v.display] is defined): %} { ParameterEnumerationValue* const enumValues = new ParameterEnumerationValue[1]; enumValues[0].value = {{v.attributes.min}}f; enumValues[0].label = "-inf"; parameter.enumValues.count = 1; parameter.enumValues.values = enumValues; } {%- endif %} {%- if meta.enumerators != None and meta.enumerators[v.display] is defined %} {% set enums = meta.enumerators[v.display] %} {% set enumlen = enums|length %} if (ParameterEnumerationValue *values = new ParameterEnumerationValue[{{enumlen}}]) { parameter.enumValues.restrictedMode = true; {% for i in enums -%} values[{{loop.index - 1}}].value = {{loop.index - 1}}.0f; values[{{loop.index - 1}}].label = "{{i}}"; {% endfor -%} parameter.enumValues.count = {{enumlen}}; parameter.enumValues.values = values; } {%- endif %} break; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.265823 hvcc-0.13.3/hvcc/generators/c2dpf/templates/midiInput.cpp0000644000000000000000000000550714735300474020223 0ustar00// ------------------------------------------------------------------- // Midi Input handler void {{class_name}}::handleMidiInput(uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) { // Midi events for (uint32_t i=0; i < midiEventCount; ++i) { int status = midiEvents[i].data[0]; int command = status & 0xF0; int channel = status & 0x0F; int data1 = midiEvents[i].data[1]; int data2 = midiEvents[i].data[2]; // raw [midiin] messages int dataSize = *(&midiEvents[i].data + 1) - midiEvents[i].data; for (int i = 0; i < dataSize; ++i) { _context->sendMessageToReceiverV(HV_HASH_MIDIIN, 1000.0*midiEvents->frame/getSampleRate(), "ff", (float) midiEvents[i].data[i], (float) channel); } if(mrtSet.find(status) != mrtSet.end()) { _context->sendMessageToReceiverV(HV_HASH_MIDIREALTIMEIN, 1000.0*midiEvents->frame/getSampleRate(), "ff", (float) status); } // typical midi messages switch (command) { case 0x80: { // note off _context->sendMessageToReceiverV(HV_HASH_NOTEIN, 1000.0*midiEvents->frame/getSampleRate(), "fff", (float) data1, // pitch (float) 0, // velocity (float) channel); break; } case 0x90: { // note on _context->sendMessageToReceiverV(HV_HASH_NOTEIN, 1000.0*midiEvents->frame/getSampleRate(), "fff", (float) data1, // pitch (float) data2, // velocity (float) channel); break; } case 0xA0: { // polyphonic aftertouch _context->sendMessageToReceiverV(HV_HASH_POLYTOUCHIN, 1000.0*midiEvents->frame/getSampleRate(), "fff", (float) data2, // pressure (float) data1, // note (float) channel); break; } case 0xB0: { // control change _context->sendMessageToReceiverV(HV_HASH_CTLIN, 1000.0*midiEvents->frame/getSampleRate(), "fff", (float) data2, // value (float) data1, // cc number (float) channel); break; } case 0xC0: { // program change _context->sendMessageToReceiverV(HV_HASH_PGMIN, 1000.0*midiEvents->frame/getSampleRate(), "ff", (float) data1, (float) channel); break; } case 0xD0: { // aftertouch _context->sendMessageToReceiverV(HV_HASH_TOUCHIN, 1000.0*midiEvents->frame/getSampleRate(), "ff", (float) data1, (float) channel); break; } case 0xE0: { // pitch bend // combine 7bit lsb and msb into 32bit int hv_uint32_t value = (((hv_uint32_t) data2) << 7) | ((hv_uint32_t) data1); _context->sendMessageToReceiverV(HV_HASH_BENDIN, 1000.0*midiEvents->frame/getSampleRate(), "ff", (float) value, (float) channel); break; } default: break; } } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5911822 hvcc-0.13.3/hvcc/generators/c2dpf/templates/midiOutput.cpp0000644000000000000000000000610414735300037020411 0ustar00// ------------------------------------------------------------------- // Midi Send handler void {{class_name}}::handleMidiSend(uint32_t sendHash, const HvMessage *m) { MidiEvent midiSendEvent; midiSendEvent.frame = 0; midiSendEvent.dataExt = nullptr; switch(sendHash){ case HV_HASH_NOTEOUT: // __hv_noteout { uint8_t note = hv_msg_getFloat(m, 0); uint8_t velocity = hv_msg_getFloat(m, 1); uint8_t ch = hv_msg_getFloat(m, 2); ch %= 16; // drop any pd "ports" midiSendEvent.size = 3; if (velocity > 0){ midiSendEvent.data[0] = 0x90 | ch; // noteon } else { midiSendEvent.data[0] = 0x80 | ch; // noteoff } midiSendEvent.data[1] = note; midiSendEvent.data[2] = velocity; writeMidiEvent(midiSendEvent); break; } case HV_HASH_CTLOUT: { uint8_t value = hv_msg_getFloat(m, 0); uint8_t cc = hv_msg_getFloat(m, 1); uint8_t ch = hv_msg_getFloat(m, 2); ch %= 16; midiSendEvent.size = 3; midiSendEvent.data[0] = 0xB0 | ch; // send CC midiSendEvent.data[1] = cc; midiSendEvent.data[2] = value; writeMidiEvent(midiSendEvent); break; } case HV_HASH_POLYTOUCHOUT: { uint8_t value = hv_msg_getFloat(m, 0); uint8_t note = hv_msg_getFloat(m, 1); uint8_t ch = hv_msg_getFloat(m, 2); midiSendEvent.size = 3; midiSendEvent.data[0] = 0xA0 | ch; // send Poly Aftertouch midiSendEvent.data[1] = note; midiSendEvent.data[2] = value; writeMidiEvent(midiSendEvent); break; } case HV_HASH_PGMOUT: { uint8_t pgm = hv_msg_getFloat(m, 0); uint8_t ch = hv_msg_getFloat(m, 1); ch %= 16; midiSendEvent.size = 2; midiSendEvent.data[0] = 0xC0 | ch; // send Program Change midiSendEvent.data[1] = pgm; writeMidiEvent(midiSendEvent); break; } case HV_HASH_TOUCHOUT: { uint8_t value = hv_msg_getFloat(m, 0); uint8_t ch = hv_msg_getFloat(m, 1); ch %= 16; midiSendEvent.size = 2; midiSendEvent.data[0] = 0xD0 | ch; // send Touch midiSendEvent.data[1] = value; writeMidiEvent(midiSendEvent); break; } case HV_HASH_BENDOUT: { uint16_t value = hv_msg_getFloat(m, 0); uint8_t lsb = value & 0x7F; uint8_t msb = (value >> 7) & 0x7F; uint8_t ch = hv_msg_getFloat(m, 1); ch %= 16; midiSendEvent.size = 3; midiSendEvent.data[0] = 0xE0 | ch; // send Bend midiSendEvent.data[1] = lsb; midiSendEvent.data[2] = msb; writeMidiEvent(midiSendEvent); break; } case HV_HASH_MIDIOUT: // __hv_midiout { if (midiOutCount == 0) { midiOutEvent.frame = 0; midiOutEvent.dataExt = nullptr; // we don't support sysex midiOutEvent.size = 4; } midiOutEvent.data[midiOutCount] = hv_msg_getFloat(m, 0); if (midiOutCount < 3) { midiOutCount++; break; } writeMidiEvent(midiOutEvent); midiOutCount = 0; break; } default: break; } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.265823 hvcc-0.13.3/hvcc/generators/c2dpf/templates/portGroups.cpp0000644000000000000000000000507114735300474020441 0ustar00void {{class_name}}::initAudioPort(bool input, uint32_t index, AudioPort& port) { port.hints = 0x0; if (input) { switch (index) { {%- if meta.port_groups.input|length %} {%- for group, gConfig in meta.port_groups.input.items() %} {%- for port, value in gConfig.items() %} case {{value[0] or value}}: port.name = "Input {{port}} ({{group}})"; port.symbol = "in_{{port|lower}}_{{group|lower}}"; port.groupId = kPortGroup{{group}}; {%- if value[1] is sameas true %} port.hints = kAudioPortIsCV | kCVPortHasPositiveUnipolarRange | kCVPortHasScaledRange | kCVPortIsOptional; {%- endif %} break; {%- endfor %} {%- endfor %} {%- else %} {%- if num_input_channels == 2 %} case 0: port.name = "Input Left"; port.symbol = "in_left"; break; case 1: port.name = "Input Right"; port.symbol = "in_right"; break; port.groupId = kPortGroupStereo; {%- endif %} {%- endif %} } } else { switch (index) { {%- if meta.port_groups.output|length %} {%- for group, gConfig in meta.port_groups.output.items() %} {%- for port, value in gConfig.items() %} case {{value[0] or value}}: port.name = "Output {{port}} ({{group}})"; port.symbol = "out_{{port|lower}}_{{group|lower}}"; port.groupId = kPortGroup{{group}}; {%- if value[1] is sameas true %} port.hints = kAudioPortIsCV | kCVPortHasPositiveUnipolarRange | kCVPortHasScaledRange | kCVPortIsOptional; {%- endif %} break; {%- endfor %} {%- endfor %} {% else %} {%- if num_output_channels == 2 %} case 0: port.name = "Output Left"; port.symbol = "out_left"; break; case 1: port.name = "Output Right"; port.symbol = "out_right"; break; } port.groupId = kPortGroupStereo; {%- endif %} {%- endif %} } } } void {{class_name}}::initPortGroup(uint32_t groupId, PortGroup& portGroup) { switch (groupId) { {%- if meta.port_groups.input|length %} {%- for group, value in meta.port_groups.input.items() %} case kPortGroup{{group}}: portGroup.name = "{{group}}"; portGroup.symbol = "{{group|lower}}"; break; {%- endfor %} {%- endif %} {%- if meta.port_groups.output|length %} {%- for group, value in meta.port_groups.output.items() %} case kPortGroup{{group}}: portGroup.name = "{{group}}"; portGroup.symbol = "{{group|lower}}"; break; {%- endfor %} {%- endif %} } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7532067 hvcc-0.13.3/hvcc/generators/c2js/README.md0000644000000000000000000000025514435670357014703 0ustar00# c2js Generator Note: make sure emscripten sdk is sourced and `emcc` command is in your PATH: http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7532067 hvcc-0.13.3/hvcc/generators/c2js/__init__.py0000644000000000000000000000000014435670357015521 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739952989.4286463 hvcc-0.13.3/hvcc/generators/c2js/c2js.py0000644000000000000000000002514014755311535014632 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2021-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os import subprocess import time import jinja2 from shutil import which from typing import Optional from hvcc.core.hv2ir.HeavyException import HeavyException from ..copyright import copyright_manager from hvcc.interpreters.pd2hv.NotificationEnum import NotificationEnum from hvcc.types.compiler import Generator, CompilerResp, CompilerNotif, CompilerMsg, ExternInfo from hvcc.types.meta import Meta class c2js(Generator): """Compiles a directory of C source files into javascript. Requires the emscripten library to be installed - https://github.com/kripken/emscripten """ __HV_API = [ "_hv_{0}_new", "_hv_{0}_new_with_options", "_hv_delete", "_hv_processInline", "_hv_getNumInputChannels", "_hv_getNumOutputChannels", "_hv_samplesToMilliseconds", "_hv_setPrintHook", "_hv_setSendHook", "_hv_sendFloatToReceiver", "_hv_sendBangToReceiver", "_hv_sendSymbolToReceiver", "_hv_stringToHash", "_hv_msg_getByteSize", "_hv_msg_init", "_hv_msg_hasFormat", "_hv_msg_setFloat", "_hv_msg_getFloat", "_hv_msg_getTimestamp", "_hv_table_getLength", "_hv_table_setLength", "_hv_table_getBuffer", "_hv_sendMessageToReceiverV", "_hv_sendMessageToReceiverFF", "_hv_sendMessageToReceiverFFF", "_malloc" # Rationale: https://github.com/emscripten-core/emscripten/issues/6882#issuecomment-406745898 ] @classmethod def run_emscripten( cls, c_src_dir: str, out_dir: str, patch_name: str, output_name: str, post_js_path: str, should_modularize: int, environment: str, pre_js_path: str = "", binaryen_async: int = 1 ) -> str: """Run the emcc command to compile C source files to a javascript library. """ # Detect Windows OS, but ignore if running in MingW if os.name == 'nt' and os.environ.get('MSYSTEM') is None: emcc_path = which("emcc.bat") else: emcc_path = which("emcc") if emcc_path is None: raise HeavyException("emcc is not in the PATH") c_flags = [ f"-I {c_src_dir}", "-DHV_SIMD_NONE", "-ffast-math", "-DNDEBUG", "-Wall" ] c_src_paths = [os.path.join(c_src_dir, c) for c in os.listdir(c_src_dir) if c.endswith((".c"))] cpp_src_paths = [os.path.join(c_src_dir, cpp) for cpp in os.listdir(c_src_dir) if cpp.endswith((".cpp"))] obj_paths = [] cmd = "" # compile C files for c in c_src_paths: obj_path = f"{os.path.splitext(c)[0]}.o" cmd = [emcc_path] + c_flags + ["-c", "-o", obj_path, c] # type: ignore subprocess.check_output(cmd) # run emscripten obj_paths += [obj_path] # compile C++ files for cpp in cpp_src_paths: obj_path = f"{os.path.splitext(cpp)[0]}.o" cmd = [emcc_path] + c_flags + ["-std=c++11"] + ["-c", "-o", obj_path, cpp] # type: ignore subprocess.check_output(cmd) # run emscripten obj_paths += [obj_path] # exported heavy api methods hv_api_defs = ", ".join([f"\"{x.format(patch_name)}\"" for x in cls.__HV_API]) # output path wasm_js_path = os.path.join(out_dir, f"{output_name}.js") linker_flags = [ "-O3", "-s", "RESERVED_FUNCTION_POINTERS=2", "-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$addFunction", "-s", f"EXPORTED_FUNCTIONS=[{hv_api_defs.format(patch_name)}]", "-s", f"MODULARIZE={should_modularize}", '-s', 'ASSERTIONS=1', '-s', f'ENVIRONMENT={environment}', '-s', 'SINGLE_FILE=1', '-s', 'ALLOW_TABLE_GROWTH=1', '-s', f'BINARYEN_ASYNC_COMPILATION={binaryen_async}', # Set this to 0 for the worklet so we don't # wait for promises when instantiating "--post-js", post_js_path ] if len(pre_js_path): linker_flags = linker_flags + [ "--pre-js", pre_js_path ] # include C/C++ obj files in js library cmd = [emcc_path] + obj_paths + linker_flags # type: ignore subprocess.check_output( # WASM cmd + [ # type: ignore "-s", "WASM=1", "-s", f"EXPORT_NAME='{output_name}_Module'", "-o", wasm_js_path ]) # clean up for o in obj_paths: os.remove(o) return wasm_js_path @classmethod def compile( cls, c_src_dir: str, out_dir: str, externs: ExternInfo, patch_name: Optional[str] = None, patch_meta: Meta = Meta(), num_input_channels: int = 0, num_output_channels: int = 0, copyright: Optional[str] = None, verbose: Optional[bool] = False ) -> CompilerResp: tick = time.time() parameter_list = externs.parameters.inParam parameter_out_list = externs.parameters.outParam event_list = externs.events.inEvent event_out_list = externs.events.outEvent midi_list = externs.midi.inMidi midi_out_list = externs.midi.outMidi out_dir = os.path.join(out_dir, "js") patch_name = patch_name or "heavy" copyright_js = copyright_manager.get_copyright_for_c(copyright) copyright_html = copyright_manager.get_copyright_for_xml(copyright) if not os.path.exists(out_dir): os.makedirs(out_dir) out_dir = os.path.abspath(out_dir) try: # initialise the jinja template environment env = jinja2.Environment() env.loader = jinja2.FileSystemLoader(os.path.join( os.path.dirname(__file__), "template")) # generate heavy js wrapper from template # Note: this file will be incorporated into the emscripten output # and removed afterwards post_js_path = os.path.join(out_dir, "hv_wrapper.js") with open(post_js_path, "w") as f: f.write(env.get_template("hv_wrapper.js").render( name=patch_name, copyright=copyright_js, externs=externs, pool_sizes_kb=externs.memoryPoolSizesKb)) js_path = cls.run_emscripten(c_src_dir=c_src_dir, out_dir=out_dir, patch_name=patch_name, output_name=patch_name, post_js_path=post_js_path, should_modularize=1, environment="web") # delete temporary files os.remove(post_js_path) js_out_file = os.path.basename(js_path) # generate index.html from template with open(os.path.join(out_dir, "index.html"), "w") as f: f.write(env.get_template("index.html").render( name=patch_name, includes=[f"./{js_out_file}"], parameters=parameter_list, parameters_out=parameter_out_list, events=event_list, events_out=event_out_list, midi=midi_list, midi_out=midi_out_list, copyright=copyright_html)) # generate heavy js worklet from template # Note: this file will be incorporated into the emscripten output # and removed afterwards post_js_path = os.path.join(out_dir, "hv_worklet.js") with open(post_js_path, "w") as f: f.write(env.get_template("hv_worklet.js").render( name=patch_name, copyright=copyright_js, externs=externs, pool_sizes_kb=externs.memoryPoolSizesKb)) pre_js_path = os.path.join(out_dir, "hv_worklet_start.js") with open(pre_js_path, "w") as f: f.write(env.get_template("hv_worklet_start.js").render( name=patch_name, copyright=copyright_js, externs=externs, pool_sizes_kb=externs.memoryPoolSizesKb)) js_path = cls.run_emscripten(c_src_dir=c_src_dir, out_dir=out_dir, patch_name=patch_name, output_name=f"{patch_name}_AudioLibWorklet", post_js_path=post_js_path, should_modularize=0, environment="shell,worker", pre_js_path=pre_js_path, binaryen_async=0) # delete temporary files os.remove(post_js_path) os.remove(pre_js_path) return CompilerResp( stage="c2js", in_dir=c_src_dir, out_dir=out_dir, out_file=js_out_file, compile_time=time.time() - tick ) except Exception as e: return CompilerResp( stage="c2js", notifs=CompilerNotif( has_error=True, exception=e, warnings=[], errors=[CompilerMsg( enum=NotificationEnum.ERROR_EXCEPTION, message=str(e) )] ), in_dir=c_src_dir, out_dir=out_dir, compile_time=time.time() - tick ) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1739952883.945202 hvcc-0.13.3/hvcc/generators/c2js/template/hv_worklet.js0000644000000000000000000002672714755311364017770 0ustar00{{copyright}} /* * AudioLibWorklet - Processes the audio through the Heavy C API */ class {{name}}_AudioLibWorklet extends AudioWorkletProcessor { constructor({ processorOptions }) { super(); this.sampleRate = processorOptions.sampleRate || 44100.0; // As of right now (June 2022), blockSize is always 128. // In the future, it could become dynamic, // and we'll have to read the lengths of incoming outputs and re-alloc the processBuffer if it changes. this.blockSize = 128; // instantiate heavy context this.heavyContext = _hv_{{name}}_new_with_options(this.sampleRate, {{pool_sizes_kb.internal}}, {{pool_sizes_kb.inputQueue}}, {{pool_sizes_kb.outputQueue}}); this.setPrintHook(); this.setSendHook(); // allocate temporary buffers (pointer size is 4 bytes in javascript) var lengthInSamples = this.blockSize * this.getNumOutputChannels(); this.processBuffer = new Float32Array( Module.HEAPF32.buffer, Module._malloc(lengthInSamples * Float32Array.BYTES_PER_ELEMENT), lengthInSamples); this.port.onmessage = (e) => { console.log(e.data); switch(e.data.type){ case 'setFloatParameter': this.setFloatParameter(e.data.name, e.data.value); break; case 'sendEvent': this.sendEvent(e.data.name); break; case 'sendMidi': this.sendMidi(e.data.message); break; case 'fillTableWithFloatBuffer': this.fillTableWithFloatBuffer(e.data.name, e.data.buffer); break; default: console.error('No handler for message of type: ', e.data.type); } } } process(inputs, outputs, parameters) { try{ _hv_processInline(this.heavyContext, null, this.processBuffer.byteOffset, this.blockSize); // TODO: Figure out what "multiple outputs" means if not multiple channels var output = outputs[0]; for (var i = 0; i < this.getNumOutputChannels(); ++i) { var channel = output[i]; var offset = i * this.blockSize; for (var j = 0; j < this.blockSize; ++j) { channel[j] = this.processBuffer[offset+j]; } } } catch(e){ this.port.postMessage({ type:'error', error: e.toString() }); } return true; } getNumInputChannels() { return (this.heavyContext) ? _hv_getNumInputChannels(this.heavyContext) : -1; } getNumOutputChannels() { return (this.heavyContext) ? _hv_getNumOutputChannels(this.heavyContext) : -1; } setPrintHook() { if (!this.heavyContext) { console.error("heavy: Can't set Print Hook, no Heavy Context instantiated"); return; } var self = this; // typedef void (HvPrintHook_t) (HeavyContextInterface *context, const char *printName, const char *str, const HvMessage *msg); var printHook = addFunction(function(context, printName, str, msg) { // Converts Heavy print callback to a printable message var timeInSecs =_hv_samplesToMilliseconds(context, _hv_msg_getTimestamp(msg)) / 1000.0; var m = UTF8ToString(printName) + " [" + timeInSecs.toFixed(3) + "]: " + UTF8ToString(str); self.port.postMessage({ type: 'printHook', payload: m }); }, "viiii" ); _hv_setPrintHook(this.heavyContext, printHook); } setSendHook() { if (!this.heavyContext) { console.error("heavy: Can't set Send Hook, no Heavy Context instantiated"); return; } var self = this; // typedef void (HvSendHook_t) (HeavyContextInterface *context, const char *sendName, hv_uint32_t sendHash, const HvMessage *msg); var sendHook = addFunction(function(context, sendName, sendHash, msg) { // Filter out MIDI messages const midiMessage = sendMidiOut(UTF8ToString(sendName), msg); if (midiMessage.length > 0) { self.port.postMessage({ type: 'midiOut', payload: midiMessage }); } else { // Converts sendhook callback to (sendName, float) message self.port.postMessage({ type: 'sendHook', payload: [UTF8ToString(sendName), _hv_msg_getFloat(msg, 0)] }); } }, "viiii" ); _hv_setSendHook(this.heavyContext, sendHook); } sendEvent(name) { if (this.heavyContext) { _hv_sendBangToReceiver(this.heavyContext, eventInHashes[name]); } } setFloatParameter(name, floatValue) { if (this.heavyContext) { _hv_sendFloatToReceiver(this.heavyContext, parameterInHashes[name], parseFloat(floatValue)); } } sendMidi(message) { sendMidiIn(this.heavyContext, message); } sendStringToReceiver(name, message) { // Note(joe): it's not a good idea to call this frequently it is possible for // the stack memory to run out over time. if (this.heavyContext) { var r = allocate(intArrayFromString(name), 'i8', ALLOC_STACK); var m = allocate(intArrayFromString(message), 'i8', ALLOC_STACK); _hv_sendSymbolToReceiver(this.heavyContext, _hv_stringToHash(r), m); } } fillTableWithFloatBuffer(name, buffer) { var tableHash = tableHashes[name]; if (_hv_table_getBuffer(this.heavyContext, tableHash) !== 0) { // resize current table to new buffer length _hv_table_setLength(this.heavyContext, tableHash, buffer.length); // access internal float buffer from table let tableBuffer = new Float32Array( Module.HEAPF32.buffer, _hv_table_getBuffer(this.heavyContext, tableHash), buffer.length); // set the table buffer with the data from the 1st channel (mono) tableBuffer.set(buffer); } else { console.error("heavy: Table '" + name + "' doesn't exist in the patch context."); } } } var parameterInHashes = { {%- for k,v in externs.parameters.inParam %} "{{v.display}}": {{v.hash}}, // {{v.display}} {%- endfor %} }; var parameterOutHashes = { {%- for k,v in externs.parameters.outParam %} "{{v.display}}": {{v.hash}}, // {{v.display}} {%- endfor %} }; var eventInHashes = { {%- for k,v in externs.events.inEvent %} "{{v.display}}": {{v.hash}}, // {{v.display}} {%- endfor %} }; var eventOutHashes = { {%- for k,v in externs.events.outEvent %} "{{v.display}}": {{v.hash}}, // {{v.display}} {%- endfor %} }; var tableHashes = { {%- for k,v in externs.tables %} "{{v.display}}": {{v.hash}}, // {{v.display}} {%- endfor %} }; registerProcessor("{{name}}_AudioLibWorklet", {{name}}_AudioLibWorklet); // midi_utils function sendMidiIn(hv_context, message) { if (hv_context) { var command = message[0] & 0xF0; var channel = message[0] & 0x0F; var data1 = message[1]; var data2 = message[2]; // all events to [midiin] for (var i = 1; i <= 2; i++) { _hv_sendMessageToReceiverFF(hv_context, HV_HASH_MIDIIN, 0, message[i], channel ); } // realtime events to [midirealtimein] if (MIDI_REALTIME.includes(message[0])) { _hv_sendMessageToReceiverFF(hv_context, HV_HASH_MIDIREALTIMEIN, 0, message[0] ); } switch(command) { case 0x80: // note off _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_NOTEIN, 0, data1, 0, channel); break; case 0x90: // note on _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_NOTEIN, 0, data1, data2, channel); break; case 0xA0: // polyphonic aftertouch _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_POLYTOUCHIN, 0, data2, // pressure data1, // note channel); break; case 0xB0: // control change _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_CTLIN, 0, data2, // value data1, // cc number channel); break; case 0xC0: // program change _hv_sendMessageToReceiverFF(hv_context, HV_HASH_PGMIN, 0, data1, channel); break; case 0xD0: // aftertouch _hv_sendMessageToReceiverFF(hv_context, HV_HASH_TOUCHIN, 0, data1, channel); break; case 0xE0: // pitch bend // combine 7bit lsb and msb into 32bit int var value = (data2 << 7) | data1; _hv_sendMessageToReceiverFF(hv_context, HV_HASH_BENDIN, 0, value, channel); break; default: // console.error('No handler for midi message: ', message); } } } function sendMidiOut(sendName, msg) { switch (sendName) { case "__hv_noteout": var note = _hv_msg_getFloat(msg, 0); var velocity = _hv_msg_getFloat(msg, 1); var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midi ports return [ ((velocity > 0) ? 144 : 128) | channel, note, velocity ] case "__hv_ctlout": var value = _hv_msg_getFloat(msg, 0); var cc = _hv_msg_getFloat(msg, 1); var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midi ports return [ 176 | channel, cc, value ] case "__hv_pgmout": var program = _hv_msg_getFloat(msg, 0); var channel = _hv_msg_getFloat(msg, 1) % 16; // no pd midi ports return [ 192 | channel, program ] case "__hv_touchout": var pressure = _hv_msg_getFloat(msg, 0); var channel = _hv_msg_getFloat(msg, 1) % 16; // no pd midi ports return [ 208 | channel, pressure, ] case "__hv_polytouchout": var value = _hv_msg_getFloat(msg, 0); var note = _hv_msg_getFloat(msg, 1); var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midi ports return[ 160 | channel, note, value ] case "__hv_bendout": var value = _hv_msg_getFloat(msg, 0); let lsb = value & 0x7F; let msb = (value >> 7) & 0x7F; var channel = _hv_msg_getFloat(msg, 1) % 16; // no pd midi ports return [ 224 | channel, lsb, msb ] case "__hv_midiout": let firstByte = _hv_msg_getFloat(msg, 0); return (firstByte === 192 || firstByte === 208) ? [_hv_msg_getFloat(msg, 0), _hv_msg_getFloat(msg, 1)] : [_hv_msg_getFloat(msg, 0), _hv_msg_getFloat(msg, 1), _hv_msg_getFloat(msg, 2)]; default: console.warn(`Unhandled sendName: ${sendName}`); return []; } } /* * MIDI Constants */ const HV_HASH_NOTEIN = 0x67E37CA3; const HV_HASH_CTLIN = 0x41BE0f9C; const HV_HASH_POLYTOUCHIN = 0xBC530F59; const HV_HASH_PGMIN = 0x2E1EA03D; const HV_HASH_TOUCHIN = 0x553925BD; const HV_HASH_BENDIN = 0x3083F0F7; const HV_HASH_MIDIIN = 0x149631bE; const HV_HASH_MIDIREALTIMEIN = 0x6FFF0BCF; const MIDI_REALTIME = [0xF8, 0xFA, 0xFB, 0xFC, 0xFE, 0xFF]; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.266823 hvcc-0.13.3/hvcc/generators/c2js/template/hv_worklet_start.js0000644000000000000000000000050414735300474021164 0ustar00 // Some hacks gathered from this thread: https://github.com/emscripten-core/emscripten/issues/6230 var self = { location: { href: "http://localhost:3000/" // URL where the module was loaded from } }; function importScripts(){ console.warn('importScripts should not be called in an AudioWorklet', arguments); } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1739952883.945202 hvcc-0.13.3/hvcc/generators/c2js/template/hv_wrapper.js0000644000000000000000000003532414755311364017752 0ustar00{{copyright}} var audioWorkletSupported = (typeof AudioWorklet === 'function'); /* * AudioLibLoader - Convenience functions for setting up the web audio context * and initialising the AudioLib context */ var AudioLibLoader = function() { this.isPlaying = false; this.webAudioContext = null; this.webAudioProcessor = null; this.webAudioWorklet = null; this.audiolib = null; } /* * @param (Object) options * @param options.blockSize (Number) number of samples to process in each iteration * @param options.printHook (Function) callback that gets triggered on each print message * @param options.sendHook (Function) callback that gets triggered for messages sent via @hv_param/@hv_event */ AudioLibLoader.prototype.init = function(options) { // use provided web audio context or create a new one this.webAudioContext = options.webAudioContext || (new (window.AudioContext || window.webkitAudioContext || null)); if (this.webAudioContext) { return (async() => { var blockSize = options.blockSize || 2048; if (audioWorkletSupported) { await this.webAudioContext.audioWorklet.addModule("{{name}}_AudioLibWorklet.js"); this.webAudioWorklet = new AudioWorkletNode(this.webAudioContext, "{{name}}_AudioLibWorklet", { outputChannelCount: [2], processorOptions: { sampleRate: this.webAudioContext.sampleRate, blockSize, } }); this.webAudioWorklet.port.onmessage = (event) => { if (event.data.type === 'printHook' && options.printHook) { options.printHook(event.data.payload); } else if (event.data.type === 'sendHook' && options.sendHook) { options.sendHook(event.data.payload[0], event.data.payload[1]); } else if (event.data.type === 'midiOut' && options.sendHook) { options.sendHook("midiOutMessage", event.data.payload); } else { console.log('Unhandled message from {{name}}_AudioLibWorklet:', event.data); } }; this.webAudioWorklet.connect(this.webAudioContext.destination); } else { console.warn('heavy: AudioWorklet not supported, reverting to ScriptProcessorNode'); var instance = new {{name}}_AudioLib({ sampleRate: this.webAudioContext.sampleRate, blockSize: blockSize, printHook: options.printHook, sendHook: options.sendHook }); this.audiolib = instance; this.webAudioProcessor = this.webAudioContext.createScriptProcessor(blockSize, instance.getNumInputChannels(), Math.max(instance.getNumOutputChannels(), 1)); this.webAudioProcessor.onaudioprocess = (function(e) { instance.process(e) }) } })(); } else { console.error("heavy: failed to load - WebAudio API not available in this browser") } } AudioLibLoader.prototype.start = function() { if (this.audiolib) { this.webAudioProcessor.connect(this.webAudioContext.destination); } else { this.webAudioContext.resume(); } this.isPlaying = true; } AudioLibLoader.prototype.stop = function() { if (this.audiolib) { this.webAudioProcessor.disconnect(this.webAudioContext.destination); } else { this.webAudioContext.suspend(); } this.isPlaying = false; } AudioLibLoader.prototype.sendFloatParameterToWorklet = function(name, value) { if (this.audiolib) { this.audiolib.sendEvent(name, value); } else { this.webAudioWorklet.port.postMessage({ type:'setFloatParameter', name, value }); } } AudioLibLoader.prototype.sendEvent = function(name, value) { if (this.audiolib) { this.audiolib.sendEvent(name, value); } else { this.webAudioWorklet.port.postMessage({ type:'sendEvent', name, value }); } } AudioLibLoader.prototype.sendMidi = function(message) { if (this.audiolib) { this.audiolib.sendMidi(message); } else { this.webAudioWorklet.port.postMessage({ type:'sendMidi', message:message }); } } AudioLibLoader.prototype.fillTableWithFloatBuffer = function(name, buffer) { if (this.audiolib) { this.audiolib.fillTableWithFloatBuffer(name, buffer); } else { this.webAudioWorklet.port.postMessage({ type:'fillTableWithFloatBuffer', name, buffer }); } } Module.AudioLibLoader = AudioLibLoader; /* * Heavy Javascript AudioLib - Wraps over the Heavy C API */ /* * @param (Object) options * @param options.sampleRate (Number) audio sample rate * @param options.blockSize (Number) number of samples to process in each iteration * @param options.printHook (Function) callback that gets triggered on each print message * @param options.sendHook (Function) callback that gets triggered for messages sent via @hv_param/@hv_event */ var {{name}}_AudioLib = function(options) { this.sampleRate = options.sampleRate || 44100.0; this.blockSize = options.blockSize || 2048; // instantiate heavy context this.heavyContext = _hv_{{name}}_new_with_options(this.sampleRate, {{pool_sizes_kb.internal}}, {{pool_sizes_kb.inputQueue}}, {{pool_sizes_kb.outputQueue}}); this.setPrintHook(options.printHook); this.setSendHook(options.sendHook); // allocate temporary buffers (pointer size is 4 bytes in javascript) var lengthInSamples = this.blockSize * this.getNumOutputChannels(); this.processBuffer = new Float32Array( Module.HEAPF32.buffer, Module._malloc(lengthInSamples * Float32Array.BYTES_PER_ELEMENT), lengthInSamples); } var parameterInHashes = { {%- for k,v in externs.parameters.inParam %} "{{v.display}}": {{v.hash}}, // {{v.display}} {%- endfor %} }; var parameterOutHashes = { {%- for k,v in externs.parameters.outParam %} "{{v.display}}": {{v.hash}}, // {{v.display}} {%- endfor %} }; var eventInHashes = { {%- for k,v in externs.events.inEvent %} "{{v.display}}": {{v.hash}}, // {{v.display}} {%- endfor %} }; var eventOutHashes = { {%- for k,v in externs.events.outEvent %} "{{v.display}}": {{v.hash}}, // {{v.display}} {%- endfor %} }; var tableHashes = { {%- for k,v in externs.tables %} "{{v.display}}": {{v.hash}}, // {{v.display}} {%- endfor %} }; {{name}}_AudioLib.prototype.process = function(event) { _hv_processInline(this.heavyContext, null, this.processBuffer.byteOffset, this.blockSize); for (var i = 0; i < this.getNumOutputChannels(); ++i) { var output = event.outputBuffer.getChannelData(i); var offset = i * this.blockSize; for (var j = 0; j < this.blockSize; ++j) { output[j] = this.processBuffer[offset+j]; } } } {{name}}_AudioLib.prototype.getNumInputChannels = function() { return (this.heavyContext) ? _hv_getNumInputChannels(this.heavyContext) : -1; } {{name}}_AudioLib.prototype.getNumOutputChannels = function() { return (this.heavyContext) ? _hv_getNumOutputChannels(this.heavyContext) : -1; } {{name}}_AudioLib.prototype.setPrintHook = function(hook) { if (!this.heavyContext) { console.error("heavy: Can't set Print Hook, no Heavy Context instantiated"); return; } if (hook) { // typedef void (HvPrintHook_t) (HeavyContextInterface *context, const char *printName, const char *str, const HvMessage *msg); var printHook = addFunction(function(context, printName, str, msg) { // Converts Heavy print callback to a printable message var timeInSecs =_hv_samplesToMilliseconds(context, _hv_msg_getTimestamp(msg)) / 1000.0; var m = UTF8ToString(printName) + " [" + timeInSecs.toFixed(3) + "]: " + UTF8ToString(str); hook(m); }, "viiii" ); _hv_setPrintHook(this.heavyContext, printHook); } } {{name}}_AudioLib.prototype.setSendHook = function(hook) { if (!this.heavyContext) { console.error("heavy: Can't set Send Hook, no Heavy Context instantiated"); return; } if (hook) { // typedef void (HvSendHook_t) (HeavyContextInterface *context, const char *sendName, hv_uint32_t sendHash, const HvMessage *msg); var sendHook = addFunction(function(context, sendName, sendHash, msg) { const midiMessage = sendMidiOut(UTF8ToString(sendName), msg); if (midiMessage.length > 0) { hook("midiOutMessage", midiMessage); } else { // Converts sendhook callback to (sendName, float) message hook(UTF8ToString(sendName), _hv_msg_getFloat(msg, 0)); } }, "viiii" ); _hv_setSendHook(this.heavyContext, sendHook); } } {{name}}_AudioLib.prototype.sendEvent = function(name) { if (this.heavyContext) { _hv_sendBangToReceiver(this.heavyContext, eventInHashes[name]); } } {{name}}_AudioLib.prototype.sendMidi = function(message) { sendMidiIn(this.heavyContext, message); } {{name}}_AudioLib.prototype.setFloatParameter = function(name, floatValue) { if (this.heavyContext) { _hv_sendFloatToReceiver(this.heavyContext, parameterInHashes[name], parseFloat(floatValue)); } } {{name}}_AudioLib.prototype.sendStringToReceiver = function(name, message) { // Note(joe): it's not a good idea to call this frequently it is possible for // the stack memory to run out over time. if (this.heavyContext) { var r = allocate(intArrayFromString(name), 'i8', ALLOC_STACK); var m = allocate(intArrayFromString(message), 'i8', ALLOC_STACK); _hv_sendSymbolToReceiver(this.heavyContext, _hv_stringToHash(r), m); } } {{name}}_AudioLib.prototype.fillTableWithFloatBuffer = function(name, buffer) { var tableHash = tableHashes[name]; if (_hv_table_getBuffer(this.heavyContext, tableHash) !== 0) { // resize current table to new buffer length _hv_table_setLength(this.heavyContext, tableHash, buffer.length); // access internal float buffer from table tableBuffer = new Float32Array( Module.HEAPF32.buffer, _hv_table_getBuffer(this.heavyContext, tableHash), buffer.length); // set the table buffer with the data from the 1st channel (mono) tableBuffer.set(buffer); } else { console.error("heavy: Table '" + name + "' doesn't exist in the patch context."); } } Module.{{name}}_AudioLib = {{name}}_AudioLib; // midi_utils function sendMidiIn(hv_context, message) { if (hv_context) { var command = message[0] & 0xF0; var channel = message[0] & 0x0F; var data1 = message[1]; var data2 = message[2]; // all events to [midiin] for (var i = 1; i <= 2; i++) { _hv_sendMessageToReceiverFF(hv_context, HV_HASH_MIDIIN, 0, message[i], channel ); } // realtime events to [midirealtimein] if (MIDI_REALTIME.includes(message[0])) { _hv_sendMessageToReceiverFF(hv_context, HV_HASH_MIDIREALTIMEIN, 0, message[0] ); } switch(command) { case 0x80: // note off _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_NOTEIN, 0, data1, 0, channel); break; case 0x90: // note on _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_NOTEIN, 0, data1, data2, channel); break; case 0xA0: // polyphonic aftertouch _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_POLYTOUCHIN, 0, data2, // pressure data1, // note channel); break; case 0xB0: // control change _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_CTLIN, 0, data2, // value data1, // cc number channel); break; case 0xC0: // program change _hv_sendMessageToReceiverFF(hv_context, HV_HASH_PGMIN, 0, data1, channel); break; case 0xD0: // aftertouch _hv_sendMessageToReceiverFF(hv_context, HV_HASH_TOUCHIN, 0, data1, channel); break; case 0xE0: // pitch bend // combine 7bit lsb and msb into 32bit int var value = (data2 << 7) | data1; _hv_sendMessageToReceiverFF(hv_context, HV_HASH_BENDIN, 0, value, channel); break; default: // console.error('No handler for midi message: ', message); } } } function sendMidiOut(sendName, msg) { switch (sendName) { case "__hv_noteout": var note = _hv_msg_getFloat(msg, 0); var velocity = _hv_msg_getFloat(msg, 1); var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midi ports return [ ((velocity > 0) ? 144 : 128) | channel, note, velocity ] case "__hv_ctlout": var value = _hv_msg_getFloat(msg, 0); var cc = _hv_msg_getFloat(msg, 1); var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midi ports return [ 176 | channel, cc, value ] case "__hv_pgmout": var program = _hv_msg_getFloat(msg, 0); var channel = _hv_msg_getFloat(msg, 1) % 16; // no pd midi ports return [ 192 | channel, program ] case "__hv_touchout": var pressure = _hv_msg_getFloat(msg, 0); var channel = _hv_msg_getFloat(msg, 1) % 16; // no pd midi ports return [ 208 | channel, pressure, ] case "__hv_polytouchout": var value = _hv_msg_getFloat(msg, 0); var note = _hv_msg_getFloat(msg, 1); var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midi ports return[ 160 | channel, note, value ] case "__hv_bendout": var value = _hv_msg_getFloat(msg, 0); let lsb = value & 0x7F; let msb = (value >> 7) & 0x7F; var channel = _hv_msg_getFloat(msg, 1) % 16; // no pd midi ports return [ 224 | channel, lsb, msb ] case "__hv_midiout": let firstByte = _hv_msg_getFloat(msg, 0); return (firstByte === 192 || firstByte === 208) ? [_hv_msg_getFloat(msg, 0), _hv_msg_getFloat(msg, 1)] : [_hv_msg_getFloat(msg, 0), _hv_msg_getFloat(msg, 1), _hv_msg_getFloat(msg, 2)]; default: console.warn(`Unhandled sendName: ${sendName}`); return []; } } /* * MIDI Constants */ const HV_HASH_NOTEIN = 0x67E37CA3; const HV_HASH_CTLIN = 0x41BE0f9C; const HV_HASH_POLYTOUCHIN = 0xBC530F59; const HV_HASH_PGMIN = 0x2E1EA03D; const HV_HASH_TOUCHIN = 0x553925BD; const HV_HASH_BENDIN = 0x3083F0F7; const HV_HASH_MIDIIN = 0x149631bE; const HV_HASH_MIDIREALTIMEIN = 0x6FFF0BCF; const MIDI_REALTIME = [0xF8, 0xFA, 0xFB, 0xFC, 0xFE, 0xFF]; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.266823 hvcc-0.13.3/hvcc/generators/c2js/template/index.html0000644000000000000000000002474214735300474017234 0ustar00 {{name}} {% for path in includes -%} {% endfor -%}

{{name}}

{%- if events | length %}
Input Events:
{%- for k, v in events %}
{%- endfor %}
{%- endif %} {%- if events_out | length %}
Output Events:
{%- for k, v in events_out %} {{k}}: 0
{%- endfor %}
{%- endif %}
{%- if parameters | length %}
Input Parameters:
{%- for k, v in parameters %}
{{k}}
{{v.attributes.default}}
{%- endfor %} {%- endif %} {%- if parameters_out | length %}
Output Parameters:
{%- for k, v in parameters_out %}
{{k}}
{{v.attributes.default}}
{%- endfor %} {%- endif %} {%- if midi | length or midi_out | length%}
{%- if midi | length %}
MIDI inputs:
{%- endif %} {%- if midi_out | length %}
MIDI outputs:
{%- endif %}
{%- endif %}
powered by heavy
././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7542067 hvcc-0.13.3/hvcc/generators/c2owl/__init__.py0000644000000000000000000000000014435670357015706 0ustar00././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.267823 hvcc-0.13.3/hvcc/generators/c2owl/c2owl.py0000644000000000000000000001315414735300474015204 0ustar00# import datetime import os import shutil import time import jinja2 import json from typing import List, Optional import hvcc.core.hv2ir.HeavyLangObject as HeavyLangObject from ..copyright import copyright_manager from hvcc.interpreters.pd2hv.NotificationEnum import NotificationEnum from hvcc.types.compiler import Generator, CompilerResp, CompilerNotif, CompilerMsg, ExternInfo from hvcc.types.meta import Meta from hvcc.types.IR import IRGraph heavy_hash = HeavyLangObject.HeavyLangObject.get_hash OWL_BUTTONS = ['Push', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8'] class c2owl(Generator): """ Generates a OWL wrapper for a given patch. """ @classmethod def make_jdata(cls, patch_ir: str) -> List: jdata = list() with open(patch_ir, mode="r") as f: ir = IRGraph(**json.load(f)) for name, recv in ir.control.receivers.items(): # skip __hv_init and similar if name.startswith("__"): continue # If a name has been specified if recv.attributes.get('raw'): key = recv.attributes['raw'] jdata.append((key, name, 'RECV', f"0x{heavy_hash(name):X}", recv.attributes['min'], recv.attributes['max'], recv.attributes['default'], key in OWL_BUTTONS)) elif name.startswith('Channel-'): key = name.split('Channel-', 1)[1] jdata.append((key, name, 'RECV', f"0x{heavy_hash(name):X}", 0, 1, None, key in OWL_BUTTONS)) for _, obj in ir.objects.items(): try: if obj.type == '__send': name = obj.args['name'] if obj.args['attributes'].get('raw'): key = obj.args['attributes']['raw'] jdata.append((key, f'{name}>', 'SEND', f"0x{heavy_hash(name):X}", obj.args['attributes']['min'], obj.args['attributes']['max'], obj.args['attributes']['default'], key in OWL_BUTTONS)) elif name.startswith('Channel-'): key = name.split('Channel-', 1)[1] jdata.append((key, f'{name}>', 'SEND', f"0x{heavy_hash(name):X}", 0, 1, None, key in OWL_BUTTONS)) except Exception: pass return jdata @classmethod def compile( cls, c_src_dir: str, out_dir: str, externs: ExternInfo, patch_name: Optional[str] = None, patch_meta: Meta = Meta(), num_input_channels: int = 0, num_output_channels: int = 0, copyright: Optional[str] = None, verbose: Optional[bool] = False ) -> CompilerResp: tick = time.time() out_dir = os.path.join(out_dir, "Source") patch_name = patch_name or "heavy" copyright_c = copyright_manager.get_copyright_for_c(copyright) try: # ensure that the output directory does not exist out_dir = os.path.abspath(out_dir) if os.path.exists(out_dir): shutil.rmtree(out_dir) # copy over generated C source files shutil.copytree(c_src_dir, out_dir) # copy over deps shutil.copytree(os.path.join(os.path.dirname(__file__), "deps"), out_dir, dirs_exist_ok=True) # initialize the jinja template environment env = jinja2.Environment() env.loader = jinja2.FileSystemLoader( os.path.join(os.path.dirname(os.path.abspath(__file__)), "templates")) # construct jdata from ir ir_dir = os.path.join(c_src_dir, "../ir") patch_ir = os.path.join(ir_dir, f"{patch_name}.heavy.ir.json") jdata = cls.make_jdata(patch_ir) # generate OWL wrapper from template owl_hpp_path = os.path.join(out_dir, f"HeavyOWL_{patch_name}.hpp") with open(owl_hpp_path, "w") as f: f.write(env.get_template("HeavyOwl.hpp").render( jdata=jdata, name=patch_name, copyright=copyright_c)) owl_h_path = os.path.join(out_dir, "HeavyOwlConstants.h") with open(owl_h_path, "w") as f: f.write(env.get_template("HeavyOwlConstants.h").render( jdata=jdata, copyright=copyright_c)) # ====================================================================================== return CompilerResp( stage="c2owl", in_dir=c_src_dir, out_dir=out_dir, out_file=os.path.basename(owl_h_path), compile_time=time.time() - tick ) except Exception as e: return CompilerResp( stage="c2owl", notifs=CompilerNotif( has_error=True, exception=e, warnings=[], errors=[CompilerMsg( enum=NotificationEnum.ERROR_EXCEPTION, message=str(e) )] ), in_dir=c_src_dir, out_dir=out_dir, compile_time=time.time() - tick ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7542067 hvcc-0.13.3/hvcc/generators/c2owl/deps/HvMessage.c0000644000000000000000000001621514435670357016575 0ustar00/** * Copyright (c) 2014,2015,2016 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvMessage.h" #include "message.h" #include HvMessage *msg_init(HvMessage *m, hv_size_t numElements, hv_uint32_t timestamp) { m->timestamp = timestamp; m->numElements = (hv_uint16_t) numElements; m->numBytes = (hv_uint16_t) msg_getCoreSize(numElements); return m; } HvMessage *msg_initWithFloat(HvMessage *m, hv_uint32_t timestamp, float f) { m->timestamp = timestamp; m->numElements = 1; m->numBytes = sizeof(HvMessage); msg_setFloat(m, 0, f); return m; } HvMessage *msg_initWithBang(HvMessage *m, hv_uint32_t timestamp) { m->timestamp = timestamp; m->numElements = 1; m->numBytes = sizeof(HvMessage); msg_setBang(m, 0); return m; } HvMessage *msg_initWithSymbol(HvMessage *m, hv_uint32_t timestamp, const char *s) { m->timestamp = timestamp; m->numElements = 1; m->numBytes = sizeof(HvMessage) + (hv_uint16_t) hv_strlen(s); msg_setSymbol(m, 0, s); return m; } HvMessage *msg_initWithHash(HvMessage *m, hv_uint32_t timestamp, hv_uint32_t h) { m->timestamp = timestamp; m->numElements = 1; m->numBytes = sizeof(HvMessage); msg_setHash(m, 0, h); return m; } void msg_copyToBuffer(const HvMessage *m, char *buffer, hv_size_t len) { HvMessage *r = (HvMessage *) buffer; hv_size_t len_r = msg_getCoreSize(msg_getNumElements(m)); // assert that the message is not already larger than the length of the buffer hv_assert(len_r <= len); // copy the basic message to the buffer hv_memcpy(r, m, len_r); char *p = buffer + len_r; // points to the end of the base message for (int i = 0; i < msg_getNumElements(m); ++i) { if (msg_isSymbol(m,i)) { const hv_size_t symLen = (hv_size_t) hv_strlen(msg_getSymbol(m,i)) + 1; // include the trailing null char hv_assert(len_r + symLen <= len); // stay safe! hv_strncpy(p, msg_getSymbol(m,i), symLen); msg_setSymbol(r, i, p); p += symLen; len_r += symLen; } } r->numBytes = (hv_uint16_t) len_r; // update the message size in memory } // the message is serialised such that all symbol elements are placed in order at the end of the buffer HvMessage *msg_copy(const HvMessage *m) { const hv_uint32_t heapSize = msg_getSize(m); char *r = (char *) hv_malloc(heapSize); hv_assert(r != NULL); msg_copyToBuffer(m, r, heapSize); return (HvMessage *) r; } void msg_free(HvMessage *m) { hv_free(m); // because heap messages are serialised in memory, a simple call to free releases the message } bool msg_hasFormat(const HvMessage *m, const char *fmt) { hv_assert(fmt != NULL); const int n = msg_getNumElements(m); for (int i = 0; i < n; ++i) { switch (fmt[i]) { case 'b': if (!msg_isBang(m, i)) return false; break; case 'f': if (!msg_isFloat(m, i)) return false; break; case 'h': if (!msg_isHash(m, i)) return false; break; case 's': if (!msg_isSymbol(m, i)) return false; break; default: return false; } } return (fmt[n] == '\0'); } bool msg_compareSymbol(const HvMessage *m, int i, const char *s) { switch (msg_getType(m,i)) { case HV_MSG_SYMBOL: return !hv_strcmp(msg_getSymbol(m, i), s); case HV_MSG_HASH: return (msg_getHash(m,i) == hv_string_to_hash(s)); default: return false; } } bool msg_equalsElement(const HvMessage *m, int i_m, const HvMessage *n, int i_n) { if (i_m < msg_getNumElements(m) && i_n < msg_getNumElements(n)) { if (msg_getType(m, i_m) == msg_getType(n, i_n)) { switch (msg_getType(m, i_m)) { case HV_MSG_BANG: return true; case HV_MSG_FLOAT: return (msg_getFloat(m, i_m) == msg_getFloat(n, i_n)); case HV_MSG_SYMBOL: return msg_compareSymbol(m, i_m, msg_getSymbol(n, i_n)); case HV_MSG_HASH: return msg_getHash(m,i_m) == msg_getHash(n,i_n); default: break; } } } return false; } void msg_setElementToFrom(HvMessage *n, int i_n, const HvMessage *const m, int i_m) { switch (msg_getType(m, i_m)) { case HV_MSG_BANG: msg_setBang(n, i_n); break; case HV_MSG_FLOAT: msg_setFloat(n, i_n, msg_getFloat(m, i_m)); break; case HV_MSG_SYMBOL: msg_setSymbol(n, i_n, msg_getSymbol(m, i_m)); break; case HV_MSG_HASH: msg_setHash(n, i_n, msg_getHash(m, i_m)); default: break; } } hv_uint32_t msg_getHash(const HvMessage *const m, int i) { hv_assert(i < msg_getNumElements(m)); // invalid index switch (msg_getType(m,i)) { case HV_MSG_BANG: return 0xFFFFFFFF; case HV_MSG_FLOAT: { float f = msg_getFloat(m,i); return *((hv_uint32_t *) &f); } case HV_MSG_SYMBOL: return hv_string_to_hash(msg_getSymbol(m,i)); case HV_MSG_HASH: return (&(m->elem)+i)->data.h; default: return 0; } } char *msg_toString(const HvMessage *m) { hv_assert(msg_getNumElements(m) > 0); int *len = (int *) hv_alloca(msg_getNumElements(m)*sizeof(int)); int size = 0; // the total length of our final buffer // loop through every element in our list of atoms // first loop figures out how long our buffer should be for (int i = 0; i < msg_getNumElements(m); i++) { // length of our string is each atom plus a space, or \0 on the end switch (msg_getType(m, i)) { case HV_MSG_BANG: len[i] = 5; break; case HV_MSG_FLOAT: len[i] = strnlen(msg_ftoa(msg_getFloat(m, i), 10), 16)+1; break; case HV_MSG_SYMBOL: len[i] = strnlen(msg_getSymbol(m, i), 16)+1; break; case HV_MSG_HASH: len[i] = strnlen(msg_itoa(msg_getHash(m, i), 16), 8)+3; break; default: break; } size += len[i]; } hv_assert(size > 0); // now we do the piecewise concatenation into our final string // the final buffer we will pass back after concatenating all strings - user should free it char *finalString = (char *) hv_malloc(size*sizeof(char)); char* dst = finalString; for (int i = 0; i < msg_getNumElements(m); i++) { // put a string representation of each atom into the final string char* ptr; switch (msg_getType(m, i)) { case HV_MSG_BANG: dst = stpcpy(dst, "bang"); break; case HV_MSG_FLOAT: ptr = msg_ftoa(msg_getFloat(m, i), 10); dst = stpcpy(dst, ptr); break; case HV_MSG_SYMBOL: ptr = (char*)msg_getSymbol(m, i); dst = stpcpy(dst, ptr); break; case HV_MSG_HASH: ptr = msg_itoa(msg_getHash(m, i), 16); dst = stpcpy(dst, "0x"); dst = stpcpy(dst, ptr); break; default: break; } dst = stpcpy(dst, " "); } hv_assert(dst - finalString == size); finalString[size-1] = '\0'; // ensure that the string is null terminated return finalString; } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7542067 hvcc-0.13.3/hvcc/generators/c2owl/deps/HvUtils.h0000644000000000000000000002476214435670357016324 0ustar00/** * Copyright (c) 2014,2015,2016 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_UTILS_H_ #define _HEAVY_UTILS_H_ // platform definitions #if _WIN32 || _WIN64 #define HV_WIN 1 #ifdef _MSC_VER #define HV_MSVC 1 #endif #elif __APPLE__ #define HV_APPLE 1 #elif __ANDROID__ #define HV_ANDROID 1 #elif __unix__ || __unix #define HV_UNIX 1 #else #warning Could not detect platform. Assuming Unix-like. #endif #ifdef EMSCRIPTEN #define HV_EMSCRIPTEN 1 #endif // basic includes #include #ifdef ARM_CORTEX #include #else #include #include #endif // type definitions #include #include #define hv_uint8_t uint8_t #define hv_int16_t int16_t #define hv_uint16_t uint16_t #define hv_int32_t int32_t #define hv_uint32_t uint32_t #define hv_uint64_t uint64_t #define hv_size_t size_t #define hv_uintptr_t uintptr_t // SIMD-specific includes #if !(HV_SIMD_NONE || HV_SIMD_NEON || HV_SIMD_SSE || HV_SIMD_AVX) #define HV_SIMD_NEON __ARM_NEON__ #define HV_SIMD_SSE (__SSE__ && __SSE2__ && __SSE3__ && __SSSE3__ && __SSE4_1__) #define HV_SIMD_AVX (__AVX__ && HV_SIMD_SSE) #endif #ifndef HV_SIMD_FMA #define HV_SIMD_FMA __FMA__ #endif #if HV_SIMD_AVX || HV_SIMD_SSE #include #elif HV_SIMD_NEON #include #endif #if HV_SIMD_NEON // NEON #define HV_N_SIMD 4 #define hv_bufferf_t float32x4_t #define hv_bufferi_t int32x4_t #define hv_bInf_t float32x4_t #define hv_bOutf_t float32x4_t* #define hv_bIni_t int32x4_t #define hv_bOuti_t int32x4_t* #define VIf(_x) (_x) #define VOf(_x) (&_x) #define VIi(_x) (_x) #define VOi(_x) (&_x) #elif HV_SIMD_AVX // AVX #define HV_N_SIMD 8 #define hv_bufferf_t __m256 #define hv_bufferi_t __m256i #define hv_bInf_t __m256 #define hv_bOutf_t __m256* #define hv_bIni_t __m256i #define hv_bOuti_t __m256i* #define VIf(_x) (_x) #define VOf(_x) (&_x) #define VIi(_x) (_x) #define VOi(_x) (&_x) #elif HV_SIMD_SSE // SSE #define HV_N_SIMD 4 #define hv_bufferf_t __m128 #define hv_bufferi_t __m128i #define hv_bInf_t __m128 #define hv_bOutf_t __m128* #define hv_bIni_t __m128i #define hv_bOuti_t __m128i* #define VIf(_x) (_x) #define VOf(_x) (&_x) #define VIi(_x) (_x) #define VOi(_x) (&_x) #else // DEFAULT #define HV_N_SIMD 1 #undef HV_SIMD_NONE #define HV_SIMD_NONE 1 #define hv_bufferf_t float #define hv_bufferi_t int #define hv_bInf_t float #define hv_bOutf_t float* #define hv_bIni_t int #define hv_bOuti_t int* #define VIf(_x) (_x) #define VOf(_x) (&_x) #define VIi(_x) (_x) #define VOi(_x) (&_x) #endif #define HV_N_SIMD_MASK (HV_N_SIMD-1) // Strings #include #define hv_strlen(a) strlen(a) #define hv_strncpy(a, b, c) strncpy(a, b, c) #define hv_strcmp(a, b) strcmp(a, b) #define hv_snprintf(a, b, c, ...) snprintf(a, b, c, __VA_ARGS__) // Memory management #ifndef ARM_CORTEX #define hv_realloc(a, b) realloc(a, b) #endif // ARM_CORTEX #define hv_memcpy(a, b, c) memcpy(a, b, c) #define hv_memclear(a, b) memset(a, 0, b) #if HV_MSVC #include #define hv_alloca(_n) _alloca(_n) #if HV_SIMD_AVX #define hv_malloc(_n) _aligned_malloc(_n, 32) #define hv_realloc(a, b) _aligned_realloc(a, b, 32) #define hv_free(x) _aligned_free(x) #elif HV_SIMD_SSE || HV_SIMD_NEON #define hv_malloc(_n) _aligned_malloc(_n, 16) #define hv_realloc(a, b) _aligned_realloc(a, b, 16) #define hv_free(x) _aligned_free(x) #else // HV_SIMD_NONE #define hv_malloc(_n) malloc(_n) #define hv_free(_n) free(_n) #endif #elif HV_APPLE #define hv_alloca(_n) alloca(_n) #define hv_realloc(a, b) realloc(a, b) #if HV_SIMD_AVX #include #define hv_malloc(_n) _mm_malloc(_n, 32) #define hv_free(x) _mm_free(x) #elif HV_SIMD_SSE #include #define hv_malloc(_n) _mm_malloc(_n, 16) #define hv_free(x) _mm_free(x) #elif HV_SIMD_NEON // malloc on ios always has 16-byte alignment #define hv_malloc(_n) malloc(_n) #define hv_free(x) free(x) #else // HV_SIMD_NONE #define hv_malloc(_n) malloc(_n) #define hv_free(x) free(x) #endif #elif defined ARM_CORTEX #include #define hv_alloca(_n) alloca(_n) #define hv_malloc(_n) pvPortMalloc(_n) #define hv_free(_n) vPortFree(_n) #define hv_realloc(a, b) pvPortRealloc(a, b) #else #include #define hv_alloca(_n) alloca(_n) #if HV_SIMD_AVX #define hv_malloc(_n) aligned_alloc(32, _n) #define hv_free(x) free(x) #elif HV_SIMD_SSE || HV_SIMD_NEON #define hv_malloc(_n) aligned_alloc(16, _n) #define hv_free(x) free(x) #else // HV_SIMD_NONE #define hv_malloc(_n) malloc(_n) #define hv_free(_n) free(_n) #endif #endif // Assert #ifdef ARM_CORTEX #include "message.h" #define hv_assert(e) ASSERT((e), "Heavy assertion failed") #else #include #define hv_assert(e) assert(e) #endif // Export and Inline #if HV_MSVC #define HV_EXPORT __declspec(dllexport) #define inline __inline #define HV_FORCE_INLINE __forceinline #else #define HV_EXPORT #define HV_FORCE_INLINE inline __attribute__((always_inline)) #endif #ifdef __cplusplus extern "C" { #endif // Returns a 32-bit hash of any string. Returns 0 if string is NULL. hv_uint32_t hv_string_to_hash(const char *str); #ifdef __cplusplus } #endif // Math #ifndef ARM_CORTEX #include #endif static inline hv_size_t __hv_utils_max_ui(hv_size_t x, hv_size_t y) { return (x > y) ? x : y; } static inline hv_size_t __hv_utils_min_ui(hv_size_t x, hv_size_t y) { return (x < y) ? x : y; } static inline hv_int32_t __hv_utils_max_i(hv_int32_t x, hv_int32_t y) { return (x > y) ? x : y; } static inline hv_int32_t __hv_utils_min_i(hv_int32_t x, hv_int32_t y) { return (x < y) ? x : y; } #define hv_max_ui(a, b) __hv_utils_max_ui(a, b) #define hv_min_ui(a, b) __hv_utils_min_ui(a, b) #define hv_max_i(a, b) __hv_utils_max_i(a, b) #define hv_min_i(a, b) __hv_utils_min_i(a, b) #define hv_max_f(a, b) fmaxf(a, b) #define hv_min_f(a, b) fminf(a, b) #define hv_max_d(a, b) fmax(a, b) #define hv_min_d(a, b) fmin(a, b) #ifdef ARM_CORTEX #define hv_sin_f(a) arm_sin_f32(a) #define hv_cos_f(a) arm_cos_f32(a) #define hv_sqrt_f(a) arm_sqrtf(a) #define hv_pow_f(a, b) fast_powf(a, b) #define hv_exp_f(a) fast_expf(a) #define hv_log_f(a) fast_logf(a) #else #define hv_sin_f(a) sinf(a) #define hv_cos_f(a) cosf(a) #define hv_sqrt_f(a) sqrtf(a) #define hv_pow_f(a, b) powf(a, b) #define hv_exp_f(a) expf(a) #define hv_log_f(a) logf(a) #endif #define hv_sinh_f(a) sinhf(a) #define hv_cosh_f(a) coshf(a) #define hv_tan_f(a) tanf(a) #define hv_tanh_f(a) tanhf(a) #define hv_asin_f(a) asinf(a) #define hv_asinh_f(a) asinhf(a) #define hv_acos_f(a) acosf(a) #define hv_acosh_f(a) acoshf(a) #define hv_atan_f(a) atanf(a) #define hv_atanh_f(a) atanhf(a) #define hv_atan2_f(a, b) atan2f(a, b) #define hv_abs_f(a) fabsf(a) #if HV_ANDROID // NOTE(mhroth): for whatever silly reason, log2f is not defined! #define hv_log2_f(a) (1.44269504088896f*logf(a)) #else #define hv_log2_f(a) log2f(a) #endif // HV_ANDROID #define hv_log10_f(a) log10f(a) #define hv_ceil_f(a) ceilf(a) #define hv_floor_f(a) floorf(a) #define hv_round_f(a) roundf(a) #if HV_EMSCRIPTEN || defined ARM_CORTEX #define hv_fma_f(a, b, c) ((a*b)+c) // emscripten does not support fmaf (yet?). Inefficient on ARM Cortex M #else #define hv_fma_f(a, b, c) fmaf(a, b, c) #endif #if HV_MSVC // finds ceil(log2(x)) #include static inline hv_uint32_t __hv_utils_min_max_log2(hv_uint32_t x) { unsigned long z = 0; _BitScanReverse(&z, x); return (hv_uint32_t) (z+1); } #else static inline hv_uint32_t __hv_utils_min_max_log2(hv_uint32_t x) { return (hv_uint32_t) (32 - __builtin_clz(x-1)); } #endif #define hv_min_max_log2(a) __hv_utils_min_max_log2(a) // Atomics #if HV_WIN #include #define hv_atomic_bool volatile LONG #define HV_SPINLOCK_ACQUIRE(_x) while (InterlockedCompareExchange(&_x, true, false)) { } #define HV_SPINLOCK_TRY(_x) return !InterlockedCompareExchange(&_x, true, false) #define HV_SPINLOCK_RELEASE(_x) (_x = false) #elif HV_ANDROID // Android support for atomics isn't that great, we'll do it manually // https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html #define hv_atomic_bool hv_uint8_t #define HV_SPINLOCK_ACQUIRE(_x) while (__sync_lock_test_and_set(&_x, 1)) #define HV_SPINLOCK_TRY(_x) return !__sync_lock_test_and_set(&_x, 1) #define HV_SPINLOCK_RELEASE(_x) __sync_lock_release(&_x) #elif defined ARM_CORTEX || HV_EMSCRIPTEN /* no spinlock if we don't have pre-emptive scheduling */ #define hv_atomic_bool volatile bool #define HV_SPINLOCK_ACQUIRE(_x) { extern volatile bool _msgLock; _msgLock = true; } #define HV_SPINLOCK_TRY(_x) { extern volatile bool _msgLock; return !_msgLock; } #define HV_SPINLOCK_RELEASE(_x) { extern volatile bool _msgLock; _msgLock = false; } #elif __cplusplus #include #define hv_atomic_bool std::atomic_flag #define HV_SPINLOCK_ACQUIRE(_x) while (_x.test_and_set(std::memory_order_acquire)) #define HV_SPINLOCK_TRY(_x) return !_x.test_and_set(std::memory_order_acquire) #define HV_SPINLOCK_RELEASE(_x) _x.clear(std::memory_order_release) #elif defined(__has_include) #if __has_include() #include #define hv_atomic_bool atomic_flag #define HV_SPINLOCK_ACQUIRE(_x) while (atomic_flag_test_and_set_explicit(&_x, memory_order_acquire)) #define HV_SPINLOCK_TRY(_x) return !atomic_flag_test_and_set_explicit(&_x, memory_order_acquire) #define HV_SPINLOCK_RELEASE(_x) atomic_flag_clear_explicit(memory_order_release) #endif #endif #ifndef hv_atomic_bool #define hv_atomic_bool volatile bool #define HV_SPINLOCK_ACQUIRE(_x) \ while (_x) {} \ _x = true; #define HV_SPINLOCK_TRY(_x) \ if (!_x) { \ _x = true; \ return true; \ } else return false; #define HV_SPINLOCK_RELEASE(_x) (_x = false) #endif #endif // _HEAVY_UTILS_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739952822.5703619 hvcc-0.13.3/hvcc/generators/c2owl/templates/HeavyOwl.hpp0000644000000000000000000002034014755311267020050 0ustar00{{copyright}} #ifndef __HeavyPatch_hpp__ #define __HeavyPatch_hpp__ #include "Patch.h" #include "basicmaths.h" #include "HvHeavy.h" #include "Heavy_{{name}}.hpp" #include "HeavyOwlConstants.h" #define BUTTON_Push PUSHBUTTON #define BUTTON_B1 BUTTON_A #define BUTTON_B2 BUTTON_B #define BUTTON_B3 BUTTON_C #define BUTTON_B4 BUTTON_D #define BUTTON_B5 BUTTON_E #define BUTTON_B6 BUTTON_F #define BUTTON_B7 BUTTON_G #define BUTTON_B8 BUTTON_H #define HV_HASH_NOTEIN 0x67E37CA3 #define HV_HASH_CTLIN 0x41BE0f9C #define HV_HASH_POLYTOUCHIN 0xBC530F59 #define HV_HASH_PGMIN 0x2E1EA03D #define HV_HASH_TOUCHIN 0x553925BD #define HV_HASH_BENDIN 0x3083F0F7 #define HV_HASH_MIDIIN 0x149631bE #define HV_HASH_MIDIREALTIMEIN 0x6FFF0BCF #define HV_HASH_NOTEOUT 0xD1D4AC2 #define HV_HASH_CTLOUT 0xE5e2A040 #define HV_HASH_POLYTOUCHOUT 0xD5ACA9D1 #define HV_HASH_PGMOUT 0x8753E39E #define HV_HASH_TOUCHOUT 0x476D4387 #define HV_HASH_BENDOUT 0xE8458013 #define HV_HASH_MIDIOUT 0x6511DE55 #define HV_HASH_MIDIOUTPORT 0x165707E4 #define HEAVY_MESSAGE_POOL_SIZE 4 // in kB (default 10kB) #define HEAVY_MESSAGE_IN_QUEUE_SIZE 1 // in kB (default 2kB) #define HEAVY_MESSAGE_OUT_QUEUE_SIZE 0 // in kB (default 0kB) extern "C" { volatile bool _msgLock = false; static bool isButtonPressed(PatchButtonId bid){ return getProgramVector()->buttons & (1<buttons |= 1<buttons &= ~(1<setUserData(this); context->setPrintHook(&owlPrintHook); context->setSendHook(&owlSendHook); {% for param, name, typ, namehash, minvalue, maxvalue, defvalue, button in jdata if button == False %} // {{name}} registerParameter(PARAMETER_{{param}}, HV_NAME_CHANNEL_{{param}}); setParameterValue(PARAMETER_{{param}}, HV_DEFAULT_CHANNEL_{{param}}); {% endfor %} } ~HeavyPatch() { delete context; } uint16_t getButtonValue(PatchButtonId bid, const HvMessage *m){ if(hv_msg_getNumElements(m) > 0 && hv_msg_isFloat(m, 0)) return hv_msg_getFloat(m, 0) > 0.5 ? 4095 : 0; else return isButtonPressed(bid) ? 0 : 4095; // toggle } void sendCallback(uint32_t sendHash, const HvMessage *m){ switch(sendHash){ case HV_HASH_NOTEOUT: { uint8_t note = hv_msg_getFloat(m, 0); uint8_t velocity = hv_msg_getFloat(m, 1); uint8_t ch = hv_msg_getFloat(m, 2); ch %= 16; // drop any pd "ports" // debugMessage("noteout", note, velocity, ch); sendMidi(MidiMessage::note(ch, note, velocity)); } break; case HV_HASH_CTLOUT: { uint8_t value = hv_msg_getFloat(m, 0); uint8_t cc = hv_msg_getFloat(m, 1); uint8_t ch = hv_msg_getFloat(m, 2); ch %= 16; // debugMessage("ctlout", value, cc, ch); sendMidi(MidiMessage::cc(ch, cc, value)); } break; case HV_HASH_BENDOUT: { uint16_t value = hv_msg_getFloat(m, 0); uint8_t ch = hv_msg_getFloat(m, 1); ch %= 16; // debugMessage("bendout", value, ch); sendMidi(MidiMessage::pb(ch, value)); } break; case HV_HASH_POLYTOUCHOUT: { uint8_t value = hv_msg_getFloat(m, 0); uint8_t note = hv_msg_getFloat(m, 1); uint8_t ch = hv_msg_getFloat(m, 2); ch %= 16; sendMidi(MidiMessage::at(ch, note, value)); } break; case HV_HASH_TOUCHOUT: { uint8_t value = hv_msg_getFloat(m, 0); uint8_t ch = hv_msg_getFloat(m, 1); ch %= 16; sendMidi(MidiMessage::cp(ch, value)); } break; case HV_HASH_PGMOUT: { uint8_t value = hv_msg_getFloat(m, 0); uint8_t ch = hv_msg_getFloat(m, 1); ch %= 16; sendMidi(MidiMessage::pc(ch, value)); } break; {% for param, name, typ, namehash, minvalue, maxvalue, defvalue, button in jdata if typ == 'SEND'%} {% if button == True %} // Button {{name}} case HV_HASH_{{typ}}_CHANNEL_{{param}}: setButton(BUTTON_{{param}}, (hv_msg_getFloat(m, 0)-HV_MIN_CHANNEL_{{param}})/ (HV_MAX_CHANNEL_{{param}}-HV_MIN_CHANNEL_{{param}}) > 0.5); {% else %} // Parameter {{name}} case HV_HASH_{{typ}}_CHANNEL_{{param}}: setParameterValue(PARAMETER_{{param}}, (hv_msg_getFloat(m, 0)-HV_MIN_CHANNEL_{{param}})/ (HV_MAX_CHANNEL_{{param}}-HV_MIN_CHANNEL_{{param}})); {% endif %} break; {% endfor %} default: break; } } void processMidi(MidiMessage msg){ // sendMessageToReceiverV parses format and loops over args, see HeavyContext.cpp switch(msg.getStatus()){ case CONTROL_CHANGE: context->sendMessageToReceiverV(HV_HASH_CTLIN, 0, "fff", (float)msg.getControllerValue(), // value (float)msg.getControllerNumber(), // controller number (float)msg.getChannel()); break; case NOTE_ON: context->sendMessageToReceiverV(HV_HASH_NOTEIN, 0, "fff", (float)msg.getNote(), // pitch (float)msg.getVelocity(), // velocity (float)msg.getChannel()); break; case NOTE_OFF: context->sendMessageToReceiverV(HV_HASH_NOTEIN, 0, "fff", (float)msg.getNote(), // pitch 0.0f, // velocity (float)msg.getChannel()); break; case POLY_KEY_PRESSURE: context->sendMessageToReceiverV(HV_HASH_POLYTOUCHIN, 0, "fff", (float)msg.getPolyKeyPressure(), (float)msg.getNote(), (float)msg.getChannel()); break; case CHANNEL_PRESSURE: context->sendMessageToReceiverV(HV_HASH_TOUCHIN, 0, "ff", (float)msg.getChannelPressure(), (float)msg.getChannel()); break; case PITCH_BEND_CHANGE: context->sendMessageToReceiverV(HV_HASH_BENDIN, 0, "ff", (float)msg.getPitchBend(), (float)msg.getChannel()); break; case PROGRAM_CHANGE: context->sendMessageToReceiverV(HV_HASH_PGMIN, 0, "ff", (float)msg.getProgramChange(), (float)msg.getChannel()); break; default: break; } } void buttonChanged(PatchButtonId bid, uint16_t value, uint16_t samples){ if(_msgLock) return; switch(bid){ {% for param, name, typ, namehash, minvalue, maxvalue, defvalue, button in jdata if typ == 'RECV' and button == True %} // {{name}} case BUTTON_{{param}}: context->sendFloatToReceiver(HV_HASH_{{typ}}_CHANNEL_{{param}}, isButtonPressed(BUTTON_{{param}})* (HV_MAX_CHANNEL_{{param}}-HV_MIN_CHANNEL_{{param}})+HV_MIN_CHANNEL_{{param}}); break; {% endfor %} default: break; } } void processAudio(AudioBuffer &buffer) { _msgLock = true; {% for param, name, typ, namehash, minvalue, maxvalue, defvalue, button in jdata if typ == 'RECV' and button == False %} // {{name}} context->sendFloatToReceiver(HV_HASH_{{typ}}_CHANNEL_{{param}}, getParameterValue(PARAMETER_{{param}})* (HV_MAX_CHANNEL_{{param}}-HV_MIN_CHANNEL_{{param}})+HV_MIN_CHANNEL_{{param}}); {% endfor %} _msgLock = false; float* outputs[] = {buffer.getSamples(LEFT_CHANNEL), buffer.getSamples(RIGHT_CHANNEL)}; context->process(outputs, outputs, getBlockSize()); } private: HeavyContext* context; }; static void owlSendHook(HeavyContextInterface* ctxt, const char *receiverName, uint32_t sendHash, const HvMessage *m){ HeavyPatch* patch = (HeavyPatch*)ctxt->getUserData(); patch->sendCallback(sendHash, m); } #endif // __HeavyPatch_hpp__ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7542067 hvcc-0.13.3/hvcc/generators/c2owl/templates/HeavyOwlConstants.h0000644000000000000000000000077714435670357021424 0ustar00{{copyright}} {% for param, name, typ, namehash, minvalue, maxvalue, defvalue, button in jdata %} // {{param}} {{name}} {{typ}} {{namehash}} {{minvalue}} {{maxvalue}} {{defvalue}} {{(defvalue-minvalue)/(maxvalue-minvalue)}} #define HV_NAME_CHANNEL_{{param}} "{{name}}" #define HV_HASH_{{typ}}_CHANNEL_{{param}} {{namehash}} #define HV_MIN_CHANNEL_{{param}} {{minvalue}} #define HV_MAX_CHANNEL_{{param}} {{maxvalue}} #define HV_DEFAULT_CHANNEL_{{param}} {{(defvalue-minvalue)/(maxvalue-minvalue)}} {% endfor %} ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7542067 hvcc-0.13.3/hvcc/generators/c2pdext/__init__.py0000644000000000000000000000000014435670357016231 0ustar00././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.267823 hvcc-0.13.3/hvcc/generators/c2pdext/c2pdext.py0000644000000000000000000001043414735300474016050 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2021-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os import shutil import time import jinja2 from typing import Optional from ..copyright import copyright_manager from ..filters import filter_max from hvcc.interpreters.pd2hv.NotificationEnum import NotificationEnum from hvcc.types.compiler import Generator, CompilerResp, CompilerNotif, CompilerMsg, ExternInfo from hvcc.types.meta import Meta class c2pdext(Generator): """Generates a Pure Data external wrapper for a given patch. """ @classmethod def compile( cls, c_src_dir: str, out_dir: str, externs: ExternInfo, patch_name: Optional[str] = None, patch_meta: Meta = Meta(), num_input_channels: int = 0, num_output_channels: int = 0, copyright: Optional[str] = None, verbose: Optional[bool] = False ) -> CompilerResp: tick = time.time() out_dir = os.path.join(out_dir, "pdext") receiver_list = externs.parameters.inParam copyright = copyright_manager.get_copyright_for_c(copyright) patch_name = patch_name or "heavy" ext_name = f"{patch_name}~" struct_name = f"{patch_name}_tilde" # ensure that the output directory does not exist out_dir = os.path.abspath(out_dir) if os.path.exists(out_dir): shutil.rmtree(out_dir) # copy over generated C source files shutil.copytree(c_src_dir, out_dir) # copy over static files shutil.copy( os.path.join(os.path.dirname(os.path.abspath(__file__)), "static", "m_pd.h"), f"{out_dir}/") shutil.copy( os.path.join(os.path.dirname(os.path.abspath(__file__)), "static", "Makefile.pdlibbuilder"), f"{out_dir}/../") try: # initialise the jinja template environment env = jinja2.Environment() env.filters["max"] = filter_max env.loader = jinja2.FileSystemLoader( os.path.join(os.path.dirname(os.path.abspath(__file__)), "templates")) # generate Pd external wrapper from template pdext_path = os.path.join(out_dir, f"{ext_name}.c") with open(pdext_path, "w") as f: f.write(env.get_template("pd_external.c").render( name=patch_name, struct_name=struct_name, display_name=ext_name, num_input_channels=num_input_channels, num_output_channels=num_output_channels, receivers=receiver_list, copyright=copyright)) # generate Makefile from template pdext_path = os.path.join(out_dir, "../Makefile") with open(pdext_path, "w") as f: f.write(env.get_template("Makefile").render( name=patch_name)) return CompilerResp( stage="c2pdext", in_dir=c_src_dir, out_dir=out_dir, out_file=os.path.basename(pdext_path), compile_time=time.time() - tick ) except Exception as e: return CompilerResp( stage="c2pdext", notifs=CompilerNotif( has_error=True, exception=e, warnings=[], errors=[CompilerMsg( enum=NotificationEnum.ERROR_EXCEPTION, message=str(e) )] ), in_dir=c_src_dir, out_dir=out_dir, compile_time=time.time() - tick ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5931823 hvcc-0.13.3/hvcc/generators/c2pdext/static/Makefile.pdlibbuilder0000644000000000000000000013145114735300037021512 0ustar00# Makefile.pdlibbuilder dated 2019-12-21 version = 0.7.0 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. # Inspired by Hans Christoph Steiner's Makefile Template and Stephan Beal's # ShakeNMake. # # Grab the newest version of Makefile.pdlibbuilder from # https://github.com/pure-data/pd-lib-builder/ # # GNU make version >= 3.81 required. # # #=== characteristics =========================================================== # # # - defines build settings based on autodetected OS and architecture # - defines rules to build Pd class- or lib executables from C or C++ sources # - defines rules for libdir installation # - defines convenience targets for developer and user # - evaluates implicit dependencies for non-clean builds # # #=== basic usage =============================================================== # # # In your Makefile, define your Pd lib name and class files, and include # Makefile.pdlibbuilder at the end of the Makefile. Like so: # # ________________________________________________________________________ # # # Makefile for mylib # # lib.name = mylib # # class.sources = myclass1.c myclass2.c # # datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENSE.txt # # include Makefile.pdlibbuilder # ________________________________________________________________________ # # # For files in class.sources it is assumed that class basename == source file # basename. The default target builds all classes as individual executables # with Pd's default extension for the platform. For anything more than the # most basic usage, continue reading. # # #=== list of Makefile.pdlibbuilder API variables =============================== # # # Variables available for definition in your library Makefile: # # - lib.name # - lib.setup.sources # - class.sources # - common.sources # - shared.sources # - .class.sources # - .class.ldflags # - .class.ldlibs # - cflags # - ldflags # - ldlibs # - datafiles # - datadirs # - makefiles # - makefiledirs # - externalsdir # # Optional multiline defines evaluated per operating system: # # - forLinux # - forDarwin # - forWindows # # Variables available for your makefile or make command line: # # - make-lib-executable # - suppress-wunused # # Path variables for make command line or environment: # # - PDDIR # - PDINCLUDEDIR # - PDBINDIR # - PDLIBDIR # # Standard make variables for make command line or environment: # # - CPPFLAGS # - CFLAGS # - LDFLAGS # - CC # - CXX # - INSTALL # - STRIP # - DESTDIR # # Optional user variables for make command line or environment: # # - PLATFORM # - extension # - floatsize # # Deprecated path variables: # # - pdincludepath # - pdbinpath # - objectsdir # # #=== descriptions of Makefile.pdlibbuilder API variables ======================= # # # lib.name: # Name of the library directory as it will be installed / distributed. Also the # name of the lib executable in the case where all classes are linked into # a single binary. # # lib.setup.sources: # Source file(s) (C or C++) which must be compiled only when linking all classes # into a single lib binary. # # class.sources: # All sources files (C or C++) for which the condition holds that # class name == source file basename. # # .class.sources: # Source file(s) (C or C++) specific to class . Use this for # multiple-source classes or when class name != source file basename. # # common.sources: # Source file(s) which must be statically linked to each class in the library. # # shared.sources: # Source file(s) (C or C++) to build a shared dynamic link lib, to be linked # with all class executables. # # cflags, ldflags, ldlibs: # Define cflags (preprocessor&compiler), ldflags (linker) and ldlibs (dynamic # link libs) for the whole library. These flags are added to platform-specific # flags defined by Makefile.pdlibbuilder. # # .class.ldflags and .class.ldlibs: # Define ldflags resp. ldlibs specific to class . These flags are # added to platform-specific flags defined by Makefile.pdlibbuilder, and flags # defined in your Makefile for the whole library. Note: cflags can not be # defined per class in the current implementation. # # datafiles and datadirs: # All extra files you want to include in binary distributions of the # library: abstractions and help patches, example patches, meta patch, readme # and license texts, manuals, sound files, etcetera. Use 'datafiles' for all # files that should go into your lib rootdir and 'datadirs' for complete # directories you want to copy from source to distribution. # # forLinux, forDarwin, forWindows: # Shorthand for 'variable definitions for Linux only' etc. Use like: # define forLinux # cflags += -DLINUX # class.sources += linuxthing.c # endef # # makefiles and makefiledirs: # Extra makefiles or directories with makefiles that should be made in sub-make # processes. # # make-lib-executable: # When this variable is defined 'yes' in your makefile or as command argument, # Makefile.pdlibbuilder will try to build all classes into a single library # executable (but it will force exit if lib.setup.sources is undefined). # If your makefile defines 'make-lib-executable=yes' as the library default, # this can still be overridden with 'make-lib-executable=no' as command argument # to build individual class executables (the Makefile.pdlibbuilder default.) # # suppress-wunused: # When this variable is defined ('yes' or any other value), -Wunused-variable, # -Wunused-parameter, -Wunused-value and -Wunused-function are suppressed, # but the other warnings from -Wall are retained. # # PDDIR: # Root directory of 'portable' pd package. When defined, PDINCLUDEDIR and # PDBINDIR will be evaluated as $(PDDIR)/src and $(PDDIR)/bin. # # PDINCLUDEDIR: # Directory where Pd API m_pd.h should be found, and other Pd header files. # Overrides the default search path. # # PDBINDIR: # Directory where pd.dll should be found for linking (Windows only). Overrides # the default search path. # # PDLIBDIR: # Root directory for installation of Pd library directories. Overrides the # default install location. # # DESTDIR: # Prepended path component for staged install. # # PLATFORM: # Target platform for cross compilation in the form of GNU triplet: # cpu-vendor-os. Example: x86_64-w64-mingw32. This specifies the tool chain that # pdlibbuilder will use, if installed and locatable. System and architecture # will then be autodefined accordingly. In most cases no other variables need to # be overridden. # # extension: # Extension for the external to use. Example: m_amd64 # A sane default is picked, but it is useful if you want to provide # co-installable externals for multiple platforms (for the same operating # systems) # # floatsize: # the size of the t_float in bits. Example: 32 # t_float are usually single precision (32bit), which is the default. # For double precision use floatsize=64 # When building double precision externals, you will want to set the extension # as well, e.g. extension=windows-amd64-64.dll (--.) # # CPPFLAGS: # Preprocessor flags which are not strictly required for building. # # CFLAGS: # Compiler flags which are not strictly required for building. Compiler flags # defined by Makefile.pdlibbuilder for warning, optimization and architecture # specification are overriden by CFLAGS. # # LDFLAGS: # Linker flags which are not strictly required for building. Linker flags # defined by Makefile.pdlibbuilder for architecture specification are overriden # by LDFLAGS. # # CC and CXX: # C and C++ compiler programs as defined in your build environment. # # INSTALL # Definition of install program. # # STRIP # Name of strip program. Default 'strip' can be overridden in cross compilation # environments. # # objectsdir: # Root directory for installation of Pd library directories, like PDLIBDIR but # not overridable by environment. Supported for compatibility with pd-extended # central makefile, but deprecated otherwise. # # pdincludepath, pdbinpath: # As PDINCLUDEDIR and PDBINDIR but not overridable by environment. Deprecated # as user variables. # # #=== paths ===================================================================== # # # Source files in directories other than current working directory must be # prefixed with their relative path. Do not rely on VPATH or vpath. # Object (.o) files are built in the directory of their source files. # Executables are built in current working directory. # # Default search path for m_pd.h and other API header files is platform # dependent, and overridable by PDINCLUDEDIR: # # Linux: /usr/include/pd # # OSX: /Applications/Pd*.app/Contents/Resources/src # # Windows: %PROGRAMFILES%/Pd/src # %PROGRAMFILES(X86)%/Pd/src (32 bit builds on 64 bit Windows) # # Default search path for binary pd.dll (Windows), overridable by PDBINDIR # # %PROGRAMFILES%/Pd/bin # %PROGRAMFILES(X86)%/Pd/bin (32 bit builds on 64 bit Windows) # # Default location to install pd libraries is platform dependent, and # overridable by PDLIBDIR: # # Linux: /usr/local/lib/pd-externals # OSX: ~/Library/Pd # Windows: %APPDATA%/Pd # # https://puredata.info/docs/faq/how-do-i-install-externals-and-help-files # The rationale for not installing to ~/pd-externals by default on Linux # is that some people share the home dir between 32 and 64 bit installations. # # #=== targets =================================================================== # # # all: build $(executables) plus optional post target # post: target to build after $(executables) # alldebug: build all with -g option turned on for debug symbols # : force clean build of an individual class # .pre: make preprocessor output file in current working directory # .lst: make asm/source output file in current working directory # # install: install executables and data files # clean: remove build products from source tree # # help: print help text # vars: print makefile variables # allvars: print all variables # depend: print generated prerequisites # dumpmachine: print compiler output of option '-dumpmachine' # coffee: dummy target # # Variable $(executables) expands to class executables plus optional shared lib, # or alternatively to single lib executable when make-lib-executable=true. # Targets pre and post can be defined by library makefile. Make sure to include # Makefile.pdlibbuilder first so default target all will not be redefined. # # #=== Pd-extended libdir concept ================================================ # # # For libdir layout as conceived by Hans-Christoph Steiner, see: # # https://puredata.info/docs/developer/Libdir # # Files README.txt, LICENSE.txt and -meta.pd are part of the libdir # convention. Help patches for each class and abstraction are supposed to be # available. Makefile.pdlibbuilder does not force the presence of these files # however. It does not automatically include such files in libdir installations. # Data files you want to include in distributions must be defined explicitly in # your Makefile. # # #=== Makefile.pdlibbuilder syntax conventions ================================== # # # Makefile.pdlibbuilder variable names are lower case. Default make variables, # environment variables, and standard user variables (CC, CXX, CFLAGS, DESTDIR) # are upper case. Use target 'allvars' to print all variables and their values. # # 'Fields' in data variables are separated by dots, like in 'foo.class.sources'. # Words in variables expressing a function or command are separated by dashes, # like in 'make-lib-executable'. # # #=== useful make options ======================================================= # # # Use 'make -d ' to print debug details of the make process. # Use 'make -p ' to print make's database. # # #=== TODO ====================================================================== # # # - decide whether to use -static-libgcc or shared dll in MinGW # - cygwin support # - android support # - figure out how to handle '$' in filenames # - add makefile template targets dpkg-source dist libdir distclean tags? # # #=== end of documentation sections ============================================= # # ################################################################################ ################################################################################ ################################################################################ # GNU make version 3.81 (2006) or higher is required because of the following: # - function 'info' # - variable '.DEFAULT_GOAL' # force exit when make version is < 3.81 ifneq ($(firstword $(sort 3.81 $(MAKE_VERSION))), 3.81) $(error GNU make version 3.81 or higher is required) endif # Relative path to externals root dir in multi-lib source tree like # pd-extended SVN. Default is parent of current working directory. May be # defined differently in including makefile. externalsdir ?= .. # variable you can use to check if Makefile.pdlibbuilder is already included Makefile.pdlibbuilder = true ################################################################################ ### target platform detection ################################################## ################################################################################ #=== target platform =========================================================== # PLATFORM: optional user variable to define target platform for cross # compilation. Redefine build tools accordingly. PLATFORM should match # the exact target prefix of tools present in $PATH, like x86_64-w64-mingw32, # x86_64-apple-darwin12 etc. Tool definitions are exported to ensure submakes # will get the same. ifneq ($(PLATFORM),) ifneq ($(findstring darwin, $(PLATFORM)),) export CC = $(PLATFORM)-cc export CXX = $(PLATFORM)-c++ export CPP = $(PLATFORM)-cc else export CC = $(PLATFORM)-gcc export CXX = $(PLATFORM)-g++ export CPP = $(PLATFORM)-cpp endif STRIP = $(PLATFORM)-strip endif # Let (native or cross-) compiler report target triplet and isolate individual # words therein to facilitate later processing. target.triplet := $(subst -, ,$(shell $(CC) -dumpmachine)) #=== operating system ========================================================== # The following systems are defined: Linux, Darwin, Windows. GNU and # GNU/kFreeBSD are treated as Linux to get the same options. ifneq ($(filter linux gnu% kfreebsd, $(target.triplet)),) system = Linux endif ifneq ($(filter darwin%, $(target.triplet)),) system = Darwin endif ifneq ($(filter mingw% cygwin%, $(target.triplet)),) system = Windows endif # evaluate possible system-specific multiline defines from library makefile $(eval $(for$(system))) # TODO: Cygwin, Android #=== architecture ============================================================== # The following CPU names can be processed by pdlibbuilder: # i*86 Intel 32 bit # x86_64 Intel 64 bit # arm ARM 32 bit # aarch64 ARM 64 bit target.arch := $(firstword $(target.triplet)) ################################################################################ ### variables per platform ##################################################### ################################################################################ #=== flags per floatsize == ==================================================== floatsize = 32 ifneq ($(filter-out 32,$(floatsize)),) floatsize.flags = -DPD_FLOATSIZE=$(floatsize) else floatsize.flags = endif #=== flags per architecture ==================================================== # Set architecture-dependent cflags, mainly for Linux. For Mac and Windows, # arch.c.flags are overriden below. To see gcc's default architecture flags: # $ gcc -Q --help=target # ARMv6: Raspberry Pi 1st gen, not detectable from target.arch ifeq ($(shell uname -m), armv6l) arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard # ARMv7: Beagle, Udoo, RPi2 etc. else ifeq ($(target.arch), arm) arch.c.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard # ARMv8 64 bit, not tested yet else ifeq ($(target.arch), aarch64) arch.c.flags = -mcpu=cortex-a53 # Intel 32 bit, build with SSE and SSE2 instructions else ifneq ($(filter i%86, $(target.arch)),) arch.c.flags = -march=pentium4 -mfpmath=sse -msse -msse2 # Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions else ifeq ($(target.arch), x86_64) arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 # if none of the above architectures detected else arch.c.flags = endif #=== flags and paths for Linux ================================================= ifeq ($(system), Linux) prefix = /usr/local libdir := $(prefix)/lib pkglibdir = $(libdir)/pd-externals pdincludepath := $(wildcard /usr/include/pd) extension = pd_linux cpp.flags := -DUNIX c.flags := -fPIC c.ldflags := -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags c.ldlibs := -lc -lm cxx.flags := -fPIC -fcheck-new cxx.ldflags := -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags cxx.ldlibs := -lc -lm -lstdc++ shared.extension = so shared.ldflags = -rdynamic -fPIC -shared -Wl,-soname,$(shared.lib) endif #=== flags and paths for Darwin ================================================ # LLVM-clang doesn't support -fcheck-new, therefore this flag is only used when # compiling with g++. ifeq ($(system), Darwin) pkglibdir = $(HOME)/Library/Pd pdincludepath := $(firstword $(wildcard \ /Applications/Pd*.app/Contents/Resources/src)) extension = pd_darwin cpp.flags := -DUNIX -DMACOSX -I /sw/include c.flags := c.ldflags := -undefined suppress -flat_namespace -bundle c.ldlibs := -lc cxx.ldflags := -undefined suppress -flat_namespace -bundle cxx.ldlibs := -lc shared.extension = dylib shared.ldflags = -dynamiclib -undefined dynamic_lookup \ -install_name @loader_path/$(shared.lib) \ -compatibility_version 1 -current_version 1.0 ifneq ($(filter %g++, $(CXX)),) cxx.flags := -fcheck-new endif ifeq ($(extension), d_fat) arch := i386 x86_64 else arch := $(target.arch) endif ifneq ($(filter -mmacosx-version-min=%, $(cflags)),) version.flag := $(filter -mmacosx-version-min=%, $(cflags)) else version.flag = -mmacosx-version-min=10.6 endif arch.c.flags := $(addprefix -arch , $(arch)) $(version.flag) arch.ld.flags := $(arch.c.flags) endif #=== flags and paths for Windows =============================================== # Standard paths on Windows contain spaces, and GNU make functions treat such # paths as lists, with unintended effects. Therefore we must use shell function # ls instead of make's wildcard when probing for a path, and use double quotes # when specifying a path in a command argument. # Default paths in Mingw / Mingw-w64 environments. 'PROGRAMFILES' is standard # location for builds with native architecture, 'ProgramFiles(x86)' for i686 # builds on x86_64 Windows (detection method by Lucas Cordiviola). Curly braces # required because of parentheses in variable name. ifeq ($(system), Windows) pkglibdir := $(APPDATA)/Pd ifeq ($(target.arch), i686) programfiles := ${ProgramFiles(x86)} else programfiles := $(PROGRAMFILES) endif pdbinpath := $(programfiles)/Pd/bin pdincludepath := $(programfiles)/Pd/src endif # Store default path to pd.dll in PDBINDIR if the latter is not user-defined. # For include path this is done in the platform-independent paths section below, # but for PDBINDIR it is done here so ld flags can be evaluated as immediate # variables. ifeq ($(system), Windows) ifdef PDDIR PDBINDIR := $(PDDIR)/bin endif PDBINDIR ?= $(pdbinpath) endif # TODO: decide whether -mms-bitfields should be specified. ifeq ($(system), Windows) cpp.flags := -DMSW -DNT ifeq ($(target.arch), i686) arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse else ifeq ($(target.arch), x86_64) cpp.flags := -DMSW -DNT -DPD_LONGINTTYPE=__int64 arch.c.flags := -march=core2 -msse -msse2 -msse3 -mfpmath=sse else arch.c.flags = endif extension = dll c.flags := c.ldflags := -static-libgcc -shared \ -Wl,--enable-auto-import "$(PDBINDIR)/pd$(filter-out 32,$(floatsize)).dll" c.ldlibs := cxx.flags := -fcheck-new cxx.ldflags := -static-libgcc -static-libstdc++ -shared \ -Wl,--enable-auto-import "$(PDBINDIR)/pd$(filter-out 32,$(floatsize)).dll" cxx.ldlibs := shared.extension = dll shared.ldflags := -static-libgcc -shared "$(PDBINDIR)/pd$(filter-out 32,$(floatsize)).dll" stripflags = --strip-all endif #=== paths ===================================================================== # Platform-dependent default paths are specified above, but overridable. # Path variables in upper case can be defined as make command argument or in the # environment. Variable 'objectsdir' is supported for compatibility with # the build system that pd-l2ork has inherited from pd-extended. PDINCLUDEDIR ?= $(pdincludepath) PDLIBDIR ?= $(firstword $(objectsdir) $(pkglibdir)) ifdef PDDIR PDINCLUDEDIR := $(wildcard $(PDDIR)/src) endif # base path where all components of the lib will be installed by default installpath := $(DESTDIR)$(PDLIBDIR)/$(lib.name) # check if include path contains spaces (as is often the case on Windows) # if so, store the path so we can later do checks with it pdincludepathwithspaces := $(if $(word 2, $(PDINCLUDEDIR)), $(PDINCLUDEDIR)) #=== accumulated build flags =================================================== # From GNU make docs: 'Users expect to be able to specify CFLAGS freely # themselves.' So we use CFLAGS to define options which are not strictly # required for compilation: optimizations, architecture specifications, and # warnings. CFLAGS can be safely overriden using a make command argument. # Variables cflags, ldflags and ldlibs may be defined in including makefile. optimization.flags = -O3 -ffast-math -funroll-loops -fomit-frame-pointer warn.flags = -Wall -Wextra -Wshadow -Winline -Wstrict-aliasing # suppress -Wunused-variable & Co if you don't want to clutter a build log ifdef suppress-wunused warn.flags += $(addprefix -Wno-unused-, function parameter value variable) endif CFLAGS = $(warn.flags) $(optimization.flags) $(arch.c.flags) # preprocessor flags cpp.flags := -DPD -I "$(PDINCLUDEDIR)" $(floatsize.flags) $(cpp.flags) $(CPPFLAGS) # flags for dependency checking (cflags from makefile may define -I options) depcheck.flags := $(cpp.flags) $(cflags) # architecture specifications for linker are overridable by LDFLAGS LDFLAGS := $(arch.ld.flags) # now add the same ld flags to shared dynamic lib shared.ldflags += $(LDFLAGS) # accumulated flags for C compiler / linker c.flags := $(cpp.flags) $(c.flags) $(cflags) $(CFLAGS) c.ldflags := $(c.ldflags) $(ldflags) $(LDFLAGS) c.ldlibs := $(c.ldlibs) $(ldlibs) # accumulated flags for C++ compiler / linker cxx.flags := $(cpp.flags) $(cxx.flags) $(cflags) $(CFLAGS) cxx.ldflags := $(cxx.ldflags) $(ldflags) $(LDFLAGS) cxx.ldlibs := $(cxx.ldlibs) $(ldlibs) ################################################################################ ### variables: library name and version ######################################## ################################################################################ # strip possibles spaces from lib.name, they mess up calculated file names lib.name := $(strip $(lib.name)) # if meta file exists, check library version metafile := $(wildcard $(lib.name)-meta.pd) ifdef metafile lib.version := $(shell sed -n \ 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' \ $(metafile)) endif ################################################################################ ### variables: files ########################################################### ################################################################################ object.extension = $(extension).o #=== sources =================================================================== # (re)define .class.sources using file names in class.sources define add-class-source $(notdir $(basename $v)).class.sources += $v endef $(foreach v, $(class.sources), $(eval $(add-class-source))) # derive class names from .class.sources variables sourcevariables := $(filter %.class.sources, $(.VARIABLES)) classes := $(basename $(basename $(sourcevariables))) # accumulate all source files specified in makefile classes.sources := $(sort $(foreach v, $(sourcevariables), $($v))) all.sources := $(classes.sources) $(lib.setup.sources) \ $(shared.sources) $(common.sources) #=== object files ============================================================== # construct object filenames from all C and C++ source file names classes.objects := $(addsuffix .$(object.extension), $(basename $(classes.sources))) common.objects := $(addsuffix .$(object.extension), $(basename $(common.sources))) shared.objects := $(addsuffix .$(object.extension), $(basename $(shared.sources))) lib.setup.objects := $(addsuffix .$(object.extension), $(basename $(lib.setup.sources))) all.objects = $(classes.objects) $(common.objects) $(shared.objects) \ $(lib.setup.objects) #=== executables =============================================================== # construct class executable names from class names classes.executables := $(addsuffix .$(extension), $(classes)) # Construct shared lib executable name if shared sources are defined. # If extension does not end with shared extension, use both to facilitate co- # installation for different platforms, like .m_i386.dll and .linux-amd64-32.so ifdef shared.sources ifneq ($(filter %.$(shared.extension), .$(extension)), ) # $(extension) already ends with $(shared.extension), no need to duplicate it shared.lib = lib$(lib.name).$(extension) else shared.lib = lib$(lib.name).$(extension).$(shared.extension) endif else shared.lib := endif ################################################################################ ### variables: tools ########################################################### ################################################################################ # aliases so we can later define 'compile-$1' and set 'c' or 'cxx' as argument compile-c := $(CC) compile-cxx := $(CXX) ################################################################################ ### checks ##################################################################### ################################################################################ # At this point most variables are defined. Now do some checks and info's # before rules begin. # print Makefile.pdlibbuilder version before possible termination $(info ++++ info: using Makefile.pdlibbuilder version $(version)) # Terminate if target triplet remained empty, to avoid all sorts of confusing # scenarios and spurious bugs. ifeq ($(target.triplet),) $(error Command "$(CC) -dumpmachine" did not return a target triplet, \ needed for a build. \ Is compiler "$(CC)" installed in your PATH? ($(PATH)). \ Does compiler "$(CC)" support option "-dumpmachine"?) endif # 'forward declaration' of default target, needed to do checks all: # To avoid unpredictable results, make sure the default target is not redefined # by including makefile. ifneq ($(.DEFAULT_GOAL), all) $(error Default target must be 'all'.) endif # find out which target(s) will be made ifdef MAKECMDGOALS goals := $(MAKECMDGOALS) else goals := all endif # store path to Pd API m_pd.h if it is found ifdef PDINCLUDEDIR mpdh := $(shell ls "$(PDINCLUDEDIR)/m_pd.h") endif # store path to pd.dll; if not found, ls will give a useful error ifeq ($(system), Windows) pddll := $(shell ls "$(PDBINDIR)/pd$(filter-out 32,$(floatsize)).dll") endif # when making target all, check if m_pd.h is found and print info about it ifeq ($(goals), all) $(if $(mpdh), \ $(info ++++ info: using Pd API $(mpdh)), \ $(warning Where is Pd API m_pd.h? Do 'make help' for info.)) endif # print target info $(info ++++ info: making target $(goals) $(if $(lib.name),in lib $(lib.name))) # when installing, print installpath info $(if $(filter install install-lib, $(goals)), $(info ++++ info: \ installpath is '$(installpath)')) #=== define executables ======================================================== # By default we build class executables, and optionally a shared dynamic link # lib. When make-lib-executable=yes we build all classes into a single lib # executable, on the condition that variable lib.setup.sources is defined. ifeq ($(make-lib-executable),yes) $(if $(lib.setup.sources), ,\ $(error Can not build library blob because lib.setup.sources is undefined)) executables := $(lib.name).$(extension) else executables := $(classes.executables) $(shared.lib) endif ################################################################################ ### rules: special targets ##################################################### ################################################################################ # Disable built-in rules. If some target can't be built with the specified # rules, it should not be built at all. MAKEFLAGS += --no-builtin-rules .PRECIOUS: .SUFFIXES: .PHONY: all post build-lib \ $(classes) $(makefiledirs) $(makefiles) \ install install-executables install-datafiles install-datadirs \ force clean vars allvars depend help ################################################################################ ### rules: build targets ####################################################### ################################################################################ # Target all forces the build of targets [$(executables) post] in # deterministic order. Target $(executables) builds class executables plus # optional shared lib or alternatively a single lib executable when # make-lib-executable=true. Target post is optionally defined by # library makefile. all: post post: $(executables) all: $(info ++++info: target all in lib $(lib.name) completed) # build all with -g option turned on for debug symbols alldebug: c.flags += -g alldebug: cxx.flags += -g alldebug: all #=== class executable ========================================================== # recipe for linking objects in class executable # argument $1 = compiler type (c or cxx) # argument $2 = class basename define link-class $(compile-$1) \ $($1.ldflags) $($2.class.ldflags) \ -o $2.$(extension) \ $(addsuffix .$(object.extension), $(basename $($2.class.sources))) \ $(addsuffix .$(object.extension), $(basename $(common.sources))) \ $($1.ldlibs) $($2.class.ldlibs) $(shared.lib) endef # general rule for linking object files in class executable %.$(extension): $(shared.lib) $(info ++++ info: linking objects in $@ for lib $(lib.name)) $(if $(filter %.cc %.cpp, $($*.class.sources)), \ $(call link-class,cxx,$*), \ $(call link-class,c,$*)) #=== library blob ============================================================== # build all classes into single executable build-lib: $(lib.name).$(extension) $(info ++++ info: library blob $(lib.name).$(extension) completed) # recipe for linking objects in lib executable # argument $1 = compiler type (c or cxx) define link-lib $(compile-$1) \ $($1.ldflags) $(lib.ldflags) \ -o $(lib.name).$(extension) $(all.objects) \ $($1.ldlibs) $(lib.ldlibs) endef # rule for linking objects in lib executable # declared conditionally to avoid name clashes ifeq ($(make-lib-executable),yes) $(lib.name).$(extension): $(all.objects) $(if $(filter %.cc %.cpp, $(all.sources)), \ $(call link-lib,cxx), \ $(call link-lib,c)) endif #=== shared dynamic lib ======================================================== # recipe for linking objects in shared executable # argument $1 = compiler type (c or cxx) define link-shared $(compile-$1) \ $(shared.ldflags) \ -o $(shared.lib) $(shared.objects) \ $($1.ldlibs) $(shared.ldlibs) endef # rule for linking objects in shared executable # build recipe is in macro 'link-shared' $(shared.lib): $(shared.objects) $(info ++++ info: linking objects in shared lib $@) $(if $(filter %.cc %.cpp, $(shared.sources)), \ $(call link-shared,cxx), \ $(call link-shared,c)) #=== object files ============================================================== # recipe to make .o file from source # argument $1 is compiler type (c or cxx) define make-object-file $(info ++++ info: making $@ in lib $(lib.name)) $(compile-$1) \ $($1.flags) \ -o $@ -c $< endef # Three rules to create .o files. These are double colon 'terminal' rules, # meaning they are the last in a rules chain. %.$(object.extension):: %.c $(call make-object-file,c) %.$(object.extension):: %.cc $(call make-object-file,cxx) %.$(object.extension):: %.cpp $(call make-object-file,cxx) #=== explicit prerequisites for class executables ============================== # For class executables, prerequisite rules are declared in run time. Target # 'depend' prints these rules for debugging purposes. # declare explicit prerequisites rule like 'class: class.extension' # argument $v is class basename define declare-class-target $v: $v.$(extension) endef # declare explicit prerequisites rule like 'class.extension: object1.o object2.o' # argument $v is class basename define declare-class-executable-target $v.$(extension): $(addsuffix .$(object.extension), $(basename $($v.class.sources))) \ $(addsuffix .$(object.extension), $(basename $(common.sources))) endef # evaluate explicit prerequisite rules for all classes $(foreach v, $(classes), $(eval $(declare-class-target))) $(foreach v, $(classes), $(eval $(declare-class-executable-target))) #=== implicit prerequisites for class executables ============================== # Evaluating implicit prerequisites (header files) with help from the # preprocessor is 'expensive' so this is done conditionally and selectively. # Note that it is also possible to trigger a build via install targets, in # which case implicit prerequisites are not checked. # When the Pd include path contains spaces it will mess up the implicit # prerequisites rules. disable-dependency-tracking := $(strip $(pdincludepathwithspaces)) ifndef disable-dependency-tracking must-build-everything := $(filter all, $(goals)) must-build-class := $(filter $(classes), $(goals)) must-build-sources := $(foreach v, $(must-build-class), $($v.class.sources)) endif # declare implicit prerequisites rule like 'object.o: header1.h header2.h ...' # argument $1 is input source file(s) # dir is explicitly added because option -MM strips it by default define declare-object-target $(dir $1)$(patsubst %.o:,%.$(object.extension):,$(filter %.o: %.h, $(shell $(CPP) $(depcheck.flags) -MM $1))) $(MAKEFILE_LIST) endef # evaluate implicit prerequisite rules when rebuilding everything ifdef must-build-everything $(if $(wildcard $(all.objects)), \ $(info ++++ info: evaluating implicit prerequisites in lib $(lib.name).....) \ $(foreach v, $(all.sources), $(eval $(call declare-object-target, $v)))) endif # evaluate implicit prerequisite rules when selectively building classes ifdef must-build-class $(foreach v, $(must-build-sources), \ $(eval $(call declare-object-target, $v))) $(foreach v, $(shared.sources), \ $(eval $(call declare-object-target, $v))) endif ################################################################################ ### rules: preprocessor and assembly files ##################################### ################################################################################ # Preprocessor and assembly output files for bug tracing etc. They are not part # of the build processes for executables. By default these files are created in # the current working directory. Dependency tracking is not performed, the build # is forced instead to make sure it's up to date. force: #=== preprocessor file ========================================================= # make preprocessor output file with extension .pre # argument $1 = compiler type (c or cxx) define make-preprocessor-file $(info ++++ info: making preprocessor output file $(notdir $*.pre) \ in current working directory) $(compile-$1) -E $< $(c.flags) $($1.flags) -o $(notdir $*.pre) endef %.pre:: %.c force $(call make-preprocessor-file,c) %.pre:: %.cc force $(call make-preprocessor-file,cxx) %.pre:: %.cpp force $(call make-preprocessor-file,cxx) #=== assembly file ============================================================= # make C / assembly interleaved output file with extension .lst # argument $1 = compiler type (c or cxx) define make-assembly-file $(info ++++ info: making assembly output file $(notdir $*.lst) \ in current working directory) $(compile-$1) \ -c -Wa,-a,-ad -fverbose-asm \ $($1.flags) \ $< > $(notdir $*.lst) endef %.lst:: %.c force $(call make-assembly-file,c) %.lst:: %.cc force $(call make-assembly-file,cxx) %.lst:: %.cpp force $(call make-assembly-file,cxx) ################################################################################ ### rules: installation targets ################################################ ################################################################################ #=== strip ===================================================================== # Stripping of installed binaries will only be done when variable 'stripflags' # is defined non-empty. No default definition is provided except for Windows # where the unstripped binaries are large, especially in the case of Mingw-w64. # Note: while stripping all symbols ('-s' or '--strip-all') is possible for # Linux and Windows, in the case of OSX only non-global symbols can be stripped # (option '-x' or '--discard-all'). # Make definition of strip command overridable so it can be defined in an # environment for cross-compilation. STRIP ?= strip # Commands in 'strip-executables' will be executed conditionally in the rule for # target 'install-executables'. strip-executables = cd "$(installpath)" && \ $(foreach v, $(executables), $(STRIP) $(stripflags) '$v';) #=== install =================================================================== # Install targets depend on successful exit status of target all because nothing # must be installed in case of a build error. # -p = preserve time stamps # -m = set permission mode (as in chmod) # -d = create all components of specified directories INSTALL = install INSTALL_PROGRAM := $(INSTALL) -p -m 644 INSTALL_DATA := $(INSTALL) -p -m 644 INSTALL_DIR := $(INSTALL) -m 755 -d # strip spaces from file names executables := $(strip $(executables)) datafiles := $(strip $(datafiles)) datadirs := $(strip $(datadirs)) # Do not make any install sub-target with empty variable definition because the # install program would exit with an error. install: $(if $(executables), install-executables) install: $(if $(datafiles), install-datafiles) install: $(if $(datadirs), install-datadirs) install-executables: all $(INSTALL_DIR) -v "$(installpath)" $(foreach v, $(executables), \ $(INSTALL_PROGRAM) '$v' "$(installpath)";) $(info ++++ info: executables of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) $(if $(stripflags), $(strip-executables),) install-datafiles: all $(INSTALL_DIR) -v "$(installpath)" $(foreach v, $(datafiles), \ $(INSTALL_DATA) '$(v)' "$(installpath)";) $(info ++++ info: data files of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) install-datadirs: all $(foreach v, $(datadirs), $(INSTALL_DIR) "$(installpath)/$v";) $(foreach v, $(datadirs), \ $(INSTALL_DATA) $(wildcard $v/*) "$(installpath)/$v";) $(info ++++ info: data directories of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) ################################################################################ ### rules: distribution targets ################################################ ################################################################################ # TODO # These targets are implemented in Makefile Template, but I have to figure out # how to do it under the not-so-strict conditions of Makefile.pdlibbuilder. # make source package dist: @echo "target dist not yet implemented" # make Debian source package dpkg-source: @echo "target dpkg-source not yet implemented" $(ORIGDIR): $(DISTDIR): ################################################################################ ### rules: clean targets ####################################################### ################################################################################ # delete build products from build tree clean: rm -f $(all.objects) rm -f $(classes.executables) $(lib.name).$(extension) $(shared.lib) rm -f *.pre *.lst # remove distribution directories and tarballs from build tree distclean: clean @echo "target distclean not yet implemented" ################################################################################ ### rules: submake targets ##################################################### ################################################################################ # Iterate over sub-makefiles or makefiles in other directories. # When 'continue-make=yes' is set, sub-makes will report 'true' to the parent # process regardless of their real exit status. This prevents the parent make # from being aborted by a sub-make error. Useful when you want to quickly find # out which sub-makes from a large set will succeed. ifeq ($(continue-make),yes) continue = || true endif # These targets will trigger sub-make processes for entries in 'makefiledirs' # and 'makefiles'. all alldebug install clean distclean dist dkpg-source: \ $(makefiledirs) $(makefiles) # this expands to identical rules for each entry in 'makefiledirs' $(makefiledirs): $(MAKE) --directory=$@ $(MAKECMDGOALS) $(continue) # this expands to identical rules for each entry in 'makefiles' $(makefiles): $(MAKE) --directory=$(dir $@) --makefile=$(notdir $@) $(MAKECMDGOALS) $(continue) ################################################################################ ### rules: convenience targets ################################################# ################################################################################ #=== show variables ============================================================ # Several 'function' macro's cause errors when expanded within a rule or without # proper arguments. Variables which are set with the define directive are only # shown by name for that reason. functions = \ add-class-source \ declare-class-target \ declare-class-executable-target \ declare-object-target \ link-class \ link-lib \ link-shared \ make-object-file \ make-preprocessor-file \ make-assembly-file # show variables from makefiles vars: $(info ++++ info: showing makefile variables:) $(foreach v,\ $(sort $(filter-out $(functions) functions, $(.VARIABLES))),\ $(if $(filter file, $(origin $v)),\ $(info variable $v = $($v)))) $(foreach v, $(functions), $(info 'function' name: $v)) @echo # show all variables allvars: $(info ++++ info: showing default, automatic and makefile variables:) $(foreach v, \ $(sort $(filter-out $(functions) functions, $(.VARIABLES))), \ $(info variable ($(origin $v)) $v = $($v))) $(foreach v, $(functions), $(info 'function' name: $v)) @echo #=== show dependencies ========================================================= # show generated prerequisites rules depend: $(info ++++ info: generated prerequisite rules) $(foreach v, $(classes), $(info $(declare-class-target))) $(foreach v, $(classes), $(info $(declare-class-executable-target))) $(foreach v, $(all.sources), $(info $(call declare-object-target, $v))) @echo #=== show help text ============================================================ # brief info about targets and paths ifdef mpdh mpdhinfo := $(mpdh) else mpdhinfo := m_pd.h was not found. Is Pd installed? endif help: @echo @echo " Main targets:" @echo " all: build executables (default target)" @echo " install: install all components of the library" @echo " vars: print makefile variables for troubleshooting" @echo " allvars: print all variables for troubleshooting" @echo " help: print this help text" @echo @echo " Pd API m_pd.h:" @echo " $(mpdhinfo)" @echo " You may specify your preferred Pd include directory as argument" @echo " to the make command, like 'PDINCLUDEDIR=path/to/pd/src'." @echo @echo " Path for installation of your libdir(s):" @echo " $(PDLIBDIR)" @echo " Alternatively you may specify your path for installation as argument" @echo " to the make command, like 'PDLIBDIR=path/to/pd-externals'." @echo @echo " Default paths are listed in the doc sections in Makefile.pdlibbuilder." @echo #=== platform test ============================================================= # This target can be used to test if the compiler for specified PLATFORM is # correctly defined and available. dumpmachine: @$(CC) -dumpmachine #=== dummy target ============================================================== coffee: @echo "Makefile.pdlibbuilder: Can not make coffee. Sorry." ################################################################################ ### end of rules sections ###################################################### ################################################################################ # for syntax highlighting in vim and github # vim: set filetype=make: ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5931823 hvcc-0.13.3/hvcc/generators/c2pdext/static/m_pd.h0000644000000000000000000011301214735300037016473 0ustar00/* Copyright (c) 1997-1999 Miller Puckette. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __m_pd_h_ #if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) extern "C" { #endif #define PD_MAJOR_VERSION 0 #define PD_MINOR_VERSION 54 #define PD_BUGFIX_VERSION 0 #define PD_TEST_VERSION "" extern int pd_compatibilitylevel; /* e.g., 43 for pd 0.43 compatibility */ /* old name for "MSW" flag -- we have to take it for the sake of many old "nmakefiles" for externs, which will define NT and not MSW */ #if defined(NT) && !defined(MSW) #define MSW #endif /* These pragmas are only used for MSVC, not MinGW or Cygwin */ #ifdef _MSC_VER /* #pragma warning( disable : 4091 ) */ #pragma warning( disable : 4305 ) /* uncast const double to float */ #pragma warning( disable : 4244 ) /* uncast float/int conversion etc. */ #pragma warning( disable : 4101 ) /* unused automatic variables */ #endif /* _MSC_VER */ /* the external storage class is "extern" in UNIX; in MSW it's ugly. */ #ifndef EXTERN #ifdef _WIN32 #ifdef PD_INTERNAL #define EXTERN __declspec(dllexport) extern #else #define EXTERN __declspec(dllimport) extern #endif /* PD_INTERNAL */ #else #define EXTERN extern #endif /* _WIN32 */ #endif /* EXTERN */ /* On most c compilers, you can just say "struct foo;" to declare a structure whose elements are defined elsewhere. On very old MSVC versions, when compiling C (but not C++) code, you have to say "extern struct foo;". So we make a stupid macro: */ #if defined(_MSC_VER) && !defined(_LANGUAGE_C_PLUS_PLUS) \ && !defined(__cplusplus) && (_MSC_VER < 1700) #define EXTERN_STRUCT extern struct #else #define EXTERN_STRUCT struct #endif /* Define some attributes, specific to the compiler */ #if defined(__GNUC__) #define ATTRIBUTE_FORMAT_PRINTF(a, b) __attribute__ ((format (printf, a, b))) #else #define ATTRIBUTE_FORMAT_PRINTF(a, b) #endif #if !defined(_SIZE_T) && !defined(_SIZE_T_) #include /* just for size_t -- how lame! */ #endif /* Microsoft Visual Studio is not C99, but since VS2015 has included most C99 headers: https://docs.microsoft.com/en-us/previous-versions/hh409293(v=vs.140)#c-runtime-library These definitions recreate stdint.h types, but only in pre-2015 Visual Studio: */ #if defined(_MSC_VER) && _MSC_VER < 1900 typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; typedef signed __int64 int64_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; #else # include #endif /* for FILE, needed by sys_fopen() and sys_fclose() only */ #include #define MAXPDSTRING 1000 /* use this for anything you want */ #define MAXPDARG 5 /* max number of args we can typecheck today */ /* signed and unsigned integer types the size of a pointer: */ #if !defined(PD_LONGINTTYPE) #if defined(_WIN32) && defined(_WIN64) #define PD_LONGINTTYPE long long #else #define PD_LONGINTTYPE long #endif #endif #if !defined(PD_FLOATSIZE) /* normally, our floats (t_float, t_sample,...) are 32bit */ # define PD_FLOATSIZE 32 #endif #if PD_FLOATSIZE == 32 # define PD_FLOATTYPE float /* an unsigned int of the same size as FLOATTYPE: */ # define PD_FLOATUINTTYPE uint32_t #elif PD_FLOATSIZE == 64 # define PD_FLOATTYPE double # define PD_FLOATUINTTYPE uint64_t #else # error invalid FLOATSIZE: must be 32 or 64 #endif typedef PD_LONGINTTYPE t_int; /* pointer-size integer */ typedef PD_FLOATTYPE t_float; /* a float type at most the same size */ typedef PD_FLOATTYPE t_floatarg; /* float type for function calls */ typedef struct _symbol { const char *s_name; struct _class **s_thing; struct _symbol *s_next; } t_symbol; EXTERN_STRUCT _array; #define t_array struct _array /* g_canvas.h */ /* pointers to glist and array elements go through a "stub" which sticks around after the glist or array is freed. The stub itself is deleted when both the glist/array is gone and the refcount is zero, ensuring that no gpointers are pointing here. */ #define GP_NONE 0 /* the stub points nowhere (has been cut off) */ #define GP_GLIST 1 /* the stub points to a glist element */ #define GP_ARRAY 2 /* ... or array */ typedef struct _gstub { union { struct _glist *gs_glist; /* glist we're in */ struct _array *gs_array; /* array we're in */ } gs_un; int gs_which; /* GP_GLIST/GP_ARRAY */ int gs_refcount; /* number of gpointers pointing here */ } t_gstub; typedef struct _gpointer /* pointer to a gobj in a glist */ { union { struct _scalar *gp_scalar; /* scalar we're in (if glist) */ union word *gp_w; /* raw data (if array) */ } gp_un; int gp_valid; /* number which must match gpointee */ t_gstub *gp_stub; /* stub which points to glist/array */ } t_gpointer; typedef union word { t_float w_float; t_symbol *w_symbol; t_gpointer *w_gpointer; t_array *w_array; struct _binbuf *w_binbuf; int w_index; } t_word; typedef enum { A_NULL, A_FLOAT, A_SYMBOL, A_POINTER, A_SEMI, A_COMMA, A_DEFFLOAT, A_DEFSYM, A_DOLLAR, A_DOLLSYM, A_GIMME, A_CANT } t_atomtype; #define A_DEFSYMBOL A_DEFSYM /* better name for this */ typedef struct _atom { t_atomtype a_type; union word a_w; } t_atom; EXTERN_STRUCT _class; #define t_class struct _class EXTERN_STRUCT _outlet; #define t_outlet struct _outlet EXTERN_STRUCT _inlet; #define t_inlet struct _inlet EXTERN_STRUCT _binbuf; #define t_binbuf struct _binbuf EXTERN_STRUCT _clock; #define t_clock struct _clock EXTERN_STRUCT _outconnect; #define t_outconnect struct _outconnect EXTERN_STRUCT _glist; #define t_glist struct _glist #define t_canvas struct _glist /* LATER lose this */ EXTERN_STRUCT _template; typedef t_class *t_pd; /* pure datum: nothing but a class pointer */ typedef struct _gobj /* a graphical object */ { t_pd g_pd; /* pure datum header (class) */ struct _gobj *g_next; /* next in list */ } t_gobj; typedef struct _scalar /* a graphical object holding data */ { t_gobj sc_gobj; /* header for graphical object */ t_symbol *sc_template; /* template name (LATER replace with pointer) */ t_word sc_vec[1]; /* indeterminate-length array of words */ } t_scalar; typedef struct _text /* patchable object - graphical, with text */ { t_gobj te_g; /* header for graphical object */ t_binbuf *te_binbuf; /* holder for the text */ t_outlet *te_outlet; /* linked list of outlets */ t_inlet *te_inlet; /* linked list of inlets */ short te_xpix; /* x&y location (within the toplevel) */ short te_ypix; short te_width; /* requested width in chars, 0 if auto */ unsigned int te_type:2; /* from defs below */ } t_text; #define T_TEXT 0 /* just a textual comment */ #define T_OBJECT 1 /* a MAX style patchable object */ #define T_MESSAGE 2 /* a MAX type message */ #define T_ATOM 3 /* a cell to display a number or symbol */ #define te_pd te_g.g_pd /* t_object is synonym for t_text (LATER unify them) */ typedef struct _text t_object; #define ob_outlet te_outlet #define ob_inlet te_inlet #define ob_binbuf te_binbuf #define ob_pd te_g.g_pd #define ob_g te_g typedef void (*t_method)(void); typedef void *(*t_newmethod)(void); /* in ARM 64 a varargs prototype generates a different function call sequence from a fixed one, so in that special case we make a more restrictive definition for t_gotfn. This will break some code in the "chaos" package in Pd extended. (that code will run incorrectly anyhow so why not catch it at compile time anyhow.) */ #if defined(__APPLE__) && defined(__aarch64__) typedef void (*t_gotfn)(void *x); #else typedef void (*t_gotfn)(void *x, ...); #endif /* ---------------- pre-defined objects and symbols --------------*/ EXTERN t_pd pd_objectmaker; /* factory for creating "object" boxes */ EXTERN t_pd pd_canvasmaker; /* factory for creating canvases */ /* --------- prototypes from the central message system ----------- */ EXTERN void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv); EXTERN void pd_forwardmess(t_pd *x, int argc, t_atom *argv); EXTERN t_symbol *gensym(const char *s); EXTERN t_gotfn getfn(const t_pd *x, t_symbol *s); EXTERN t_gotfn zgetfn(const t_pd *x, t_symbol *s); EXTERN void nullfn(void); EXTERN void pd_vmess(t_pd *x, t_symbol *s, const char *fmt, ...); /* the following macros are for sending non-type-checkable messages, i.e., using function lookup but circumventing type checking on arguments. Only use for internal messaging protected by A_CANT so that the message can't be generated at patch level. */ #define mess0(x, s) ((*getfn((x), (s)))((x))) typedef void (*t_gotfn1)(void *x, void *arg1); #define mess1(x, s, a) ((*(t_gotfn1)getfn((x), (s)))((x), (a))) typedef void (*t_gotfn2)(void *x, void *arg1, void *arg2); #define mess2(x, s, a,b) ((*(t_gotfn2)getfn((x), (s)))((x), (a),(b))) typedef void (*t_gotfn3)(void *x, void *arg1, void *arg2, void *arg3); #define mess3(x, s, a,b,c) ((*(t_gotfn3)getfn((x), (s)))((x), (a),(b),(c))) typedef void (*t_gotfn4)(void *x, void *arg1, void *arg2, void *arg3, void *arg4); #define mess4(x, s, a,b,c,d) \ ((*(t_gotfn4)getfn((x), (s)))((x), (a),(b),(c),(d))) typedef void (*t_gotfn5)(void *x, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5); #define mess5(x, s, a,b,c,d,e) \ ((*(t_gotfn5)getfn((x), (s)))((x), (a),(b),(c),(d),(e))) EXTERN void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv); EXTERN t_pd *pd_newest(void); /* --------------- memory management -------------------- */ EXTERN void *getbytes(size_t nbytes); EXTERN void *getzbytes(size_t nbytes); EXTERN void *copybytes(const void *src, size_t nbytes); EXTERN void freebytes(void *x, size_t nbytes); EXTERN void *resizebytes(void *x, size_t oldsize, size_t newsize); /* -------------------- atoms ----------------------------- */ #define SETSEMI(atom) ((atom)->a_type = A_SEMI, (atom)->a_w.w_index = 0) #define SETCOMMA(atom) ((atom)->a_type = A_COMMA, (atom)->a_w.w_index = 0) #define SETPOINTER(atom, gp) ((atom)->a_type = A_POINTER, \ (atom)->a_w.w_gpointer = (gp)) #define SETFLOAT(atom, f) ((atom)->a_type = A_FLOAT, (atom)->a_w.w_float = (f)) #define SETSYMBOL(atom, s) ((atom)->a_type = A_SYMBOL, \ (atom)->a_w.w_symbol = (s)) #define SETDOLLAR(atom, n) ((atom)->a_type = A_DOLLAR, \ (atom)->a_w.w_index = (n)) #define SETDOLLSYM(atom, s) ((atom)->a_type = A_DOLLSYM, \ (atom)->a_w.w_symbol= (s)) EXTERN t_float atom_getfloat(const t_atom *a); EXTERN t_int atom_getint(const t_atom *a); EXTERN t_symbol *atom_getsymbol(const t_atom *a); EXTERN t_symbol *atom_gensym(const t_atom *a); EXTERN t_float atom_getfloatarg(int which, int argc, const t_atom *argv); EXTERN t_int atom_getintarg(int which, int argc, const t_atom *argv); EXTERN t_symbol *atom_getsymbolarg(int which, int argc, const t_atom *argv); EXTERN void atom_string(const t_atom *a, char *buf, unsigned int bufsize); /* ------------------ binbufs --------------- */ EXTERN t_binbuf *binbuf_new(void); EXTERN void binbuf_free(t_binbuf *x); EXTERN t_binbuf *binbuf_duplicate(const t_binbuf *y); EXTERN void binbuf_text(t_binbuf *x, const char *text, size_t size); EXTERN void binbuf_gettext(const t_binbuf *x, char **bufp, int *lengthp); EXTERN void binbuf_clear(t_binbuf *x); EXTERN void binbuf_add(t_binbuf *x, int argc, const t_atom *argv); EXTERN void binbuf_addv(t_binbuf *x, const char *fmt, ...); EXTERN void binbuf_addbinbuf(t_binbuf *x, const t_binbuf *y); EXTERN void binbuf_addsemi(t_binbuf *x); EXTERN void binbuf_restore(t_binbuf *x, int argc, const t_atom *argv); EXTERN void binbuf_print(const t_binbuf *x); EXTERN int binbuf_getnatom(const t_binbuf *x); EXTERN t_atom *binbuf_getvec(const t_binbuf *x); EXTERN int binbuf_resize(t_binbuf *x, int newsize); EXTERN void binbuf_eval(const t_binbuf *x, t_pd *target, int argc, const t_atom *argv); EXTERN int binbuf_read(t_binbuf *b, const char *filename, const char *dirname, int crflag); EXTERN int binbuf_read_via_canvas(t_binbuf *b, const char *filename, const t_canvas *canvas, int crflag); EXTERN int binbuf_read_via_path(t_binbuf *b, const char *filename, const char *dirname, int crflag); EXTERN int binbuf_write(const t_binbuf *x, const char *filename, const char *dir, int crflag); EXTERN void binbuf_evalfile(t_symbol *name, t_symbol *dir); EXTERN t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, const t_atom *av, int tonew); /* ------------------ clocks --------------- */ EXTERN t_clock *clock_new(void *owner, t_method fn); EXTERN void clock_set(t_clock *x, double systime); EXTERN void clock_delay(t_clock *x, double delaytime); EXTERN void clock_unset(t_clock *x); EXTERN void clock_setunit(t_clock *x, double timeunit, int sampflag); EXTERN double clock_getlogicaltime(void); EXTERN double clock_getsystime(void); /* OBSOLETE; use clock_getlogicaltime() */ EXTERN double clock_gettimesince(double prevsystime); EXTERN double clock_gettimesincewithunits(double prevsystime, double units, int sampflag); EXTERN double clock_getsystimeafter(double delaytime); EXTERN void clock_free(t_clock *x); /* ----------------- pure data ---------------- */ EXTERN t_pd *pd_new(t_class *cls); EXTERN void pd_free(t_pd *x); EXTERN void pd_bind(t_pd *x, t_symbol *s); EXTERN void pd_unbind(t_pd *x, t_symbol *s); EXTERN t_pd *pd_findbyclass(t_symbol *s, const t_class *c); EXTERN void pd_pushsym(t_pd *x); EXTERN void pd_popsym(t_pd *x); EXTERN void pd_bang(t_pd *x); EXTERN void pd_pointer(t_pd *x, t_gpointer *gp); EXTERN void pd_float(t_pd *x, t_float f); EXTERN void pd_symbol(t_pd *x, t_symbol *s); EXTERN void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv); EXTERN void pd_anything(t_pd *x, t_symbol *s, int argc, t_atom *argv); #define pd_class(x) (*(x)) /* ----------------- pointers ---------------- */ EXTERN void gpointer_init(t_gpointer *gp); EXTERN void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto); EXTERN void gpointer_unset(t_gpointer *gp); EXTERN int gpointer_check(const t_gpointer *gp, int headok); /* ----------------- patchable "objects" -------------- */ EXTERN t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1, t_symbol *s2); EXTERN t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp); EXTERN t_inlet *floatinlet_new(t_object *owner, t_float *fp); EXTERN t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp); EXTERN t_inlet *signalinlet_new(t_object *owner, t_float f); EXTERN void inlet_free(t_inlet *x); EXTERN t_outlet *outlet_new(t_object *owner, t_symbol *s); EXTERN void outlet_bang(t_outlet *x); EXTERN void outlet_pointer(t_outlet *x, t_gpointer *gp); EXTERN void outlet_float(t_outlet *x, t_float f); EXTERN void outlet_symbol(t_outlet *x, t_symbol *s); EXTERN void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv); EXTERN void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv); EXTERN t_symbol *outlet_getsymbol(t_outlet *x); EXTERN void outlet_free(t_outlet *x); EXTERN t_object *pd_checkobject(t_pd *x); /* -------------------- canvases -------------- */ EXTERN void glob_setfilename(void *dummy, t_symbol *name, t_symbol *dir); EXTERN void canvas_setargs(int argc, const t_atom *argv); EXTERN void canvas_getargs(int *argcp, t_atom **argvp); EXTERN t_symbol *canvas_getcurrentdir(void); EXTERN t_glist *canvas_getcurrent(void); EXTERN void canvas_makefilename(const t_glist *c, const char *file, char *result, int resultsize); EXTERN t_symbol *canvas_getdir(const t_glist *x); EXTERN char sys_font[]; /* default typeface set in s_main.c */ EXTERN char sys_fontweight[]; /* default font weight set in s_main.c */ EXTERN int sys_hostfontsize(int fontsize, int zoom); EXTERN int sys_zoomfontwidth(int fontsize, int zoom, int worstcase); EXTERN int sys_zoomfontheight(int fontsize, int zoom, int worstcase); EXTERN int sys_fontwidth(int fontsize); EXTERN int sys_fontheight(int fontsize); EXTERN void canvas_dataproperties(t_glist *x, t_scalar *sc, t_binbuf *b); EXTERN int canvas_open(const t_canvas *x, const char *name, const char *ext, char *dirresult, char **nameresult, unsigned int size, int bin); EXTERN t_float canvas_getsr(t_canvas *x); EXTERN int canvas_getsignallength(t_canvas *x); /* ---------------- widget behaviors ---------------------- */ EXTERN_STRUCT _widgetbehavior; #define t_widgetbehavior struct _widgetbehavior EXTERN_STRUCT _parentwidgetbehavior; #define t_parentwidgetbehavior struct _parentwidgetbehavior EXTERN const t_parentwidgetbehavior *pd_getparentwidget(t_pd *x); /* -------------------- classes -------------- */ #define CLASS_DEFAULT 0 /* flags for new classes below */ #define CLASS_PD 1 /* non-canvasable (bare) pd such as an inlet */ #define CLASS_GOBJ 2 /* pd that can belong to a canvas */ #define CLASS_PATCHABLE 3 /* pd that also can have inlets and outlets */ #define CLASS_TYPEMASK 3 #define CLASS_NOINLET 8 /* suppress left inlet */ #define CLASS_MULTICHANNEL 0x10 /* can deal with multichannel sigs */ #define CLASS_NOPROMOTESIG 0x20 /* don't promote scalars to signals */ #define CLASS_NOPROMOTELEFT 0x40 /* not even the main (left) inlet */ /* Setting a tilde object's CLASS_MULTICHANNEL flag declares that it can deal with multichannel inputs. In this case the channel counts of the inputs might not match; it's up to the dsp method to figure out what to do. Also, the output signal vectors aren't allocated. The output channel counts have to be specified by the object at DSP time. If the object can't put itself on the DSP chain it then has to create outputs anyway and arrange to zero them. By default, if a tilde object's inputs are unconnected, Pd fills them in by adding scalar-to-vector conversions to the DSP chain as needed before calling the dsp method. This behavior can be suppressed for the left (main) inlet by setting CLASS_NOPROMOTELEFT and for one or more non-main inlets by setting CLASS_NOPROMOTESIG. Seeing this, the object can then opt to supply a faster routine; for example, "+" can do a vector-scalar add. In any case, signal outputs are all vectors, and are allocated automatically unless the CLASS_MULTICHANNEL flag is also set. */ EXTERN t_class *class_new(t_symbol *name, t_newmethod newmethod, t_method freemethod, size_t size, int flags, t_atomtype arg1, ...); EXTERN t_class *class_new64(t_symbol *name, t_newmethod newmethod, t_method freemethod, size_t size, int flags, t_atomtype arg1, ...); EXTERN void class_free(t_class *c); #ifdef PDINSTANCE EXTERN t_class *class_getfirst(void); #endif EXTERN void class_addcreator(t_newmethod newmethod, t_symbol *s, t_atomtype type1, ...); EXTERN void class_addmethod(t_class *c, t_method fn, t_symbol *sel, t_atomtype arg1, ...); EXTERN void class_addbang(t_class *c, t_method fn); EXTERN void class_addpointer(t_class *c, t_method fn); EXTERN void class_doaddfloat(t_class *c, t_method fn); EXTERN void class_addsymbol(t_class *c, t_method fn); EXTERN void class_addlist(t_class *c, t_method fn); EXTERN void class_addanything(t_class *c, t_method fn); EXTERN void class_sethelpsymbol(t_class *c, t_symbol *s); EXTERN void class_setwidget(t_class *c, const t_widgetbehavior *w); EXTERN void class_setparentwidget(t_class *c, const t_parentwidgetbehavior *w); EXTERN const char *class_getname(const t_class *c); EXTERN const char *class_gethelpname(const t_class *c); EXTERN const char *class_gethelpdir(const t_class *c); EXTERN void class_setdrawcommand(t_class *c); EXTERN int class_isdrawcommand(const t_class *c); EXTERN void class_set_extern_dir(t_symbol *s); EXTERN void class_domainsignalin(t_class *c, int onset); #define CLASS_MAINSIGNALIN(c, type, field) \ class_domainsignalin(c, (char *)(&((type *)0)->field) - (char *)0) /* prototype for functions to save Pd's to a binbuf */ typedef void (*t_savefn)(t_gobj *x, t_binbuf *b); EXTERN void class_setsavefn(t_class *c, t_savefn f); EXTERN t_savefn class_getsavefn(const t_class *c); EXTERN void obj_saveformat(const t_object *x, t_binbuf *bb); /* add format to bb */ /* prototype for functions to open properties dialogs */ typedef void (*t_propertiesfn)(t_gobj *x, struct _glist *glist); EXTERN void class_setpropertiesfn(t_class *c, t_propertiesfn f); EXTERN t_propertiesfn class_getpropertiesfn(const t_class *c); typedef void (*t_classfreefn)(t_class *); EXTERN void class_setfreefn(t_class *c, t_classfreefn fn); #ifndef PD_CLASS_DEF #define class_addbang(x, y) class_addbang((x), (t_method)(y)) #define class_addpointer(x, y) class_addpointer((x), (t_method)(y)) #define class_addfloat(x, y) class_doaddfloat((x), (t_method)(y)) #define class_addsymbol(x, y) class_addsymbol((x), (t_method)(y)) #define class_addlist(x, y) class_addlist((x), (t_method)(y)) #define class_addanything(x, y) class_addanything((x), (t_method)(y)) #endif #if PD_FLOATSIZE == 64 # define class_new class_new64 #endif /* ------------ printing --------------------------------- */ EXTERN void post(const char *fmt, ...); EXTERN void startpost(const char *fmt, ...); EXTERN void poststring(const char *s); EXTERN void postfloat(t_floatarg f); EXTERN void postatom(int argc, const t_atom *argv); EXTERN void endpost(void); EXTERN void bug(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); EXTERN void pd_error(const void *object, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3); /* for logpost(); does *not* work with verbose()! */ typedef enum { PD_CRITICAL = 0, PD_ERROR, PD_NORMAL, PD_DEBUG, PD_VERBOSE } t_loglevel; EXTERN void logpost(const void *object, int level, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(3, 4); /* deprecated, use logpost() instead. */ EXTERN void verbose(int level, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3); /* ------------ system interface routines ------------------- */ EXTERN int sys_isabsolutepath(const char *dir); EXTERN void sys_bashfilename(const char *from, char *to); EXTERN void sys_unbashfilename(const char *from, char *to); EXTERN int open_via_path(const char *dir, const char *name, const char *ext, char *dirresult, char **nameresult, unsigned int size, int bin); EXTERN int sched_geteventno(void); EXTERN double sys_getrealtime(void); EXTERN int (*sys_idlehook)(void); /* hook to add idle time computation */ /* Win32's open()/fopen() do not handle UTF-8 filenames so we need * these internal versions that handle UTF-8 filenames the same across * all platforms. They are recommended for use in external * objectclasses as well so they work with Unicode filenames on Windows */ EXTERN int sys_open(const char *path, int oflag, ...); EXTERN int sys_close(int fd); EXTERN FILE *sys_fopen(const char *filename, const char *mode); EXTERN int sys_fclose(FILE *stream); /* ------------ threading ------------------- */ EXTERN void sys_lock(void); EXTERN void sys_unlock(void); EXTERN int sys_trylock(void); /* --------------- signals ----------------------------------- */ typedef PD_FLOATTYPE t_sample; typedef union _sampleint_union { t_sample f; PD_FLOATUINTTYPE i; } t_sampleint_union; #define MAXLOGSIG 32 #define MAXSIGSIZE (1 << MAXLOGSIG) typedef struct _signal { union { int s_length; /* number of items per channel */ int s_n; /* for source compatibility: pre-0.54 name */ }; t_sample *s_vec; /* the samples, s_nchans vectors of s_length */ t_float s_sr; /* samples per second per channel */ int s_nchans; /* number of channels */ int s_overlap; /* number of times each sample appears */ int s_refcount; /* number of times signal is referenced */ int s_isborrowed; /* whether we're going to borrow our array */ int s_isscalar; /* scalar for an unconnected signal input */ struct _signal *s_borrowedfrom; /* signal to borrow it from */ struct _signal *s_nextfree; /* next in freelist */ struct _signal *s_nextused; /* next in used list */ int s_nalloc; /* allocated size of array in points */ } t_signal; typedef t_int *(*t_perfroutine)(t_int *args); EXTERN t_signal *signal_new(int length, int nchans, t_float sr, t_sample *scalarptr); EXTERN void signal_setmultiout(t_signal **sig, int nchans); EXTERN t_int *plus_perform(t_int *args); EXTERN t_int *plus_perf8(t_int *args); EXTERN t_int *zero_perform(t_int *args); EXTERN t_int *zero_perf8(t_int *args); EXTERN t_int *copy_perform(t_int *args); EXTERN t_int *copy_perf8(t_int *args); EXTERN t_int *scalarcopy_perform(t_int *args); EXTERN t_int *scalarcopy_perf8(t_int *args); EXTERN void dsp_add_plus(t_sample *in1, t_sample *in2, t_sample *out, int n); EXTERN void dsp_add_copy(t_sample *in, t_sample *out, int n); EXTERN void dsp_add_scalarcopy(t_float *in, t_sample *out, int n); EXTERN void dsp_add_zero(t_sample *out, int n); EXTERN int sys_getblksize(void); EXTERN t_float sys_getsr(void); EXTERN int sys_get_inchannels(void); EXTERN int sys_get_outchannels(void); EXTERN void dsp_add(t_perfroutine f, int n, ...); EXTERN void dsp_addv(t_perfroutine f, int n, t_int *vec); EXTERN void pd_fft(t_float *buf, int npoints, int inverse); EXTERN int ilog2(int n); EXTERN void mayer_fht(t_sample *fz, int n); EXTERN void mayer_fft(int n, t_sample *real, t_sample *imag); EXTERN void mayer_ifft(int n, t_sample *real, t_sample *imag); EXTERN void mayer_realfft(int n, t_sample *real); EXTERN void mayer_realifft(int n, t_sample *real); EXTERN float *cos_table; #define LOGCOSTABSIZE 9 #define COSTABSIZE (1<: receiver on the GUI side (e.g. a Tcl/Tk 'proc') * : string of format specifiers * <...>: values according to the format specifiers * * the can be a NULL pointer (in which case it is ignored) * the user of NULL as a is discouraged * depending on the format specifiers, one or more values are passed * 'f' : : a floating point number * 'i' : : an integer number * 's' : : a string * 'r' : : a raw string * 'x' : : a generic pointer * 'o' : : an graphical object * '^' : : a toplevel window (legacy) * 'c' : : a canvas (on a window) * 'F' : : array of t_float's * 'S' : : array of strings * 'R' : : array of raw strings * 'a' : : list of atoms * 'A' : : array of atoms * 'w' : : list of floatwords * 'W' : : array of floatwords * 'm' : : a Pd message * 'p' : : a pascal string (explicit size; not \0-terminated) * 'k' : : a color (or kolor, if you prefer) * ' ' : none : ignored * the use of the specifiers 'x^' is discouraged * raw-strings ('rR') should only be used for constant, well-known strings */ EXTERN void pdgui_vmess(const char* destination, const char* fmt, ...); /* improved dialog window creation * this will insert a first argument to based on * which the GUI can then use to callback. * gfxstub_new() ensures that the given receiver will be available, * even if the has been removed in the meantime. * see pdgui_vmess() for a description of and the varargs */ EXTERN void pdgui_stub_vnew(t_pd *owner, const char* destination, void *key, const char* fmt, ...); EXTERN void pdgui_stub_deleteforkey(void *key); extern t_class *glob_pdobject; /* object to send "pd" messages */ /*------------- Max 0.26 compatibility --------------------*/ /* the following reflects the new way classes are laid out, with the class pointing to the messlist and not vice versa. Externs shouldn't feel it. */ typedef t_class *t_externclass; EXTERN void c_extern(t_externclass *cls, t_newmethod newroutine, t_method freeroutine, t_symbol *name, size_t size, int tiny, \ t_atomtype arg1, ...); EXTERN void c_addmess(t_method fn, t_symbol *sel, t_atomtype arg1, ...); #define t_getbytes getbytes #define t_freebytes freebytes #define t_resizebytes resizebytes #define typedmess pd_typedmess #define vmess pd_vmess /* A definition to help gui objects straddle 0.34-0.35 changes. If this is defined, there is a "te_xpix" field in objects, not a "te_xpos" as before: */ #define PD_USE_TE_XPIX #ifndef _MSC_VER /* Microoft compiler can't handle "inline" function/macros */ #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) /* a test for NANs and denormals. Should only be necessary on i386. */ #if PD_FLOATSIZE == 32 typedef union { t_float f; unsigned int ui; } t_bigorsmall32; static inline int PD_BADFLOAT(t_float f) /* malformed float */ { t_bigorsmall32 pun; pun.f = f; pun.ui &= 0x7f800000; return((pun.ui == 0) | (pun.ui == 0x7f800000)); } static inline int PD_BIGORSMALL(t_float f) /* exponent outside (-64,64) */ { t_bigorsmall32 pun; pun.f = f; return((pun.ui & 0x20000000) == ((pun.ui >> 1) & 0x20000000)); } #elif PD_FLOATSIZE == 64 typedef union { t_float f; unsigned int ui[2]; } t_bigorsmall64; static inline int PD_BADFLOAT(t_float f) /* malformed double */ { t_bigorsmall64 pun; pun.f = f; pun.ui[1] &= 0x7ff00000; return((pun.ui[1] == 0) | (pun.ui[1] == 0x7ff00000)); } static inline int PD_BIGORSMALL(t_float f) /* exponent outside (-512,512) */ { t_bigorsmall64 pun; pun.f = f; return((pun.ui[1] & 0x20000000) == ((pun.ui[1] >> 1) & 0x20000000)); } #endif /* PD_FLOATSIZE */ #else /* not INTEL or ARM */ #define PD_BADFLOAT(f) 0 #define PD_BIGORSMALL(f) 0 #endif #else /* _MSC_VER */ #if PD_FLOATSIZE == 32 #define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \ (((*(unsigned int*)&(f))&0x7f800000)==0x7f800000)) /* more stringent test: anything not between 1e-19 and 1e19 in absolute val */ #define PD_BIGORSMALL(f) ((((*(unsigned int*)&(f))&0x60000000)==0) || \ (((*(unsigned int*)&(f))&0x60000000)==0x60000000)) #else /* 64 bits... don't know what to do here */ #define PD_BADFLOAT(f) (!(((f) >= 0) || ((f) <= 0))) #define PD_BIGORSMALL(f) ((f) > 1e150 || (f) < -1e150 \ || (f) > -1e-150 && (f) < 1e-150 ) #endif #endif /* _MSC_VER */ /* get version number at run time */ EXTERN void sys_getversion(int *major, int *minor, int *bugfix); /* get floatsize at run time */ EXTERN unsigned int sys_getfloatsize(void); EXTERN_STRUCT _instancemidi; #define t_instancemidi struct _instancemidi EXTERN_STRUCT _instanceinter; #define t_instanceinter struct _instanceinter EXTERN_STRUCT _instancecanvas; #define t_instancecanvas struct _instancecanvas EXTERN_STRUCT _instanceugen; #define t_instanceugen struct _instanceugen EXTERN_STRUCT _instancestuff; #define t_instancestuff struct _instancestuff #ifndef PDTHREADS #define PDTHREADS 1 #endif struct _pdinstance { double pd_systime; /* global time in Pd ticks */ t_clock *pd_clock_setlist; /* list of set clocks */ t_canvas *pd_canvaslist; /* list of all root canvases */ struct _template *pd_templatelist; /* list of all templates */ int pd_instanceno; /* ordinal number of this instance */ t_symbol **pd_symhash; /* symbol table hash table */ t_instancemidi *pd_midi; /* private stuff for x_midi.c */ t_instanceinter *pd_inter; /* private stuff for s_inter.c */ t_instanceugen *pd_ugen; /* private stuff for d_ugen.c */ t_instancecanvas *pd_gui; /* semi-private stuff in g_canvas.h */ t_instancestuff *pd_stuff; /* semi-private stuff in s_stuff.h */ t_pd *pd_newest; /* most recently created object */ #ifdef PDINSTANCE t_symbol pd_s_pointer; t_symbol pd_s_float; t_symbol pd_s_symbol; t_symbol pd_s_bang; t_symbol pd_s_list; t_symbol pd_s_anything; t_symbol pd_s_signal; t_symbol pd_s__N; t_symbol pd_s__X; t_symbol pd_s_x; t_symbol pd_s_y; t_symbol pd_s_; #endif #if PDTHREADS int pd_islocked; #endif }; #define t_pdinstance struct _pdinstance EXTERN t_pdinstance pd_maininstance; /* m_pd.c */ #ifdef PDINSTANCE EXTERN t_pdinstance *pdinstance_new(void); EXTERN void pd_setinstance(t_pdinstance *x); EXTERN void pdinstance_free(t_pdinstance *x); #endif /* PDINSTANCE */ #if defined(PDTHREADS) && defined(PDINSTANCE) #ifdef _MSC_VER #define PERTHREAD __declspec(thread) #else #define PERTHREAD __thread #endif /* _MSC_VER */ #else #define PERTHREAD #endif #ifdef PDINSTANCE extern PERTHREAD t_pdinstance *pd_this; EXTERN t_pdinstance **pd_instances; EXTERN int pd_ninstances; #else #define pd_this (&pd_maininstance) #endif /* PDINSTANCE */ #ifdef PDINSTANCE #define s_pointer (pd_this->pd_s_pointer) #define s_float (pd_this->pd_s_float) #define s_symbol (pd_this->pd_s_symbol) #define s_bang (pd_this->pd_s_bang) #define s_list (pd_this->pd_s_list) #define s_anything (pd_this->pd_s_anything) #define s_signal (pd_this->pd_s_signal) #define s__N (pd_this->pd_s__N) #define s__X (pd_this->pd_s__X) #define s_x (pd_this->pd_s_x) #define s_y (pd_this->pd_s_y) #define s_ (pd_this->pd_s_) #else EXTERN t_symbol s_pointer, s_float, s_symbol, s_bang, s_list, s_anything, s_signal, s__N, s__X, s_x, s_y, s_; #endif EXTERN t_canvas *pd_getcanvaslist(void); EXTERN int pd_getdspstate(void); /* x_text.c */ EXTERN t_binbuf *text_getbufbyname(t_symbol *s); /* get binbuf from text obj */ EXTERN void text_notifybyname(t_symbol *s); /* notify it was modified */ /* g_undo.c */ /* store two message-sets to be sent to the object's method for 'undo'ing * resp. 'redo'ing the current state of an object. * this creates an internal copy of the atom-lists (so the caller is responsible * for freeing any dynamically allocated data) * this is a no-op if called during 'undo' (resp. 'redo'). */ EXTERN void pd_undo_set_objectstate(t_canvas*canvas, t_pd*x, t_symbol*s, int undo_argc, t_atom*undo_argv, int redo_argc, t_atom*redo_argv); #if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) } #endif #define __m_pd_h_ #endif /* __m_pd_h_ */ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739952989.4286463 hvcc-0.13.3/hvcc/generators/c2pdext/templates/Makefile0000644000000000000000000000114714755311535017566 0ustar00# Makefile to build class '{name}' for Pure Data. # Needs Makefile.pdlibbuilder as helper makefile for platform-dependent build # settings and rules. # library name lib.name = {{name}} ldlibs += -lstdc++ # input source file (class name == source file basename) class.sources = pdext/{{name}}~.c common.sources = $(filter-out pdext/{{name}}~.c, $(wildcard pdext/*.c)) common.sources += $(wildcard pdext/*.cpp) # all extra files to be included in binary distribution of the library #datafiles = helloworld-help.pd helloworld-meta.pd README.md PDLIBBUILDER_DIR=. include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5931823 hvcc-0.13.3/hvcc/generators/c2pdext/templates/pd_external.c0000644000000000000000000001224314735300037020567 0ustar00{{copyright}} #if _MSC_VER || _WIN32 || _WIN64 #include #define DLL_EXPORT __declspec(dllexport) extern #else #include #define DLL_EXPORT #endif #include #include "m_pd.h" #include "Heavy_{{name}}.h" static t_class *{{struct_name}}_class; typedef struct _{{struct_name}} { t_object x_obj; {# declare inlets and outlets #} {%- for i in range(1, num_input_channels) %} t_inlet *inlet{{i}}; {%- endfor %} {%- for i in range(num_output_channels) %} t_outlet *outlet{{i}}; {%- endfor %} t_outlet *msgOutlet; HeavyContextInterface *hv; t_float f; // dummy } t_{{struct_name}}; static void printHook(HeavyContextInterface *c, const char *receiverName, const char *msgString, const HvMessage *m) { double timestampMs = 1000.0 * ((double) hv_msg_getTimestamp(m)) / hv_getSampleRate(c); post("[{{display_name}} @ %0.3gms] %s: %s", timestampMs, receiverName, msgString); } static void sendHook(HeavyContextInterface *c, const char *receiverName, unsigned int receiverHash, const HvMessage * m) { if (!strcmp(receiverName, "HV_TO_PD")) { t_outlet *const outlet = ((t_{{struct_name}} *) hv_getUserData(c))->msgOutlet; if (hv_msg_getNumElements(m) == 1) { if (hv_msg_isFloat(m, 0)) { outlet_float(outlet, hv_msg_getFloat(m, 0)); } else if (hv_msg_isBang(m, 0)) { outlet_bang(outlet); } else if (hv_msg_isSymbol(m, 0)) { outlet_symbol(outlet, gensym(hv_msg_getSymbol(m, 0))); } else return; } else { const int argc = (int) hv_msg_getNumElements(m); t_atom *argv = (t_atom *) alloca(argc*sizeof(t_atom)); for (int i = 0; i < argc; i++) { if (hv_msg_isFloat(m, i)) { SETFLOAT(argv+i, hv_msg_getFloat(m, i)); } else if (hv_msg_isSymbol(m, i)) { SETSYMBOL(argv+i, gensym(hv_msg_getSymbol(m, i))); } else return; } outlet_list(outlet, NULL, argc, argv); } } } static void *{{struct_name}}_new(t_symbol *s, int argc, t_atom *argv) { t_{{struct_name}} *x = (t_{{struct_name}} *) pd_new({{struct_name}}_class); {%- for i in range(1, num_input_channels) %} x->inlet{{i}} = signalinlet_new(&x->x_obj, 0.0f); {%- endfor %} {%- for i in range(num_output_channels) %} x->outlet{{i}} = outlet_new(&x->x_obj, &s_signal); {%- endfor %} x->msgOutlet = outlet_new(&x->x_obj, &s_anything); x->hv = hv_{{name}}_new((double) sys_getsr()); hv_setUserData(x->hv, x); hv_setPrintHook(x->hv, printHook); hv_setSendHook(x->hv, sendHook); return (void *) x; } static void {{struct_name}}_free(t_{{struct_name}} *x) { {%- for i in range(num_input_channels-1) %} inlet_free(x->inlet{{i+1}}); {%- endfor %} {%- for i in range(num_output_channels) %} outlet_free(x->outlet{{i}}); {%- endfor %} outlet_free(x->msgOutlet); hv_delete(x->hv); } static t_int *{{struct_name}}_perform(t_int *w) { t_{{struct_name}} *x = (t_{{struct_name}} *) w[1]; {%- if num_input_channels > 0 %} float *inputChannels[{{num_input_channels}}] = { {%- for i in range(num_input_channels) %} (t_sample *) w[{{i+2}}], {%- endfor %} }; {%- else %} float **inputChannels = NULL; {%- endif %} {%- if num_output_channels > 0 %} float *outputChannels[{{num_output_channels}}] = { {%- for i in range(num_output_channels) %} (t_sample *) w[{{num_input_channels+i+2}}], {%- endfor %} }; {%- else %} float **outputChannels = NULL; {%- endif %} int n = (int) (w[{{num_input_channels+num_output_channels+2}}]); hv_process(x->hv, inputChannels, outputChannels, n); return (w+{{num_input_channels+num_output_channels+3}}); } static void {{struct_name}}_dsp(t_{{struct_name}} *x, t_signal **sp) { dsp_add({{struct_name}}_perform, {{num_input_channels+num_output_channels+2}}, x, {%- for i in range(num_input_channels) %} sp[{{i}}]->s_vec, {%- endfor %} {%- for i in range(num_input_channels|max(1), num_input_channels|max(1)+num_output_channels) %} sp[{{i}}]->s_vec, {%- endfor %} sp[0]->s_n); } static void {{struct_name}}_onMessage(t_{{struct_name}} *x, t_symbol *s0, int argc, t_atom* argv) { // convert a Pd message into a Heavy message HvMessage *msg = (HvMessage *) alloca(hv_msg_getByteSize(argc > 0 ? argc : 1)); if (argc > 0) { hv_msg_init(msg, argc, 0); for (int i = 0; i < argc; i++) { switch (argv[i].a_type) { case A_FLOAT: hv_msg_setFloat(msg, i, atom_getfloat(argv+i)); break; case A_SYMBOL: hv_msg_setSymbol(msg, i, atom_getsymbol(argv+i)->s_name); break; default: return; } } } else { hv_msg_init(msg, 1, 0); hv_msg_setBang(msg, 0); } hv_sendMessageToReceiver(x->hv, hv_stringToHash(s0->s_name), 0.0, msg); } DLL_EXPORT void {{struct_name}}_setup() { {{struct_name}}_class = class_new(gensym("{{display_name}}"), (t_newmethod) {{struct_name}}_new, (t_method) {{struct_name}}_free, sizeof(t_{{struct_name}}), CLASS_DEFAULT, A_GIMME, 0); class_addmethod({{struct_name}}_class, (t_method) {{struct_name}}_dsp, gensym("dsp"), 0); class_addanything({{struct_name}}_class, (t_method) {{struct_name}}_onMessage); CLASS_MAINSIGNALIN({{struct_name}}_class, t_{{struct_name}}, f); } {# force new line #} ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7552068 hvcc-0.13.3/hvcc/generators/c2unity/__init__.py0000644000000000000000000000000014435670357016255 0ustar00././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.267823 hvcc-0.13.3/hvcc/generators/c2unity/c2unity.py0000644000000000000000000001117214735300474016120 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2021-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import jinja2 import os import shutil import time from typing import Optional from ..copyright import copyright_manager from ..filters import filter_string_cap, filter_templates, filter_xcode_build, filter_xcode_fileref from hvcc.interpreters.pd2hv.NotificationEnum import NotificationEnum from hvcc.types.compiler import Generator, CompilerResp, CompilerNotif, CompilerMsg, ExternInfo from hvcc.types.meta import Meta class c2unity(Generator): """Generates a Audio Native Plugin wrapper for Unity 5. """ @classmethod def compile( cls, c_src_dir: str, out_dir: str, externs: ExternInfo, patch_name: Optional[str] = None, patch_meta: Meta = Meta(), num_input_channels: int = 0, num_output_channels: int = 0, copyright: Optional[str] = None, verbose: Optional[bool] = False ) -> CompilerResp: tick = time.time() parameter_list = externs.parameters.inParam event_list = externs.events.inEvent table_list = externs.tables out_dir = os.path.join(out_dir, "unity") patch_name = patch_name or "heavy" copyright = copyright_manager.get_copyright_for_c(copyright) # initialise the jinja template environment env = jinja2.Environment() env.filters["xcode_build"] = filter_xcode_build env.filters["xcode_fileref"] = filter_xcode_fileref env.filters["cap"] = filter_string_cap env.loader = jinja2.FileSystemLoader( encoding="utf-8-sig", searchpath=[os.path.join(os.path.dirname(os.path.abspath(__file__)), "templates")]) static_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "static") src_out_dir = os.path.join(out_dir, "source") try: # ensure that the output directory does not exist out_dir = os.path.abspath(out_dir) if os.path.exists(out_dir): shutil.rmtree(out_dir) # copy over static files shutil.copytree(static_dir, out_dir) # copy over generated C source files src_out_dir = os.path.join(out_dir, "source", "heavy") shutil.copytree(c_src_dir, src_out_dir) # generate files from templates for f in env.list_templates(filter_func=filter_templates): file_path = os.path.join(out_dir, f) file_path = file_path.replace("{{name}}", patch_name) if not os.path.exists(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) with open(file_path, "w") as g: g.write(env.get_template(f).render( patch_name=patch_name, files=os.listdir(src_out_dir), num_input_channels=num_input_channels, num_output_channels=num_output_channels, parameters=parameter_list, events=event_list, tables=table_list, pool_sizes_kb=externs.memoryPoolSizesKb, compile_files=os.listdir(src_out_dir), copyright=copyright)) return CompilerResp( stage="c2unity", in_dir=c_src_dir, out_dir=out_dir, compile_time=time.time() - tick ) except Exception as e: return CompilerResp( stage="c2unity", notifs=CompilerNotif( has_error=True, exception=e, warnings=[], errors=[CompilerMsg( enum=NotificationEnum.ERROR_EXCEPTION, message=str(e) )] ), in_dir=c_src_dir, out_dir=out_dir, compile_time=time.time() - tick ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7552068 hvcc-0.13.3/hvcc/generators/c2unity/static/source/unity/AudioPluginInterface.h0000644000000000000000000002637414435670357024343 0ustar00#pragma once #define UNITY_AUDIO_PLUGIN_API_VERSION 0x010000 #ifndef UNITY_PREFIX_CONFIGURE_H #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) # define UNITY_WIN 1 #elif defined(__MACH__) || defined(__APPLE__) # define UNITY_OSX 1 #elif defined(__ANDROID__) # define UNITY_ANDROID 1 #elif defined(__linux__) # define UNITY_LINUX 1 #elif defined(__PS3__) # define UNITY_PS3 1 #elif defined(__SPU__) # define UNITY_SPU 1 #endif #if defined(_AMD64_) || defined(__LP64__) # define UNITY_64 1 # define UNITY_32 0 #else # define UNITY_64 0 # define UNITY_32 1 #endif #ifndef SInt16_defined # define SInt16_defined typedef signed short SInt16; #endif #ifndef UInt16_defined # define UInt16_defined typedef unsigned short UInt16; #endif #ifndef UInt8_defined # define UInt8_defined typedef unsigned char UInt8; #endif #ifndef SInt8_defined # define SInt8_defined typedef signed char SInt8; #endif #if UNITY_64 # if UNITY_LINUX # ifndef SInt32_defined # define SInt32_defined typedef signed int SInt32; # endif # ifndef UInt32_defined # define UInt32_defined typedef unsigned int UInt32; # endif # ifndef UInt64_defined # define UInt64_defined typedef unsigned long UInt64; # endif # ifndef SInt64_defined # define SInt64_defined typedef signed long SInt64; # endif # elif UNITY_OSX # ifndef SInt32_defined # define SInt32_defined typedef signed int SInt32; # endif # ifndef UInt32_defined # define UInt32_defined typedef unsigned int UInt32; # endif # ifndef UInt64_defined # define UInt64_defined typedef unsigned long long UInt64; # endif # ifndef SInt64_defined # define SInt64_defined typedef signed long long SInt64; # endif # elif UNITY_WIN # ifndef SInt32_defined # define SInt32_defined typedef signed long SInt32; # endif # ifndef UInt32_defined # define UInt32_defined typedef unsigned long UInt32; # endif # ifndef UInt64_defined # define UInt64_defined typedef unsigned long long UInt64; # endif # ifndef SInt64_defined # define SInt64_defined typedef signed long long SInt64; # endif # elif UNITY_ANDROID # ifndef SInt32_defined # define SInt32_defined typedef signed int SInt32; # endif # ifndef UInt32_defined # define UInt32_defined typedef unsigned int UInt32; # endif # ifndef UInt64_defined # define UInt64_defined typedef unsigned long long UInt64; # endif # ifndef SInt64_defined # define SInt64_defined typedef signed long long SInt64; # endif #endif #else # ifndef SInt32_defined # define SInt32_defined typedef signed int SInt32; # endif # ifndef UInt32_defined # define UInt32_defined typedef unsigned int UInt32; # endif # ifndef UInt64_defined # define UInt64_defined typedef unsigned long long UInt64; # endif # ifndef SInt64_defined # define SInt64_defined typedef signed long long SInt64; # endif #endif #endif #if UNITY_WIN #define UNITY_AUDIODSP_CALLBACK __stdcall #elif UNITY_OSX #define UNITY_AUDIODSP_CALLBACK #else #define UNITY_AUDIODSP_CALLBACK #endif // Attribute to make function be exported from a plugin #if UNITY_WIN #define UNITY_AUDIODSP_EXPORT_API __declspec(dllexport) #else #define UNITY_AUDIODSP_EXPORT_API #endif #if defined(__CYGWIN32__) #define UNITY_AUDIODSP_CALLBACK __stdcall #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) #define UNITY_AUDIODSP_CALLBACK __stdcall #elif defined(__MACH__) || defined(__ANDROID__) || defined(__linux__) || defined(__QNX__) #define UNITY_AUDIODSP_CALLBACK #else #define UNITY_AUDIODSP_CALLBACK #endif #define UNITY_AUDIODSP_RESULT int #if !UNITY_SPU // asserts require _exit() to be defined #include #endif enum { UNITY_AUDIODSP_OK = 0, UNITY_AUDIODSP_ERR_UNSUPPORTED = 1, }; struct UnityAudioEffectState; typedef UNITY_AUDIODSP_RESULT (UNITY_AUDIODSP_CALLBACK * UnityAudioEffect_CreateCallback)(UnityAudioEffectState* state); typedef UNITY_AUDIODSP_RESULT (UNITY_AUDIODSP_CALLBACK * UnityAudioEffect_ReleaseCallback)(UnityAudioEffectState* state); typedef UNITY_AUDIODSP_RESULT (UNITY_AUDIODSP_CALLBACK * UnityAudioEffect_ResetCallback)(UnityAudioEffectState* state); typedef UNITY_AUDIODSP_RESULT (UNITY_AUDIODSP_CALLBACK * UnityAudioEffect_ProcessCallback)(UnityAudioEffectState* state, float* inbuffer, float* outbuffer, unsigned int length, int inchannels, int outchannels); typedef UNITY_AUDIODSP_RESULT (UNITY_AUDIODSP_CALLBACK * UnityAudioEffect_SetPositionCallback)(UnityAudioEffectState* state, unsigned int pos); typedef UNITY_AUDIODSP_RESULT (UNITY_AUDIODSP_CALLBACK * UnityAudioEffect_SetFloatParameterCallback)(UnityAudioEffectState* state, int index, float value); typedef UNITY_AUDIODSP_RESULT (UNITY_AUDIODSP_CALLBACK * UnityAudioEffect_GetFloatParameterCallback)(UnityAudioEffectState* state, int index, float* value, char *valuestr); typedef UNITY_AUDIODSP_RESULT (UNITY_AUDIODSP_CALLBACK * UnityAudioEffect_GetFloatBufferCallback)(UnityAudioEffectState* state, const char* name, float* buffer, int numsamples); enum UnityAudioEffectDefinitionFlags { UnityAudioEffectDefinitionFlags_IsSideChainTarget = 1 << 0, // Does this effect need a side chain buffer and can it be targeted by a Send? }; enum UnityAudioEffectStateFlags { UnityAudioEffectStateFlags_IsPlaying = 1 << 0, // Set when engine is in play mode. Also true while paused. UnityAudioEffectStateFlags_IsPaused = 1 << 1, // Set when engine is paused mode. UnityAudioEffectStateFlags_IsMuted = 1 << 2, // Set when effect is being muted (only available in the editor) UnityAudioEffectStateFlags_IsSideChainTarget = 1 << 3, // Does this effect need a side chain buffer and can it be targeted by a Send? }; struct UnityAudioEffectState { union { struct { UInt32 structsize; // Size of this struct UInt32 samplerate; // System sample rate UInt64 currdsptick; // Pointer to a sample counter marking the start of the current block being processed UInt64 prevdsptick; // Used for determining when DSPs are bypassed and so sidechain info becomes invalid float* sidechainbuffer; // Side-chain buffers to read from void* effectdata; // Internal data for the effect UInt32 flags; // Various flags through which information can be queried from the host void* internal; // Internal data, do not touch! }; unsigned char pad[64]; // This entire structure must be a multiple of 16 bytes (and and instance 16 byte aligned) for PS3 SPU DMA requirements }; #ifdef __cplusplus template inline T* GetEffectData() const { #if !UNITY_SPU // asserts require _exit() to be defined assert(effectdata); assert(internal); #endif return (T*)effectdata; } #endif }; struct UnityAudioParameterDefinition { char name[16]; // Display name on the GUI char unit[16]; // Scientific unit of parameter to be appended after the value in textboxes const char* description; // Description of parameter (displayed in tool tips, automatically generated documentation, etc.) float min; // Minimum value of the parameter float max; // Maximum value of the parameter float defaultval; // Default and initial value of the parameter float displayscale; // Scale factor used only for the display of parameters (i.e. 100 for a percentage value ranging from 0 to 1) float displayexponent; // Exponent for mapping parameters to sliders }; struct UnityAudioEffectDefinition { UInt32 structsize; // Size of this struct UInt32 paramstructsize; // Size of paramdesc fields UInt32 apiversion; // Plugin API version UInt32 pluginversion; // Version of this plugin UInt32 channels; // Number of channels. Effects should set this to 0 and process any number of input/output channels they get in the process callback. Generator elements should specify a >0 value here. UInt32 numparameters; // The number of parameters exposed by this plugin. UInt64 flags; // Various capabilities and requirements of the plugin. char name[32]; // Name used for registration of the effect. This name will also be displayed in the GUI. UnityAudioEffect_CreateCallback create; // The create callback is called when DSP unit is created and can be null. UnityAudioEffect_ReleaseCallback release; // The release callback is called just before the plugin is freed and should free any data associated with this specific instance of the plugin. No further callbacks related to the instance will happen after this function has been called. UnityAudioEffect_ResetCallback reset; // The reset callback is called by the user to bring back the plugin instance into its initial state. Use to avoid clicks or artifacts. UnityAudioEffect_ProcessCallback process; // The processing callback is repeatedly called with a block of input audio to read from and an output block to write to. UnityAudioEffect_SetPositionCallback setposition; // The position callback can be used for implementing seek operations. UnityAudioParameterDefinition* paramdefs; // A pointer to the definitions of the parameters exposed by this plugin. This data pointed to must remain valid for the whole lifetime of the dynamic library (ideally it's static). UnityAudioEffect_SetFloatParameterCallback setfloatparameter; // This is called whenever one of the exposed parameters is changed. UnityAudioEffect_GetFloatParameterCallback getfloatparameter; // This is called to query parameter values. UnityAudioEffect_GetFloatBufferCallback getfloatbuffer; // Get N samples of named buffer. Used for displaying analysis data from the runtime. }; // This function fills in N pointers for the N effects contained in the library and returns N. extern "C" UNITY_AUDIODSP_EXPORT_API int UnityGetAudioEffectDefinitions(UnityAudioEffectDefinition*** descptr); ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7552068 hvcc-0.13.3/hvcc/generators/c2unity/static/source/unity/AudioPluginUtil.cpp0000644000000000000000000001264214435670357023704 0ustar00#include "AudioPluginUtil.h" char* strnew(const char* src) { char* newstr = new char[strlen(src) + 1]; strcpy(newstr, src); return newstr; } void RegisterParameter( UnityAudioEffectDefinition& definition, const char* name, const char* unit, float minval, float maxval, float defaultval, float displayscale, float displayexponent, int enumvalue, const char* description ) { assert(defaultval >= minval); assert(defaultval <= maxval); strcpy_s(definition.paramdefs[enumvalue].name, name); strcpy_s(definition.paramdefs[enumvalue].unit, unit); definition.paramdefs[enumvalue].description = (description != NULL) ? strnew(description) : (name != NULL) ? strnew(name) : NULL; definition.paramdefs[enumvalue].defaultval = defaultval; definition.paramdefs[enumvalue].displayscale = displayscale; definition.paramdefs[enumvalue].displayexponent = displayexponent; definition.paramdefs[enumvalue].min = minval; definition.paramdefs[enumvalue].max = maxval; if (enumvalue >= (int)definition.numparameters) definition.numparameters = enumvalue + 1; } // Helper function to fill default values from the effect definition into the params array -- called by Create callbacks void InitParametersFromDefinitions( InternalEffectDefinitionRegistrationCallback registereffectdefcallback, float* params ) { UnityAudioEffectDefinition definition; memset(&definition, 0, sizeof(definition)); registereffectdefcallback(definition); for (UInt32 n = 0; n < definition.numparameters; n++) { params[n] = definition.paramdefs[n].defaultval; delete[] definition.paramdefs[n].description; } delete[] definition.paramdefs; // assumes that definition.paramdefs was allocated by registereffectdefcallback or is NULL } void DeclareEffect( UnityAudioEffectDefinition& definition, const char* name, UnityAudioEffect_CreateCallback createcallback, UnityAudioEffect_ReleaseCallback releasecallback, UnityAudioEffect_ProcessCallback processcallback, UnityAudioEffect_SetFloatParameterCallback setfloatparametercallback, UnityAudioEffect_GetFloatParameterCallback getfloatparametercallback, UnityAudioEffect_GetFloatBufferCallback getfloatbuffercallback, InternalEffectDefinitionRegistrationCallback registereffectdefcallback ) { memset(&definition, 0, sizeof(definition)); strcpy_s(definition.name, name); definition.structsize = sizeof(UnityAudioEffectDefinition); definition.paramstructsize = sizeof(UnityAudioParameterDefinition); definition.apiversion = UNITY_AUDIO_PLUGIN_API_VERSION; definition.pluginversion = 0x010000; definition.create = createcallback; definition.release = releasecallback; definition.process = processcallback; definition.setfloatparameter = setfloatparametercallback; definition.getfloatparameter = getfloatparametercallback; definition.getfloatbuffer = getfloatbuffercallback; registereffectdefcallback(definition); } #if UNITY_PS3 #define DECLARE_EFFECT(namestr,ns) \ extern char _binary_spu_ ## ns ## _spu_elf_start[]; #include "PluginList.h" #undef DECLARE_EFFECT #endif #define DECLARE_EFFECT(namestr,ns) \ namespace ns \ { \ UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK CreateCallback (UnityAudioEffectState* state); \ UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK ReleaseCallback (UnityAudioEffectState* state); \ UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK ProcessCallback (UnityAudioEffectState* state, float* inbuffer, float* outbuffer, unsigned int length, int inchannels, int outchannels); \ UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK SetFloatParameterCallback (UnityAudioEffectState* state, int index, float value); \ UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK GetFloatParameterCallback (UnityAudioEffectState* state, int index, float* value, char *valuestr); \ UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK GetFloatBufferCallback (UnityAudioEffectState* state, const char* name, float* buffer, int numsamples); \ int InternalRegisterEffectDefinition(UnityAudioEffectDefinition& definition); \ } #include "PluginList.h" #undef DECLARE_EFFECT #if UNITY_PS3 #define DECLARE_EFFECT(namestr,ns) \ DeclareEffect( \ definition[numeffects++], \ namestr, \ ns::CreateCallback, \ ns::ReleaseCallback, \ (UnityAudioEffect_ProcessCallback)_binary_spu_ ## ns ## _spu_elf_start, \ ns::SetFloatParameterCallback, \ ns::GetFloatParameterCallback, \ ns::GetFloatBufferCallback, \ ns::InternalRegisterEffectDefinition); #else #define DECLARE_EFFECT(namestr,ns) \ DeclareEffect( \ definition[numeffects++], \ namestr, \ ns::CreateCallback, \ ns::ReleaseCallback, \ ns::ProcessCallback, \ ns::SetFloatParameterCallback, \ ns::GetFloatParameterCallback, \ ns::GetFloatBufferCallback, \ ns::InternalRegisterEffectDefinition); #endif extern "C" UNITY_AUDIODSP_EXPORT_API int UnityGetAudioEffectDefinitions(UnityAudioEffectDefinition*** definitionptr) { static UnityAudioEffectDefinition definition[256]; static UnityAudioEffectDefinition* definitionp[256]; static int numeffects = 0; if (numeffects == 0) { #include "PluginList.h" } for (int n = 0; n < numeffects; n++) definitionp[n] = &definition[n]; *definitionptr = definitionp; return numeffects; } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7552068 hvcc-0.13.3/hvcc/generators/c2unity/static/source/unity/AudioPluginUtil.h0000644000000000000000000000256714435670357023356 0ustar00#pragma once #include "AudioPluginInterface.h" #include #include #include #include #include #if UNITY_WIN # include #else # if UNITY_SPU # include # include "ps3/AudioPluginInterfacePS3.h" # else # include # endif # define strcpy_s strcpy #endif typedef int (*InternalEffectDefinitionRegistrationCallback)(UnityAudioEffectDefinition& desc); void RegisterParameter( UnityAudioEffectDefinition& desc, const char* name, const char* unit, float minval, float maxval, float defaultval, float displayscale, float displayexponent, int enumvalue, const char* description = NULL); void InitParametersFromDefinitions( InternalEffectDefinitionRegistrationCallback registereffectdefcallback, float* params); void DeclareEffect( UnityAudioEffectDefinition& desc, const char* name, UnityAudioEffect_CreateCallback createcallback, UnityAudioEffect_ReleaseCallback releasecallback, UnityAudioEffect_ProcessCallback processcallback, UnityAudioEffect_SetFloatParameterCallback setfloatparametercallback, UnityAudioEffect_GetFloatParameterCallback getfloatparametercallback, UnityAudioEffect_GetFloatBufferCallback getfloatbuffercallback, InternalEffectDefinitionRegistrationCallback registereffectdefcallback); ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7552068 hvcc-0.13.3/hvcc/generators/c2unity/static/xcode/Info.plist0000644000000000000000000000236514435670357020525 0ustar00 CFBundleDevelopmentRegion English CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 CFPlugInDynamicRegisterFunction CFPlugInDynamicRegistration NO CFPlugInFactories 00000000-0000-0000-0000-000000000000 MyFactoryFunction CFPlugInTypes 00000000-0000-0000-0000-000000000000 00000000-0000-0000-0000-000000000000 CFPlugInUnloadFunction ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7552068 hvcc-0.13.3/hvcc/generators/c2unity/templates/android/jni/Android.mk0000644000000000000000000000332114435670357022264 0ustar00LOCAL_PATH := $(call my-dir) # ------------------------------------------------------------------------------ # static heavy library include $(CLEAR_VARS) LOCAL_MODULE := hv_static LOCAL_CFLAGS := -std=c11 -DNDEBUG -DHV_SIMD_NEON -O3 -ffast-math -fPIC LOCAL_CPPFLAGS := -std=c++11 LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../source/heavy LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/../../source/heavy/*.c) LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/../../source/heavy/*.cpp) LOCAL_ARM_NEON := true LOCAL_ARM_MODE := arm include $(BUILD_STATIC_LIBRARY) # ------------------------------------------------------------------------------ # audiolib.so include $(CLEAR_VARS) LOCAL_MODULE := {{patch_name}}_lib LOCAL_MODULE_FILENAME := libHv_{{patch_name}}_AudioLib LOCAL_CFLAGS := -std=c11 -DNDEBUG -DHV_SIMD_NEON -O3 -ffast-math -fPIC LOCAL_CPPFLAGS := -std=c++11 # there are no additional source files for the library wrapper, # just build a shared library version of it LOCAL_WHOLE_STATIC_LIBRARIES := hv_static LOCAL_LDLIBS := -latomic LOCAL_ARM_NEON := true LOCAL_ARM_MODE := arm include $(BUILD_SHARED_LIBRARY) # ------------------------------------------------------------------------------ # libplugin.so include $(CLEAR_VARS) LOCAL_MODULE := {{patch_name}}_plugin LOCAL_MODULE_FILENAME := AudioPlugin_Hv_{{patch_name}} LOCAL_CFLAGS := -std=c11 -DNDEBUG -DHV_SIMD_NEON -O3 -ffast-math -fPIC LOCAL_CPPFLAGS := -std=c++11 LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../source LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/../../source/unity/*.c) LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/../../source/unity/*.cpp) LOCAL_LDLIBS := -latomic LOCAL_STATIC_LIBRARIES := hv_static LOCAL_ARM_NEON := true LOCAL_ARM_MODE := arm include $(BUILD_SHARED_LIBRARY) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7552068 hvcc-0.13.3/hvcc/generators/c2unity/templates/android/jni/Application.mk0000644000000000000000000000020414435670357023144 0ustar00APP_OPTIM := release APP_STL := c++_static APP_ABI := armeabi-v7a arm64-v8a APP_MODULES := {{patch_name}}_lib {{patch_name}}_plugin ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7552068 hvcc-0.13.3/hvcc/generators/c2unity/templates/linux/Makefile0000644000000000000000000000265314435670357020761 0ustar00CC=clang CXX=clang++ MKDIR=mkdir -p SRCDIR=../source OUTDIR=../build/linux/x64/release BASEFLAGS=-I$(SRCDIR) -DNDEBUG -msse4.1 -O3 -ffast-math -fPIC -Werror -Wno-unused-function -Wno-\#warnings CFLAGS=$(BASEFLAGS) -std=c11 CXXFLAGS=$(BASEFLAGS) -std=c++11 -Wno-writable-strings -fno-exceptions -fno-rtti # AudioLib HEADERS_LIB=$(wildcard $(SRCDIR)/heavy/*.h) HEADERS_LIB+=$(wildcard $(SRCDIR)/heavy/*.hpp) CFILES_LIB=$(wildcard $(SRCDIR)/heavy/*.c) OBJC_LIB=$(CFILES_LIB:%.c=%.o) CXXFILES_LIB=$(wildcard $(SRCDIR)/heavy/*.cpp) OBJCXX_LIB=$(CXXFILES_LIB:%.cpp=%.o) # AudioPlugin HEADERS_PLUG=$(HEADERS_LIB) HEADERS_PLUG+=$(wildcard $(SRCDIR)/unity/*.hpp) CFILES_PLUG=$(CFILES_LIB) CFILES_PLUG+=$(wildcard $(SRCDIR)/unity/*.c) OBJC_PLUG=$(CFILES_PLUG:%.c=%.o) CXXFILES_PLUG=$(CXXFILES_LIB) CXXFILES_PLUG+=$(wildcard $(SRCDIR)/unity/*.cpp) OBJCXX_PLUG=$(CXXFILES_PLUG:%.cpp=%.o) %.o: %.c $(HEADERS) $(CC) -c -o $@ $< $(CFLAGS) %.o: %.cpp $(HEADERS) $(CXX) -c -o $@ $< $(CXXFLAGS) all: directories audiolib audioplugin directories: $(OUTDIR) $(OUTDIR): $(MKDIR) $(OUTDIR) audiolib: $(OBJC_LIB) $(OBJCXX_LIB) $(CXX) -o $(OUTDIR)/Hv_{{patch_name}}_AudioLib.so $^ -shared cp $(SRCDIR)/unity/Hv_{{patch_name}}_AudioLib.cs $(OUTDIR) audioplugin: $(OBJC_PLUG) $(OBJCXX_PLUG) $(CXX) -o $(OUTDIR)/AudioPlugin_Hv_{{patch_name}}.so $^ -shared .PHONY: clean clean: rm -f $(SRCDIR)/**/*.o $(OUTDIR)/*.so $(OUTDIR)/Hv_{{patch_name}}_AudioLib.cs ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7552068 hvcc-0.13.3/hvcc/generators/c2unity/templates/source/unity/Hv_{{name}}_AudioLib.cs0000644000000000000000000003645714435670357025277 0ustar00{%- set hasParams = true if parameters|length > 0 -%} {%- set hasEvents = true if events|length > 0 -%} {%- set hasTables = true if tables|length > 0 -%} {{copyright}} using System; using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine; using UnityEngine.Assertions; using AOT; #if UNITY_EDITOR using UnityEditor; [CustomEditor(typeof(Hv_{{patch_name}}_AudioLib))] public class Hv_{{patch_name}}_Editor : Editor { [MenuItem("Heavy/{{patch_name}}")] static void CreateHv_{{patch_name}}() { GameObject target = Selection.activeGameObject; if (target != null) { target.AddComponent(); } } {%- if hasParams or hasEvents or hasTables %} private Hv_{{patch_name}}_AudioLib _dsp; private void OnEnable() { _dsp = target as Hv_{{patch_name}}_AudioLib; } public override void OnInspectorGUI() { bool isEnabled = _dsp.IsInstantiated(); if (!isEnabled) { EditorGUILayout.LabelField("Press Play!", EditorStyles.centeredGreyMiniLabel); } GUILayout.BeginVertical(); {% if hasEvents -%} // EVENTS GUI.enabled = isEnabled; EditorGUILayout.Space(); {%- for k, v in events %} // {{v.display}} if (GUILayout.Button("{{v.display}}")) { _dsp.SendEvent(Hv_{{patch_name}}_AudioLib.Event.{{k|title}}); } {%- endfor %} {%- endif %} {% if hasParams -%} // PARAMETERS GUI.enabled = true; EditorGUILayout.Space(); EditorGUI.indentLevel++; {%- for k, v in parameters %} // {{v.display}} GUILayout.BeginHorizontal(); float {{k}} = _dsp.GetFloatParameter(Hv_{{patch_name}}_AudioLib.Parameter.{{k|title}}); float new{{k|title}} = EditorGUILayout.Slider("{{v.display}}", {{k}}, {{v.attributes.min}}f, {{v.attributes.max}}f); if ({{k}} != new{{k|title}}) { _dsp.SetFloatParameter(Hv_{{patch_name}}_AudioLib.Parameter.{{k|title}}, new{{k|title}}); } GUILayout.EndHorizontal(); {%- endfor %} EditorGUI.indentLevel--; {%- endif %} {% if hasTables -%} // TABLES GUI.enabled = true; EditorGUILayout.Space(); EditorGUI.indentLevel++; {%- for k, v in tables %} // {{v.display}} EditorGUI.BeginChangeCheck(); AudioClip {{k}}Clip = EditorGUILayout.ObjectField("{{v.display}}", _dsp.{{k}}Clip, typeof(AudioClip), false) as AudioClip; if (EditorGUI.EndChangeCheck()) { _dsp.{{k}}Clip = {{k}}Clip; } {%- endfor %} EditorGUI.indentLevel--; {%- endif %} GUILayout.EndVertical(); } {%- endif %} } #endif // UNITY_EDITOR [RequireComponent (typeof (AudioSource))] public class Hv_{{patch_name}}_AudioLib : MonoBehaviour { {% if hasEvents %} // Events are used to trigger bangs in the patch context (thread-safe). // Example usage: /* void Start () { Hv_{{patch_name}}_AudioLib script = GetComponent(); script.SendEvent(Hv_{{patch_name}}_AudioLib.Event.{{events[0][0]|title}}); } */ public enum Event : uint { {%- for k, v in events %} {{k|title}} = {{v.hash}}, {%- endfor %} } {% endif %} {%- if hasParams %} // Parameters are used to send float messages into the patch context (thread-safe). // Example usage: /* void Start () { Hv_{{patch_name}}_AudioLib script = GetComponent(); // Get and set a parameter float {{parameters[0][0]}} = script.GetFloatParameter(Hv_{{patch_name}}_AudioLib.Parameter.{{parameters[0][0]|title}}); script.SetFloatParameter(Hv_{{patch_name}}_AudioLib.Parameter.{{parameters[0][0]|title}}, {{parameters[0][0]}} + 0.1f); } */ public enum Parameter : uint { {%- for k,v in parameters %} {{k|title}} = {{v.hash}}, {%- endfor %} } {% endif %} {%- if hasTables %} // Tables within the patch context can be filled directly with audio content // Example usage: /* public AudioClip clip; void Start () { Hv_{{patch_name}}_AudioLib script = GetComponent(); // copy clip contents into a temporary buffer float[] buffer = new float[clip.samples]; clip.GetData(buffer, 0); // fill a buffer called "channelL" looper.FillTableWithFloatBuffer((uint) Hv_{{patch_name}}_AudioLib.Table.Channell, buffer); // notify a (non-exposed) receiver of the buffer size looper.SendFloatToReceiver("setTableSize-channelL", clip.samples); } */ public enum Table : uint { {%- for k,v in tables %} {{k|title}} = {{v.hash}}, {%- endfor %} } {% endif %} // Delegate method for receiving float messages from the patch context (thread-safe). // Example usage: /* void Start () { Hv_{{patch_name}}_AudioLib script = GetComponent(); script.RegisterSendHook(); script.FloatReceivedCallback += OnFloatMessage; } void OnFloatMessage(Hv_{{patch_name}}_AudioLib.FloatMessage message) { Debug.Log(message.receiverName + ": " + message.value); } */ public class FloatMessage { public string receiverName; public float value; public FloatMessage(string name, float x) { receiverName = name; value = x; } } public delegate void FloatMessageReceived(FloatMessage message); public FloatMessageReceived FloatReceivedCallback; {%- for k, v in parameters %} public float {{k}} = {{v.attributes.default}}f; {%- endfor %} {%- for k, v in tables %} public AudioClip {{k}}Clip = null; {%- endfor %} // internal state private Hv_{{patch_name}}_Context _context; public bool IsInstantiated() { return (_context != null); } public void RegisterSendHook() { _context.RegisterSendHook(); } {% if hasEvents %} // see Hv_{{patch_name}}_AudioLib.Event for definitions public void SendEvent(Hv_{{patch_name}}_AudioLib.Event e) { if (IsInstantiated()) _context.SendBangToReceiver((uint) e); } {% endif %} {%- if hasParams %} // see Hv_{{patch_name}}_AudioLib.Parameter for definitions public float GetFloatParameter(Hv_{{patch_name}}_AudioLib.Parameter param) { switch (param) { {%- for k, v in parameters %} case Parameter.{{k|title}}: return {{k}}; {%- endfor %} default: return 0.0f; } } public void SetFloatParameter(Hv_{{patch_name}}_AudioLib.Parameter param, float x) { switch (param) { {%- for k, v in parameters %} case Parameter.{{k|title}}: { x = Mathf.Clamp(x, {{v.attributes.min}}f, {{v.attributes.max}}f); {{k}} = x; break; } {%- endfor %} default: return; } if (IsInstantiated()) _context.SendFloatToReceiver((uint) param, x); } {% endif %} public void SendFloatToReceiver(string receiverName, float x) { _context.SendFloatToReceiver(StringToHash(receiverName), x); } public void FillTableWithMonoAudioClip(string tableName, AudioClip clip) { if (clip.channels > 1) { Debug.LogWarning("Hv_{{patch_name}}_AudioLib: Only loading first channel of '" + clip.name + "' into table '" + tableName + "'. Multi-channel files are not supported."); } float[] buffer = new float[clip.samples]; // copy only the 1st channel clip.GetData(buffer, 0); _context.FillTableWithFloatBuffer(StringToHash(tableName), buffer); } public void FillTableWithMonoAudioClip(uint tableHash, AudioClip clip) { if (clip.channels > 1) { Debug.LogWarning("Hv_{{patch_name}}_AudioLib: Only loading first channel of '" + clip.name + "' into table '" + tableHash + "'. Multi-channel files are not supported."); } float[] buffer = new float[clip.samples]; // copy only the 1st channel clip.GetData(buffer, 0); _context.FillTableWithFloatBuffer(tableHash, buffer); } public void FillTableWithFloatBuffer(string tableName, float[] buffer) { _context.FillTableWithFloatBuffer(StringToHash(tableName), buffer); } public void FillTableWithFloatBuffer(uint tableHash, float[] buffer) { _context.FillTableWithFloatBuffer(tableHash, buffer); } public uint StringToHash(string str) { return _context.StringToHash(str); } private void Awake() { _context = new Hv_{{patch_name}}_Context((double) AudioSettings.outputSampleRate); {% if hasTables -%} // Note: only copies first channel from audio clips {%- for k, v in tables %} if ({{k}}Clip != null) { // load buffer {{v.display}} int length = {{k}}Clip.samples; float[] buffer = new float[length]; {{k}}Clip.GetData(buffer, 0); _context.FillTableWithFloatBuffer((uint) Hv_{{patch_name}}_AudioLib.Table.{{k|title}}, buffer); _context.SendFloatToReceiver(_context.StringToHash("setTableSize-{{v.display}}"), length); } {%- endfor %} {%- endif %} } {% if hasParams %} private void Start() { {%- for k, v in parameters %} _context.SendFloatToReceiver((uint) Parameter.{{k|title}}, {{k}}); {%- endfor %} } {% endif %} private void Update() { // retreive sent messages if (_context.IsSendHookRegistered()) { Hv_{{patch_name}}_AudioLib.FloatMessage tempMessage; while ((tempMessage = _context.msgQueue.GetNextMessage()) != null) { FloatReceivedCallback(tempMessage); } } } private void OnAudioFilterRead(float[] buffer, int numChannels) { Assert.AreEqual(numChannels, _context.GetNumOutputChannels()); // invalid channel configuration _context.Process(buffer, buffer.Length / numChannels); // process dsp } } class Hv_{{patch_name}}_Context { #if UNITY_IOS && !UNITY_EDITOR private const string _dllName = "__Internal"; #else private const string _dllName = "Hv_{{patch_name}}_AudioLib"; #endif // Thread-safe message queue public class SendMessageQueue { private readonly object _msgQueueSync = new object(); private readonly Queue _msgQueue = new Queue(); public Hv_{{patch_name}}_AudioLib.FloatMessage GetNextMessage() { lock (_msgQueueSync) { return (_msgQueue.Count != 0) ? _msgQueue.Dequeue() : null; } } public void AddMessage(string receiverName, float value) { Hv_{{patch_name}}_AudioLib.FloatMessage msg = new Hv_{{patch_name}}_AudioLib.FloatMessage(receiverName, value); lock (_msgQueueSync) { _msgQueue.Enqueue(msg); } } } public readonly SendMessageQueue msgQueue = new SendMessageQueue(); private readonly GCHandle gch; private readonly IntPtr _context; // handle into unmanaged memory private SendHook _sendHook = null; [DllImport (_dllName)] private static extern IntPtr hv_{{patch_name}}_new_with_options(double sampleRate, int poolKb, int inQueueKb, int outQueueKb); [DllImport (_dllName)] private static extern int hv_processInlineInterleaved(IntPtr ctx, [In] float[] inBuffer, [Out] float[] outBuffer, int numSamples); [DllImport (_dllName)] private static extern void hv_delete(IntPtr ctx); [DllImport (_dllName)] private static extern double hv_getSampleRate(IntPtr ctx); [DllImport (_dllName)] private static extern int hv_getNumInputChannels(IntPtr ctx); [DllImport (_dllName)] private static extern int hv_getNumOutputChannels(IntPtr ctx); [DllImport (_dllName)] private static extern void hv_setSendHook(IntPtr ctx, SendHook sendHook); [DllImport (_dllName)] private static extern void hv_setPrintHook(IntPtr ctx, PrintHook printHook); [DllImport (_dllName)] private static extern int hv_setUserData(IntPtr ctx, IntPtr userData); [DllImport (_dllName)] private static extern IntPtr hv_getUserData(IntPtr ctx); [DllImport (_dllName)] private static extern void hv_sendBangToReceiver(IntPtr ctx, uint receiverHash); [DllImport (_dllName)] private static extern void hv_sendFloatToReceiver(IntPtr ctx, uint receiverHash, float x); [DllImport (_dllName)] private static extern uint hv_msg_getTimestamp(IntPtr message); [DllImport (_dllName)] private static extern bool hv_msg_hasFormat(IntPtr message, string format); [DllImport (_dllName)] private static extern float hv_msg_getFloat(IntPtr message, int index); [DllImport (_dllName)] private static extern bool hv_table_setLength(IntPtr ctx, uint tableHash, uint newSampleLength); [DllImport (_dllName)] private static extern IntPtr hv_table_getBuffer(IntPtr ctx, uint tableHash); [DllImport (_dllName)] private static extern float hv_samplesToMilliseconds(IntPtr ctx, uint numSamples); [DllImport (_dllName)] private static extern uint hv_stringToHash(string s); private delegate void PrintHook(IntPtr context, string printName, string str, IntPtr message); private delegate void SendHook(IntPtr context, string sendName, uint sendHash, IntPtr message); public Hv_{{patch_name}}_Context(double sampleRate, int poolKb={{pool_sizes_kb.internal}}, int inQueueKb={{pool_sizes_kb.inputQueue}}, int outQueueKb={{pool_sizes_kb.outputQueue}}) { gch = GCHandle.Alloc(msgQueue); _context = hv_{{patch_name}}_new_with_options(sampleRate, poolKb, inQueueKb, outQueueKb); hv_setPrintHook(_context, new PrintHook(OnPrint)); hv_setUserData(_context, GCHandle.ToIntPtr(gch)); } ~Hv_{{patch_name}}_Context() { hv_delete(_context); GC.KeepAlive(_context); GC.KeepAlive(_sendHook); gch.Free(); } public void RegisterSendHook() { // Note: send hook functionality only applies to messages containing a single float value if (_sendHook == null) { _sendHook = new SendHook(OnMessageSent); hv_setSendHook(_context, _sendHook); } } public bool IsSendHookRegistered() { return (_sendHook != null); } public double GetSampleRate() { return hv_getSampleRate(_context); } public int GetNumInputChannels() { return hv_getNumInputChannels(_context); } public int GetNumOutputChannels() { return hv_getNumOutputChannels(_context); } public void SendBangToReceiver(uint receiverHash) { hv_sendBangToReceiver(_context, receiverHash); } public void SendFloatToReceiver(uint receiverHash, float x) { hv_sendFloatToReceiver(_context, receiverHash, x); } public void FillTableWithFloatBuffer(uint tableHash, float[] buffer) { if (hv_table_getBuffer(_context, tableHash) != IntPtr.Zero) { hv_table_setLength(_context, tableHash, (uint) buffer.Length); Marshal.Copy(buffer, 0, hv_table_getBuffer(_context, tableHash), buffer.Length); } else { Debug.Log(string.Format("Table '{0}' doesn't exist in the patch context.", tableHash)); } } public uint StringToHash(string s) { return hv_stringToHash(s); } public int Process(float[] buffer, int numFrames) { return hv_processInlineInterleaved(_context, buffer, buffer, numFrames); } [MonoPInvokeCallback(typeof(PrintHook))] private static void OnPrint(IntPtr context, string printName, string str, IntPtr message) { float timeInSecs = hv_samplesToMilliseconds(context, hv_msg_getTimestamp(message)) / 1000.0f; Debug.Log(string.Format("{0} [{1:0.000}]: {2}", printName, timeInSecs, str)); } [MonoPInvokeCallback(typeof(SendHook))] private static void OnMessageSent(IntPtr context, string sendName, uint sendHash, IntPtr message) { if (hv_msg_hasFormat(message, "f")) { SendMessageQueue msgQueue = (SendMessageQueue) GCHandle.FromIntPtr(hv_getUserData(context)).Target; msgQueue.AddMessage(sendName, hv_msg_getFloat(message, 0)); } } } {# force new line #} ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7562068 hvcc-0.13.3/hvcc/generators/c2unity/templates/source/unity/Hv_{{name}}_AudioPlugin.cpp0000644000000000000000000001004014435670357026160 0ustar00{{copyright}} // http://docs.unity3d.com/500/Documentation/Manual/AudioMixerNativeAudioPlugin.html #include "AudioPluginUtil.h" #include "heavy/Heavy_{{patch_name}}.hpp" namespace Hv_{{patch_name}}_UnityPlugin { enum Param { {%- for k, v in parameters %} P_{{k|upper}}, {%- endfor %} P_NUM_HV_PARAMS_ }; struct EffectData { struct Data { float p[{{parameters|length if parameters|length > 0 else 1}}]; HeavyContextInterface *context; } data; }; int InternalRegisterEffectDefinition(UnityAudioEffectDefinition& definition) { int numparams = P_NUM_HV_PARAMS_; definition.paramdefs = new UnityAudioParameterDefinition[numparams]; // channels will be set to 0 if numInputChannels > 0 else it will be set to numOutputChannels definition.channels = {{0 if num_input_channels else num_output_channels}}; {%- for k, v in parameters %} {%- if v.display|length > 15 %} #if HV_WIN // Unity Windows doesn't seem to like parameter names that are longer than 15 chars RegisterParameter(definition, "{{v.display|cap(15)}}", "", {{v.attributes.min}}f, {{v.attributes.max}}f, {{v.attributes.default}}f, 1.0f, 1.0f, P_{{k|upper}}, "{{v.display}}"); #else RegisterParameter(definition, "{{v.display}}", "", {{v.attributes.min}}f, {{v.attributes.max}}f, {{v.attributes.default}}f, 1.0f, 1.0f, P_{{k|upper}}, "{{v.display}}"); #endif {%- else %} RegisterParameter(definition, "{{v.display}}", "", {{v.attributes.min}}f, {{v.attributes.max}}f, {{v.attributes.default}}f, 1.0f, 1.0f, P_{{k|upper}}, "{{v.display}}"); {%- endif %} {%- endfor %} return numparams; } UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK CreateCallback(UnityAudioEffectState* state) { EffectData* effectdata = new EffectData; effectdata->data.context = new Heavy_{{patch_name}}((double) state->samplerate, {{pool_sizes_kb.internal}}, {{pool_sizes_kb.inputQueue}}, {{pool_sizes_kb.outputQueue}}); state->effectdata = effectdata; InitParametersFromDefinitions(InternalRegisterEffectDefinition, effectdata->data.p); return UNITY_AUDIODSP_OK; } UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK ReleaseCallback(UnityAudioEffectState* state) { EffectData::Data* data = &state->GetEffectData()->data; delete data->context; delete data; return UNITY_AUDIODSP_OK; } UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK SetFloatParameterCallback( UnityAudioEffectState* state, int index, float value) { EffectData::Data *data = &state->GetEffectData()->data; switch (index) { {%- for k, v in parameters %} case P_{{k|upper}}: data->context->sendFloatToReceiver(Heavy_{{patch_name}}::Parameter::In::{{k|upper}}, value); break; {%- endfor %} default: return UNITY_AUDIODSP_ERR_UNSUPPORTED; } data->p[index] = value; return UNITY_AUDIODSP_OK; } UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK GetFloatParameterCallback( UnityAudioEffectState* state, int index, float* value, char *valuestr) { EffectData::Data* data = &state->GetEffectData()->data; if (index < 0 || index >= P_NUM_HV_PARAMS_) return UNITY_AUDIODSP_ERR_UNSUPPORTED; if (value != NULL) *value = data->p[index]; if (valuestr != NULL) valuestr[0] = 0; return UNITY_AUDIODSP_OK; } int UNITY_AUDIODSP_CALLBACK GetFloatBufferCallback(UnityAudioEffectState* state, const char* name, float* buffer, int numsamples) { return UNITY_AUDIODSP_OK; } UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK ProcessCallback( UnityAudioEffectState* state, float* inbuffer, float* outbuffer, unsigned int length, int inchannels, int outchannels) { EffectData::Data* data = &state->GetEffectData()->data; if (state->flags & UnityAudioEffectStateFlags_IsPaused) return UNITY_AUDIODSP_OK; hv_assert(inchannels == data->context->getNumInputChannels()); hv_assert(outchannels == data->context->getNumOutputChannels()); data->context->processInlineInterleaved(inbuffer, outbuffer, length); return UNITY_AUDIODSP_OK; } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7562068 hvcc-0.13.3/hvcc/generators/c2unity/templates/source/unity/PluginList.h0000644000000000000000000000010014435670357023056 0ustar00DECLARE_EFFECT("{{patch_name}}", Hv_{{patch_name}}_UnityPlugin) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1727976067.268552 hvcc-0.13.3/hvcc/generators/c2unity/templates/vs2015/AudioPlugin_Hv_{{name}}.vcxproj0000644000000000000000000002423114677551203025364 0ustar00 Debug Win32 Release Win32 Debug x64 Release x64 {%- for f in files if f.endswith((".c", ".cpp")) %} {%- endfor %} {%- for f in files if f.endswith((".h", ".hpp")) %} {%- endfor %} {F748C943-E015-44C9-A1CE-B5125DB06999} Win32Proj {{name}} 8.1 DynamicLibrary true v140 Unicode DynamicLibrary false v140 true Unicode DynamicLibrary true v140 Unicode DynamicLibrary false v140 true Unicode false $(SolutionDir)..\build\win\x86\debug\ $(SolutionDir)intermediate\win\x86\debug\$(ProjectName)\ false $(SolutionDir)..\build\win\x64\debug\ $(SolutionDir)intermediate\win\x64\debug\$(ProjectName)\ false $(SolutionDir)..\build\win\x86\release\ $(SolutionDir)intermediate\win\x86\release\$(ProjectName)\ false $(SolutionDir)..\build\win\x64\release\ $(SolutionDir)intermediate\win\x64\release\$(ProjectName)\ Level3 Disabled WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_XKEYCHECK_H;%(PreprocessorDefinitions) MultiThreadedDebug $(SolutionDir)..\source Windows true $(IntDir)$(ProjectName).pdb $(IntDir)$(TargetName).lib mincore.lib kernel32.lib; ole32.lib; system32.lib; advapi32.dll Level3 Disabled _DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_XKEYCHECK_H;%(PreprocessorDefinitions) MultiThreadedDebug $(SolutionDir)..\source Windows true $(IntDir)$(ProjectName).pdb $(IntDir)$(TargetName).lib mincore.lib kernel32.lib; ole32.lib; system32.lib; advapi32.dll Level3 MaxSpeed true true WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_XKEYCHECK_H;%(PreprocessorDefinitions) MultiThreaded $(SolutionDir)..\source Windows No $(IntDir)$(ProjectName).pdb $(IntDir)$(TargetName).lib true true mincore.lib kernel32.lib; ole32.lib; system32.lib; advapi32.dll UseLinkTimeCodeGeneration Level3 MaxSpeed true true NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;HV_SIMD_SSE;_XKEYCHECK_H;%(PreprocessorDefinitions) MultiThreaded $(SolutionDir)..\source Windows No $(IntDir)$(ProjectName).pdb $(IntDir)$(TargetName).lib true true mincore.lib kernel32.lib; ole32.lib; system32.lib; advapi32.dll UseLinkTimeCodeGeneration ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1727976067.268552 hvcc-0.13.3/hvcc/generators/c2unity/templates/vs2015/Hv_{{name}}_AudioLib.vcxproj0000644000000000000000000002425314677551203024640 0ustar00 Debug Win32 Release Win32 Debug x64 Release x64 {%- for f in files if f.endswith((".c", ".cpp")) %} {%- endfor %} {%- for f in files if f.endswith((".h", ".hpp")) %} {%- endfor %} {F748C943-E015-44C9-A1CE-B5125DB06999} Win32Proj Hv_{{patch_name}}_AudioLib 8.1 DynamicLibrary true v140 Unicode DynamicLibrary false v140 true Unicode DynamicLibrary true v140 Unicode DynamicLibrary false v140 true Unicode false $(SolutionDir)..\build\win\x86\debug\ $(SolutionDir)intermediate\win\x86\debug\$(ProjectName)\ false $(SolutionDir)..\build\win\x64\debug\ $(SolutionDir)intermediate\win\x64\debug\$(ProjectName)\ false $(SolutionDir)..\build\win\x86\release\ $(SolutionDir)intermediate\win\x86\release\$(ProjectName)\ false $(SolutionDir)..\build\win\x64\release\ $(SolutionDir)intermediate\win\x64\release\$(ProjectName)\ Level3 Disabled WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_XKEYCHECK_H;%(PreprocessorDefinitions) MultiThreadedDebug Windows true $(IntDir)$(ProjectName).pdb $(IntDir)$(TargetName).lib mincore.lib kernel32.lib; ole32.lib; system32.lib; advapi32.dll copy $(SolutionDir)..\source\unity\Hv_{{patch_name}}_AudioLib.cs $(OutDir)\Hv_{{patch_name}}_AudioLib.cs Level3 Disabled _DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_XKEYCHECK_H;%(PreprocessorDefinitions) MultiThreadedDebug Windows true $(IntDir)$(ProjectName).pdb $(IntDir)$(TargetName).lib mincore.lib kernel32.lib; ole32.lib; system32.lib; advapi32.dll copy $(SolutionDir)..\source\unity\Hv_{{patch_name}}_AudioLib.cs $(OutDir)\Hv_{{patch_name}}_AudioLib.cs Level3 MaxSpeed true true WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_XKEYCHECK_H;%(PreprocessorDefinitions) MultiThreaded Windows No $(IntDir)$(ProjectName).pdb $(IntDir)$(TargetName).lib true true mincore.lib kernel32.lib; ole32.lib; system32.lib; advapi32.dll UseLinkTimeCodeGeneration copy $(SolutionDir)..\source\unity\Hv_{{patch_name}}_AudioLib.cs $(OutDir)\Hv_{{patch_name}}_AudioLib.cs Level3 MaxSpeed true true NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;HV_SIMD_SSE;_XKEYCHECK_H;%(PreprocessorDefinitions) MultiThreaded Windows No $(IntDir)$(ProjectName).pdb $(IntDir)$(TargetName).lib true true mincore.lib kernel32.lib; ole32.lib; system32.lib; advapi32.dll UseLinkTimeCodeGeneration copy $(SolutionDir)..\source\unity\Hv_{{patch_name}}_AudioLib.cs $(OutDir)\Hv_{{patch_name}}_AudioLib.cs ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7562068 hvcc-0.13.3/hvcc/generators/c2unity/templates/vs2015/Hv_{{name}}_Unity.sln0000644000000000000000000000403714435670357023363 0ustar00Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hv_{{patch_name}}_AudioLib", "Hv_{{patch_name}}_AudioLib.vcxproj", "{F7CFEF5A-54BD-42E8-A59E-54ABAEB4EA9C}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AudioPlugin_Hv_{{patch_name}}", "AudioPlugin_Hv_{{patch_name}}.vcxproj", "{F748C943-E015-44C9-A1CE-B5125DB06999}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Release|x64 = Release|x64 Release|x86 = Release|x86 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {F7CFEF5A-54BD-42E8-A59E-54ABAEB4EA9C}.Debug|x64.ActiveCfg = Debug|x64 {F7CFEF5A-54BD-42E8-A59E-54ABAEB4EA9C}.Debug|x64.Build.0 = Debug|x64 {F7CFEF5A-54BD-42E8-A59E-54ABAEB4EA9C}.Debug|x86.ActiveCfg = Debug|Win32 {F7CFEF5A-54BD-42E8-A59E-54ABAEB4EA9C}.Debug|x86.Build.0 = Debug|Win32 {F7CFEF5A-54BD-42E8-A59E-54ABAEB4EA9C}.Release|x64.ActiveCfg = Release|x64 {F7CFEF5A-54BD-42E8-A59E-54ABAEB4EA9C}.Release|x64.Build.0 = Release|x64 {F7CFEF5A-54BD-42E8-A59E-54ABAEB4EA9C}.Release|x86.ActiveCfg = Release|Win32 {F7CFEF5A-54BD-42E8-A59E-54ABAEB4EA9C}.Release|x86.Build.0 = Release|Win32 {F748C943-E015-44C9-A1CE-B5125DB06999}.Debug|x64.ActiveCfg = Debug|x64 {F748C943-E015-44C9-A1CE-B5125DB06999}.Debug|x64.Build.0 = Debug|x64 {F748C943-E015-44C9-A1CE-B5125DB06999}.Debug|x86.ActiveCfg = Debug|Win32 {F748C943-E015-44C9-A1CE-B5125DB06999}.Debug|x86.Build.0 = Debug|Win32 {F748C943-E015-44C9-A1CE-B5125DB06999}.Release|x64.ActiveCfg = Release|x64 {F748C943-E015-44C9-A1CE-B5125DB06999}.Release|x64.Build.0 = Release|x64 {F748C943-E015-44C9-A1CE-B5125DB06999}.Release|x86.ActiveCfg = Release|Win32 {F748C943-E015-44C9-A1CE-B5125DB06999}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7562068 hvcc-0.13.3/hvcc/generators/c2unity/templates/xcode/Hv_{{name}}_Unity.xcodeproj/project.pbxproj0000644000000000000000000006323014435670357030057 0ustar00// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ {%- for f in files if f.endswith((".h", ".hpp")) %} {{f|xcode_build}} /* {{f}} in Headers */ = {isa = PBXBuildFile; fileRef = {{f|xcode_fileref}} /* {{f}} */; }; {%- endfor %} {%- for f in files if f.endswith((".c", ".cpp")) %} {{f|xcode_build}} /* {{f}} in Sources */ = {isa = PBXBuildFile; fileRef = {{f|xcode_fileref}} /* {{f}} */; }; {%- endfor %} D854D7E11E23D4840025E5F1 /* AudioPluginUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D854D7B71E23D4840025E5F1 /* AudioPluginUtil.cpp */; }; D854D7E51E23D4840025E5F1 /* Hv_{{patch_name}}_AudioPlugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D854D7BA1E23D4840025E5F1 /* Hv_{{patch_name}}_AudioPlugin.cpp */; }; D89EAC621E23F853008B3443 /* Hv_{{patch_name}}_AudioLib.cs in CopyFiles */ = {isa = PBXBuildFile; fileRef = D854D7B91E23D4840025E5F1 /* Hv_{{patch_name}}_AudioLib.cs */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ D88C9CE8207F6E6C006338E3 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 16; files = ( D89EAC621E23F853008B3443 /* Hv_{{patch_name}}_AudioLib.cs in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; D89EAC611E23F847008B3443 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 16; files = ( D89EAC621E23F853008B3443 /* Hv_{{patch_name}}_AudioLib.cs in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ {%- for f in files if f.endswith(".h") %} {{f|xcode_fileref}} /* {{f}} */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = {{f}}; path = {{f}}; sourceTree = ""; }; {%- endfor %} {%- for f in files if f.endswith(".hpp") %} {{f|xcode_fileref}} /* {{f}} */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = {{f}}; path = {{f}}; sourceTree = ""; }; {%- endfor %} {%- for f in files if f.endswith((".cpp")) %} {{f|xcode_fileref}} /* {{f}} */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = {{f}}; path = {{f}}; sourceTree = ""; }; {%- endfor %} {%- for f in files if f.endswith((".c")) %} {{f|xcode_fileref}} /* {{f}} */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = {{f}}; path = {{f}}; sourceTree = ""; }; {%- endfor %} D854D7271E23D37A0025E5F1 /* AudioPlugin_Hv_{{patch_name}}.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "AudioPlugin_Hv_{{patch_name}}.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; D854D7B61E23D4840025E5F1 /* AudioPluginInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioPluginInterface.h; sourceTree = ""; }; D854D7B71E23D4840025E5F1 /* AudioPluginUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioPluginUtil.cpp; sourceTree = ""; }; D854D7B81E23D4840025E5F1 /* AudioPluginUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioPluginUtil.h; sourceTree = ""; }; D854D7B91E23D4840025E5F1 /* Hv_{{patch_name}}_AudioLib.cs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Hv_{{patch_name}}_AudioLib.cs; sourceTree = ""; }; D854D7BA1E23D4840025E5F1 /* Hv_{{patch_name}}_AudioPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Hv_{{patch_name}}_AudioPlugin.cpp; sourceTree = ""; }; D854D7BB1E23D4840025E5F1 /* PluginList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PluginList.h; sourceTree = ""; }; D854D7E61E23D4FB0025E5F1 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D88C9CEA207F6E6C006338E3 /* libHv_{{patch_name}}_AudioLib.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libHv_{{patch_name}}_AudioLib.a; sourceTree = BUILT_PRODUCTS_DIR; }; D8D3D5061E23D2E00071977E /* Hv_{{patch_name}}_AudioLib.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Hv_{{patch_name}}_AudioLib.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ D854D7241E23D37A0025E5F1 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; D8D3D5031E23D2E00071977E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ D854D78A1E23D4840025E5F1 /* source */ = { isa = PBXGroup; children = ( D854D78B1E23D4840025E5F1 /* heavy */, D854D7B51E23D4840025E5F1 /* unity */, ); name = source; path = ../source; sourceTree = ""; }; D854D78B1E23D4840025E5F1 /* heavy */ = { isa = PBXGroup; children = ( {%- for f in files %} {{f|xcode_fileref}} /* {{f}} */, {%- endfor %} ); path = heavy; sourceTree = ""; }; D854D7B51E23D4840025E5F1 /* unity */ = { isa = PBXGroup; children = ( D854D7B61E23D4840025E5F1 /* AudioPluginInterface.h */, D854D7B71E23D4840025E5F1 /* AudioPluginUtil.cpp */, D854D7B81E23D4840025E5F1 /* AudioPluginUtil.h */, D854D7B91E23D4840025E5F1 /* Hv_{{patch_name}}_AudioLib.cs */, D854D7BA1E23D4840025E5F1 /* Hv_{{patch_name}}_AudioPlugin.cpp */, D854D7BB1E23D4840025E5F1 /* PluginList.h */, ); path = unity; sourceTree = ""; }; D8D3D4FB1E23D2AB0071977E = { isa = PBXGroup; children = ( D854D78A1E23D4840025E5F1 /* source */, D854D7E61E23D4FB0025E5F1 /* Info.plist */, D8D3D5071E23D2E00071977E /* Products */, ); sourceTree = ""; }; D8D3D5071E23D2E00071977E /* Products */ = { isa = PBXGroup; children = ( D8D3D5061E23D2E00071977E /* Hv_{{patch_name}}_AudioLib.bundle */, D854D7271E23D37A0025E5F1 /* AudioPlugin_Hv_{{patch_name}}.bundle */, D88C9CEA207F6E6C006338E3 /* libHv_{{patch_name}}_AudioLib.a */, ); name = Products; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ D854D7261E23D37A0025E5F1 /* AudioPlugin_Hv_{{patch_name}} */ = { isa = PBXNativeTarget; buildConfigurationList = D854D72A1E23D37A0025E5F1 /* Build configuration list for PBXNativeTarget "AudioPlugin_Hv_{{patch_name}}" */; buildPhases = ( D854D7231E23D37A0025E5F1 /* Sources */, D854D7241E23D37A0025E5F1 /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = "AudioPlugin_Hv_{{patch_name}}"; productName = "AudioPlugin_Hv_{{patch_name}}"; productReference = D854D7271E23D37A0025E5F1 /* AudioPlugin_Hv_{{patch_name}}.bundle */; productType = "com.apple.product-type.bundle"; }; D88C9CE9207F6E6C006338E3 /* Hv_{{patch_name}}_AudioLib_iOS */ = { isa = PBXNativeTarget; buildConfigurationList = D88C9CF2207F6E6C006338E3 /* Build configuration list for PBXNativeTarget "Hv_{{patch_name}}_AudioLib_iOS" */; buildPhases = ( D88C9CE6207F6E6C006338E3 /* Sources */, D88C9CE7207F6E6C006338E3 /* Frameworks */, D88C9CE8207F6E6C006338E3 /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = Hv_{{patch_name}}_AudioLib_iOS; productName = Hv_{{patch_name}}_AudioLib_iOS; productReference = D88C9CEA207F6E6C006338E3 /* libHv_{{patch_name}}_AudioLib.a */; productType = "com.apple.product-type.library.static"; }; D8D3D5051E23D2E00071977E /* Hv_{{patch_name}}_AudioLib */ = { isa = PBXNativeTarget; buildConfigurationList = D8D3D50A1E23D2E00071977E /* Build configuration list for PBXNativeTarget "Hv_{{patch_name}}_AudioLib" */; buildPhases = ( D8D3D5021E23D2E00071977E /* Sources */, D8D3D5031E23D2E00071977E /* Frameworks */, D89EAC611E23F847008B3443 /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = "Hv_{{patch_name}}_AudioLib"; productName = "Hv_{{patch_name}}_AudioLib"; productReference = D8D3D5061E23D2E00071977E /* Hv_{{patch_name}}_AudioLib.bundle */; productType = "com.apple.product-type.bundle"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ D8D3D4FC1E23D2AB0071977E /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0820; TargetAttributes = { D854D7261E23D37A0025E5F1 = { CreatedOnToolsVersion = 8.2; ProvisioningStyle = Automatic; }; D88C9CE9207F6E6C006338E3 = { CreatedOnToolsVersion = 9.2; ProvisioningStyle = Automatic; }; D8D3D5051E23D2E00071977E = { CreatedOnToolsVersion = 8.2; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = D8D3D4FF1E23D2AB0071977E /* Build configuration list for PBXProject "Hv_{{patch_name}}_Unity" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = D8D3D4FB1E23D2AB0071977E; productRefGroup = D8D3D5071E23D2E00071977E /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( D8D3D5051E23D2E00071977E /* Hv_{{patch_name}}_AudioLib */, D854D7261E23D37A0025E5F1 /* AudioPlugin_Hv_{{patch_name}} */, D88C9CE9207F6E6C006338E3 /* Hv_{{patch_name}}_AudioLib_iOS */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ D854D7231E23D37A0025E5F1 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( {%- for f in files if f.endswith((".c", ".cpp")) %} {{f|xcode_build}} /* {{f}} in Sources */, {%- endfor %} D854D7E51E23D4840025E5F1 /* Hv_{{patch_name}}_AudioPlugin.cpp in Sources */, D854D7E11E23D4840025E5F1 /* AudioPluginUtil.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; D8D3D5021E23D2E00071977E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( {%- for f in files if f.endswith((".c", ".cpp")) %} {{f|xcode_build}} /* {{f}} in Sources */, {%- endfor %} ); runOnlyForDeploymentPostprocessing = 0; }; D88C9CE6207F6E6C006338E3 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( {%- for f in files if f.endswith((".c", ".cpp")) %} {{f|xcode_build}} /* {{f}} in Sources */, {%- endfor %} ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ D854D72B1E23D37A0025E5F1 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/../build/macos/$(ARCHS)/$(CONFIGURATION)"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c11; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_CPP_RTTI = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../source"; INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; MACOSX_DEPLOYMENT_TARGET = 10.7; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "-msse4.1", "-Wno-#warnings", "-Wno-unused-function", ); PRODUCT_BUNDLE_IDENTIFIER = "enzn.AudioPlugin-Hv-{{patch_name}}"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; WRAPPER_EXTENSION = bundle; }; name = Debug; }; D854D72C1E23D37A0025E5F1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/../build/macos/$(ARCHS)/$(CONFIGURATION)"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c11; GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_CPP_RTTI = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../source"; INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; MACOSX_DEPLOYMENT_TARGET = 10.7; MTL_ENABLE_DEBUG_INFO = NO; OTHER_CFLAGS = ( "-msse4.1", "-ffast-math", "-DNDEBUG", "-Wno-#warnings", "-Wno-unused-function", ); PRODUCT_BUNDLE_IDENTIFIER = "enzn.AudioPlugin-Hv-{{patch_name}}"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; WRAPPER_EXTENSION = bundle; }; name = Release; }; D88C9CF0207F6E6C006338E3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/../build/ios/$(ARCHS)/$(CONFIGURATION)"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../source"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "-Wno-unused-function", "-Wno-#warnings", ); OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = Hv_{{patch_name}}_AudioLib; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; D88C9CF1207F6E6C006338E3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/../build/ios/$(ARCHS)/$(CONFIGURATION)"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../source"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = "-ObjC"; OTHER_CFLAGS = ( "-ffast-math", "-DNDEBUG", "-Wno-#warnings", "-Wno-unused-function", ); PRODUCT_NAME = Hv_{{patch_name}}_AudioLib; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; D8D3D5001E23D2AB0071977E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { }; name = Debug; }; D8D3D5011E23D2AB0071977E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { }; name = Release; }; D8D3D50B1E23D2E00071977E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/../build/macos/$(ARCHS)/$(CONFIGURATION)"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c11; GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_CPP_RTTI = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../source"; INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; MACOSX_DEPLOYMENT_TARGET = 10.7; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "-msse4.1", "-Wno-#warnings", "-Wno-unused-function", ); PRODUCT_BUNDLE_IDENTIFIER = "enzn.Hv-{{patch_name}}-AudioLib"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; WRAPPER_EXTENSION = bundle; }; name = Debug; }; D8D3D50C1E23D2E00071977E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/../build/macos/$(ARCHS)/$(CONFIGURATION)"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c11; GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_CPP_RTTI = NO; GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_CPP_RTTI = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../source"; INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; MACOSX_DEPLOYMENT_TARGET = 10.7; MTL_ENABLE_DEBUG_INFO = NO; OTHER_CFLAGS = ( "-msse4.1", "-ffast-math", "-DNDEBUG", "-Wno-#warnings", "-Wno-unused-function", ); PRODUCT_BUNDLE_IDENTIFIER = "enzn.Hv-{{patch_name}}-AudioLib"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; WRAPPER_EXTENSION = bundle; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ D854D72A1E23D37A0025E5F1 /* Build configuration list for PBXNativeTarget "AudioPlugin_Hv_{{patch_name}}" */ = { isa = XCConfigurationList; buildConfigurations = ( D854D72B1E23D37A0025E5F1 /* Debug */, D854D72C1E23D37A0025E5F1 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; D88C9CF2207F6E6C006338E3 /* Build configuration list for PBXNativeTarget "Hv_{{patch_name}}_AudioLib_iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( D88C9CF0207F6E6C006338E3 /* Debug */, D88C9CF1207F6E6C006338E3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; D8D3D4FF1E23D2AB0071977E /* Build configuration list for PBXProject "Hv_{{patch_name}}_Unity" */ = { isa = XCConfigurationList; buildConfigurations = ( D8D3D5001E23D2AB0071977E /* Debug */, D8D3D5011E23D2AB0071977E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; D8D3D50A1E23D2E00071977E /* Build configuration list for PBXNativeTarget "Hv_{{patch_name}}_AudioLib" */ = { isa = XCConfigurationList; buildConfigurations = ( D8D3D50B1E23D2E00071977E /* Debug */, D8D3D50C1E23D2E00071977E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = D8D3D4FC1E23D2AB0071977E /* Project object */; } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7562068 hvcc-0.13.3/hvcc/generators/c2wwise/__init__.py0000644000000000000000000000000014435670357016243 0ustar00././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.267823 hvcc-0.13.3/hvcc/generators/c2wwise/c2wwise.py0000644000000000000000000001434214735300474016076 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2021-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os import shutil import time import jinja2 from typing import Optional from ..copyright import copyright_manager from ..filters import filter_plugin_id from hvcc.interpreters.pd2hv.NotificationEnum import NotificationEnum from hvcc.types.compiler import Generator, CompilerResp, CompilerNotif, CompilerMsg, ExternInfo from hvcc.types.meta import Meta class c2wwise(Generator): """Generates a plugin wrapper for Audiokinetic's Wwise game audio middleware platform. """ @classmethod def compile( cls, c_src_dir: str, out_dir: str, externs: ExternInfo, patch_name: Optional[str] = None, patch_meta: Meta = Meta(), num_input_channels: int = 0, num_output_channels: int = 0, copyright: Optional[str] = None, verbose: Optional[bool] = False ) -> CompilerResp: tick = time.time() in_parameter_list = externs.parameters.inParam out_parameter_list = externs.parameters.outParam event_list = externs.events.inEvent out_event_list = externs.events.outEvent table_list = externs.tables patch_name = patch_name or "heavy" copyright_c = copyright_manager.get_copyright_for_c(copyright) copyright_xml = copyright_manager.get_copyright_for_xml(copyright) templates_dir = os.path.join(os.path.dirname(__file__), "templates") is_source_plugin = num_input_channels == 0 plugin_type = "Source" if is_source_plugin else "FX" plugin_id = filter_plugin_id(patch_name) out_dir = os.path.join(out_dir, "wwise") if not os.path.exists(out_dir): os.makedirs(out_dir) env = jinja2.Environment() env.loader = jinja2.FileSystemLoader( encoding="utf-8-sig", searchpath=[templates_dir]) try: channel_config = None if num_output_channels == 0: # Workaround to support patches that don't have any outputs, # e.g. that only ever set RTPCs or post events channel_config = "AK_SPEAKER_SETUP_MONO" elif num_output_channels == 1: channel_config = "AK_SPEAKER_SETUP_MONO" elif num_output_channels == 2: channel_config = "AK_SPEAKER_SETUP_STEREO" elif num_output_channels == 6: channel_config = "AK_SPEAKER_SETUP_5POINT1" elif num_output_channels == 8: channel_config = "AK_SPEAKER_SETUP_7POINT1" elif num_output_channels == 12: channel_config = "AK_SPEAKER_SETUP_DOLBY_7_1_4" else: raise Exception("Wwise plugins support only mono, stereo, 5.1, 7.1, " "and 7.1.4 (Atmos) configurations, number of [dac~] channels should be appropriate") if plugin_type == "FX": if num_input_channels != num_output_channels: raise Exception("Wwise FX plugins require the same input/output channel" "configuration (i.e. [adc~ 1] -> [dac~ 1]).") patch_src_dir = os.path.join(out_dir, "SoundEnginePlugin", "Heavy") if os.path.exists(patch_src_dir): shutil.rmtree(patch_src_dir) shutil.copytree(c_src_dir, patch_src_dir) src_ext_list = ["h", "hpp", "c", "cpp", "xml", "def", "rc", "lua", "json"] for f in env.list_templates(extensions=src_ext_list): file_dir = os.path.join(out_dir, os.path.dirname(f)) file_name = os.path.basename(f) file_name = file_name.replace("{{name}}", patch_name) file_name = file_name.replace("{{plugin_type}}", plugin_type) file_path = os.path.join(file_dir, file_name) if not os.path.exists(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) with open(file_path, "w") as g: g.write(env.get_template(f).render( name=patch_name, parameters=in_parameter_list, out_params=out_parameter_list, out_events=out_event_list, events=event_list, tables=table_list, pool_sizes_kb=externs.memoryPoolSizesKb, is_source=is_source_plugin, num_input_channels=num_input_channels, num_output_channels=num_output_channels, channel_config=channel_config, plugin_type=plugin_type, plugin_id=plugin_id, copyright=copyright_xml if file_name.endswith(".xml") else copyright_c)) return CompilerResp( stage="c2wwise", in_dir=c_src_dir, out_dir=out_dir, compile_time=time.time() - tick ) except Exception as e: return CompilerResp( stage="c2wwise", notifs=CompilerNotif( has_error=True, exception=e, warnings=[], errors=[CompilerMsg( enum=NotificationEnum.ERROR_EXCEPTION, message=str(e) )] ), in_dir=c_src_dir, out_dir=out_dir, compile_time=time.time() - tick ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5941823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/Includes/libnyquist/AudioDecoder.h0000644000000000000000000000557314735300037024611 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef AUDIO_DECODER_H #define AUDIO_DECODER_H #include "Common.h" #include #include #include #include namespace nqr { struct UnsupportedExtensionEx : public std::runtime_error { UnsupportedExtensionEx() : std::runtime_error("Unsupported file extension") {} }; struct LoadPathNotImplEx : public std::runtime_error { LoadPathNotImplEx() : std::runtime_error("Loading from path not implemented") {} }; struct LoadBufferNotImplEx : public std::runtime_error { LoadBufferNotImplEx() : std::runtime_error("Loading from buffer not implemented") {} }; struct BaseDecoder { virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) = 0; virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector & memory) = 0; virtual std::vector GetSupportedFileExtensions() = 0; }; typedef std::pair> DecoderPair; class NyquistIO { public: NyquistIO(); ~NyquistIO(); void Load(AudioData * data, const std::string & path); void Load(AudioData *data, std::string extension, const std::vector & buffer); bool IsFileSupported(const std::string path) const; private: std::string ParsePathForExtension(const std::string & path) const; std::shared_ptr GetDecoderForExtension(const std::string ext); void BuildDecoderTable(); void AddDecoderToTable(std::shared_ptr decoder); std::map> decoderTable; NO_MOVE(NyquistIO); }; } // end namespace nqr #endif././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5941823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/Includes/libnyquist/Common.h0000644000000000000000000002036014735300037023501 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LIBNYQUIST_COMMON_H #define LIBNYQUIST_COMMON_H #include #include #include #include #include #include #include #include #include #include #include #include "PostProcess.h" #include "Dither.h" namespace nqr { ///////////////// // Util Macros // ///////////////// #define F_ROUND(x) ((x) > 0 ? (x) + 0.5f : (x) - 0.5f) #define D_ROUND(x) ((x) > 0 ? (x) + 0.5 : (x) - 0.5) #define NO_COPY(C) C(const C &) = delete; C & operator = (const C &) = delete #define NO_MOVE(C) NO_COPY(C); C(C &&) = delete; C & operator = (const C &&) = delete /////////////////////// // Endian Operations // /////////////////////// #if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86) #define CPU_X86 1 #endif #if defined(__arm__) || defined(_M_ARM) #define CPU_ARM 1 #endif #if defined(CPU_X86) && defined(CPU_ARM) #error CPU_X86 and CPU_ARM both defined. #endif #if !defined(ARCH_CPU_BIG_ENDIAN) && !defined(ARCH_CPU_LITTLE_ENDIAN) #if CPU_X86 || CPU_ARM || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) #define ARCH_CPU_LITTLE_ENDIAN #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #define ARCH_CPU_BIG_ENDIAN #else #error ARCH_CPU_BIG_ENDIAN or ARCH_CPU_LITTLE_ENDIAN should be defined. #endif #endif #if defined(ARCH_CPU_BIG_ENDIAN) && defined(ARCH_CPU_LITTLE_ENDIAN) #error ARCH_CPU_BIG_ENDIAN and ARCH_CPU_LITTLE_ENDIAN both defined. #endif static inline uint16_t Swap16(uint16_t value) { return (uint16_t)((value >> 8) | (value << 8)); } static inline uint32_t Swap24(uint32_t value) { return (((value & 0x00ff0000) >> 16) | ((value & 0x0000ff00)) | ((value & 0x000000ff) << 16)) & 0x00FFFFFF; } static inline uint32_t Swap32(uint32_t value) { return (((value & 0x000000ff) << 24) | ((value & 0x0000ff00) << 8) | ((value & 0x00ff0000) >> 8) | ((value & 0xff000000) >> 24)); } static inline uint64_t Swap64(uint64_t value) { return (((value & 0x00000000000000ffLL) << 56) | ((value & 0x000000000000ff00LL) << 40) | ((value & 0x0000000000ff0000LL) << 24) | ((value & 0x00000000ff000000LL) << 8) | ((value & 0x000000ff00000000LL) >> 8) | ((value & 0x0000ff0000000000LL) >> 24) | ((value & 0x00ff000000000000LL) >> 40) | ((value & 0xff00000000000000LL) >> 56)); } template inline bool isOdd(const T x) { return (x & 0x1); } #ifdef ARCH_CPU_LITTLE_ENDIAN #define Read16(n) (n) #define Read24(n) (n) #define Read32(n) (n) #define Read64(n) (n) #define Write16(n) (n) #define Write24(n) (n) #define Write32(n) (n) #define Write64(n) (n) #else #define Read16(n) Swap16(n) #define Read24(n) Swap24(n) #define Read32(n) Swap32(n) #define Read64(n) Swap64(n) #define Write16(n) Swap16(n) #define Write24(n) Swap24(n) #define Write32(n) Swap32(n) #define Write64(n) Swap64(n) #endif inline uint64_t Pack(uint32_t a, uint32_t b) { uint64_t tmp = (uint64_t) b << 32 | (uint64_t) a; #ifdef ARCH_CPU_LITTLE_ENDIAN return tmp; #else return Swap64(tmp); #endif } inline uint32_t Pack(uint16_t a, uint16_t b) { uint32_t tmp = (uint32_t) b << 16 | (uint32_t) a; #ifdef ARCH_CPU_LITTLE_ENDIAN return tmp; #else return Swap32(tmp); #endif } inline uint16_t Pack(uint8_t a, uint8_t b) { uint16_t tmp = (uint16_t) b << 8 | (uint16_t) a; #ifdef ARCH_CPU_LITTLE_ENDIAN return tmp; #else return Swap16(tmp); #endif } // http://www.dsprelated.com/showthread/comp.dsp/136689-1.php inline int32_t Pack(uint8_t a, uint8_t b, uint8_t c) { // uint32_t tmp = ((c & 0x80) ? (0xFF << 24) : 0x00 << 24) | (c << 16) | (b << 8) | (a << 0); // alternate method int32_t x = (c << 16) | (b << 8) | (a << 0); auto sign_extended = (x) | (!!((x) & 0x800000) * 0xff000000); #ifdef ARCH_CPU_LITTLE_ENDIAN return sign_extended; #else Swap32(sign_extended); #endif } inline std::array Unpack(uint32_t a) { static std::array output; #ifdef ARCH_CPU_LITTLE_ENDIAN output[0] = a >> 0; output[1] = a >> 8; output[2] = a >> 16; #else output[0] = a >> 16; output[1] = a >> 8; output[2] = a >> 0; #endif return output; } ////////////////////////// // Conversion Utilities // ////////////////////////// // Signed maxes, defined for readabilty/convenience #define NQR_INT16_MAX 32767.f #define NQR_INT24_MAX 8388608.f #define NQR_INT32_MAX 2147483648.f static const float NQR_BYTE_2_FLT = 1.0f / 127.0f; #define int8_to_float32(s) ((float) (s) * NQR_BYTE_2_FLT) #define uint8_to_float32(s)(((float) (s) - 128) * NQR_BYTE_2_FLT) #define int16_to_float32(s) ((float) (s) / NQR_INT16_MAX) #define int24_to_float32(s) ((float) (s) / NQR_INT24_MAX) #define int32_to_float32(s) ((float) (s) / NQR_INT32_MAX) #define float32_to_int8(s) (float) (s * 127.f) #define float32_to_uint8(s) (float) ((s * 127.f) + 128) #define float32_to_int16(s) (float) (s * NQR_INT16_MAX) #define float32_to_int24(s) (float) (s * NQR_INT24_MAX) #define float32_to_int32(s) (float) (s * NQR_INT32_MAX) //@todo add 12, 20 for flac enum PCMFormat { PCM_U8, PCM_S8, PCM_16, PCM_24, PCM_32, PCM_64, PCM_FLT, PCM_DBL, PCM_END }; template T clamp(T a, T mn, T mx) { return std::max(std::min(a, mx), mn); } // Src data is aligned to PCMFormat // @todo normalize? void ConvertToFloat32(float * dst, const uint8_t * src, const size_t N, PCMFormat f); // Src data is always aligned to 4 bytes (WavPack, primarily) void ConvertToFloat32(float * dst, const int32_t * src, const size_t N, PCMFormat f); // Src data is always aligned to 2 bytes (IMA ADPCM, primarily) void ConvertToFloat32(float * dst, const int16_t * src, const size_t N, PCMFormat f); void ConvertFromFloat32(uint8_t * dst, const float * src, const size_t N, PCMFormat f, DitherType t = DITHER_NONE); ////////////////////////// // User Data + File Ops // ////////////////////////// struct AudioData { int channelCount; int sampleRate; double lengthSeconds; size_t frameSize; // channels * bits per sample std::vector samples; PCMFormat sourceFormat; //@todo: add field: channel layout //@todo: add field: lossy / lossless //@todo: audio data loaded (for metadata only) //@todo: bitrate (if applicable) //@todo: original sample rate (if applicable) }; struct StreamableAudioData : public AudioData { //@todo: add field: is this format streamable? //@todo: hold file handle }; struct NyquistFileBuffer { std::vector buffer; size_t size; }; NyquistFileBuffer ReadFile(std::string pathToFile); int GetFormatBitsPerSample(PCMFormat f); PCMFormat MakeFormatForBits(int bits, bool floatingPt, bool isSigned); } // end namespace nqr #endif ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5941823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/Includes/libnyquist/Dither.h0000644000000000000000000000371214735300037023472 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef DITHER_OPERATIONS_H #define DITHER_OPERATIONS_H #include namespace nqr { enum DitherType { DITHER_NONE, DITHER_TRIANGLE }; class Dither { std::uniform_real_distribution distribution; std::mt19937 rndGen; float prev = 0.0f; DitherType d; public: Dither(DitherType d) : distribution(-0.5f, +0.5f), d(d) {} float operator()(float s) { if (d == DITHER_TRIANGLE) { const float value = distribution(rndGen); s = s + value - prev; prev = value; return s; } else { return s; } } }; } // end namespace nqr #endif ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5941823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/Includes/libnyquist/IMA4Util.h0000644000000000000000000001163314735300037023604 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef IMA4_UTIL_H #define IMA4_UTIL_H #include "AudioDecoder.h" namespace nqr { struct ADPCMState { int frame_size; int firstDataBlockByte; int dataSize; int currentByte; const uint8_t * inBuffer; }; static const int ima_index_table[16] = { -1, -1, -1, -1, // +0 / +3 : - the step 2, 4, 6, 8, // +4 / +7 : + the step -1, -1, -1, -1, // -0 / -3 : - the step 2, 4, 6, 8, // -4 / -7 : + the step }; static inline int ima_clamp_index(int index) { if (index < 0) return 0; else if (index > 88) return 88; return index; } static inline int16_t ima_clamp_predict(int16_t predict) { if (predict < -32768) return -32768; else if (predict > 32767) return 32767; return predict; } static const int ima_step_table[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 }; // Decodes an IMA ADPCM nibble to a 16 bit pcm sample static inline int16_t decode_nibble(uint8_t nibble, int16_t & p, int & s) { // Compute a delta to add to the predictor value int diff = ima_step_table[s] >> 3; if (nibble & 4) diff += ima_step_table[s]; if (nibble & 2) diff += ima_step_table[s] >> 1; if (nibble & 1) diff += ima_step_table[s] >> 2; // Sign if (nibble & 8) diff = -diff; // Add delta p += diff; s += ima_index_table[nibble]; s = ima_clamp_index(s); return ima_clamp_predict(p); } void decode_ima_adpcm(ADPCMState & state, int16_t * outBuffer, uint32_t num_channels) { const uint8_t * data = state.inBuffer; // Loop over the interleaved channels for (uint32_t ch = 0; ch < num_channels; ch++) { const int byteOffset = ch * 4; // Header Structure: // Byte0: packed low byte of the initial predictor // Byte1: packed high byte of the initial predictor // Byte2: initial step index // Byte3: Reserved empty value int16_t predictor = ((int16_t)data[byteOffset + 1] << 8) | data[byteOffset]; int stepIndex = data[byteOffset + 2]; uint8_t reserved = data[byteOffset + 3]; if (reserved != 0) throw std::runtime_error("adpcm decode error"); int byteIdx = num_channels * 4 + byteOffset; //the byte index of the first data word for this channel int idx = ch; // Decode nibbles of the remaining data while (byteIdx < state.frame_size) { for (int j = 0; j < 4; j++) { outBuffer[idx] = decode_nibble(data[byteIdx] & 0xf, predictor, stepIndex); // low nibble idx += num_channels; outBuffer[idx] = decode_nibble(data[byteIdx] >> 4, predictor, stepIndex); // high nibble idx += num_channels; byteIdx++; } byteIdx += (num_channels - 1) << 2; // Jump to the next data word for the current channel } } } } // end namespace nqr #endif ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5941823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/Includes/libnyquist/ModplugDecoder.h0000644000000000000000000000343014735300037025145 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MODPLUG_DECODER_H #define MODPLUG_DECODER_H #include "AudioDecoder.h" namespace nqr { struct ModplugDecoder : public nqr::BaseDecoder { ModplugDecoder() {}; virtual ~ModplugDecoder() {}; virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override; virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector & memory) override; virtual std::vector GetSupportedFileExtensions() override; }; } // end namespace nqr #endif././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5941823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/Includes/libnyquist/PostProcess.h0000644000000000000000000000570714735300037024545 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef POSTPROCESS_H #define POSTPROCESS_H #include namespace nqr { template inline void DeinterleaveStereo(T * c1, T * c2, T const * src, size_t count) { auto src_end = src + count; while (src != src_end) { *c1 = src[0]; *c2 = src[1]; c1++; c2++; src += 2; } } template void InterleaveChannels(const T * src, T * dest, size_t numFramesPerChannel, size_t numChannels, size_t N) { for (size_t ch = 0; ch < numChannels; ch++) { size_t x = ch; const T * srcChannel = &src[ch * numFramesPerChannel]; for(size_t i = 0; i < N; i++) { dest[x] = srcChannel[i]; x += numChannels; } } } template void DeinterleaveChannels(const T * src, T * dest, size_t numFramesPerChannel, size_t numChannels, size_t N) { for(size_t ch = 0; ch < numChannels; ch++) { size_t x = ch; T *destChannel = &dest[ch * numFramesPerChannel]; for (size_t i = 0; i < N; i++) { destChannel[i] = (T) src[x]; x += numChannels; } } } template void StereoToMono(const T * src, T * dest, size_t N) { for (size_t i = 0, j = 0; i < N; i += 2, ++j) { dest[j] = (src[i] + src[i + 1]) / 2.0f; } } template void MonoToStereo(const T * src, T * dest, size_t N) { for(size_t i = 0, j = 0; i < N; ++i, j += 2) { dest[j] = src[i]; dest[j + 1] = src[i]; } } inline void TrimSilenceInterleaved(std::vector & buffer, float v, bool fromFront, bool fromEnd) { //@todo implement me! } } // end namespace nqr #endif ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5941823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/Includes/libnyquist/RiffUtils.h0000644000000000000000000000502514735300037024161 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RIFF_UTILS_H #define RIFF_UTILS_H #include "Common.h" #include "WavDecoder.h" #include "Dither.h" namespace nqr { ///////////////////// // Chunk utilities // ///////////////////// struct EncoderParams { int channelCount; PCMFormat targetFormat; DitherType dither; }; struct ChunkHeaderInfo { uint32_t offset; // Byte offset into chunk uint32_t size; // Size of the chunk in bytes }; inline uint32_t GenerateChunkCode(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { #ifdef ARCH_CPU_LITTLE_ENDIAN return ((uint32_t) ((a) | ((b) << 8) | ((c) << 16) | (((uint32_t) (d)) << 24))); #else return ((uint32_t) ((((uint32_t) (a)) << 24) | ((b) << 16) | ((c) << 8) | (d))); #endif } inline char * GenerateChunkCodeChar(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { auto chunk = GenerateChunkCode(a, b, c, d); char * outArr = new char[4]; uint32_t t = 0x000000FF; for(size_t i = 0; i < 4; i++) { outArr[i] = chunk & t; chunk >>= 8; } return outArr; } ChunkHeaderInfo ScanForChunk(const std::vector & fileData, uint32_t chunkMarker); WaveChunkHeader MakeWaveHeader(const EncoderParams param, const int sampleRate); } // end namespace nqr #endif ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5941823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/Includes/libnyquist/WavDecoder.h0000644000000000000000000001576514735300037024311 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef WAVE_DECODER_H #define WAVE_DECODER_H #include "AudioDecoder.h" namespace nqr { enum WaveFormatCode { FORMAT_UNKNOWN = 0x0, // Unknown Wave Format FORMAT_PCM = 0x1, // PCM Format FORMAT_ADPCM = 0x2, // Microsoft ADPCM Format FORMAT_IEEE = 0x3, // IEEE float/double FORMAT_ALAW = 0x6, // 8-bit ITU-T G.711 A-law FORMAT_MULAW = 0x7, // 8-bit ITU-T G.711 mu-law FORMAT_IMA_ADPCM = 0x11, // IMA ADPCM Format FORMAT_EXT = 0xFFFE // Set via subformat }; struct RiffChunkHeader { uint32_t id_riff; // Chunk ID: 'RIFF' uint32_t file_size; // Entire file in bytes uint32_t id_wave; // Chunk ID: 'WAVE' }; struct WaveChunkHeader { uint32_t fmt_id; // Chunk ID: 'fmt ' uint32_t chunk_size; // Size in bytes uint16_t format; // Format code uint16_t channel_count; // Num interleaved channels uint32_t sample_rate; // SR uint32_t data_rate; // Data rate uint16_t frame_size; // 1 frame = channels * bits per sample (also known as block align) uint16_t bit_depth; // Bits per sample }; struct BextChunk { uint32_t fmt_id; // Chunk ID: 'bext' uint32_t chunk_size; // Size in bytes uint8_t description[256]; // Description of the sound (ascii) uint8_t origin[32]; // Name of the originator (ascii) uint8_t origin_ref[32]; // Reference of the originator (ascii) uint8_t orgin_date[10]; // yyyy-mm-dd (ascii) uint8_t origin_time[8]; // hh-mm-ss (ascii) uint64_t time_ref; // First sample count since midnight uint32_t version; // Version of the BWF uint8_t uimd[64]; // Byte 0 of SMPTE UMID uint8_t reserved[188]; // 190 bytes, reserved for future use & set to NULL }; struct FactChunk { uint32_t fact_id; // Chunk ID: 'fact' uint32_t chunk_size; // Size in bytes uint32_t sample_length; // number of samples per channel }; struct ExtensibleData { uint16_t size; uint16_t valid_bits_per_sample; uint32_t channel_mask; struct GUID { uint32_t data0; uint16_t data1; uint16_t data2; uint16_t data3; uint8_t data4[6]; }; }; template std::basic_ostream & operator << (std::basic_ostream & a, const WaveChunkHeader & b) { return a << "Format ID:\t\t" << b.fmt_id << "\nChunk Size:\t\t" << b.chunk_size << "\nFormat Code:\t\t" << b.format << "\nChannels:\t\t" << b.channel_count << "\nSample Rate:\t\t" << b.sample_rate << "\nData Rate:\t\t" << b.data_rate << "\nFrame Size:\t\t" << b.frame_size << "\nBit Depth:\t\t" << b.bit_depth << std::endl; } //@todo expose speaker/channel/layout masks in the API: enum SpeakerChannelMask { SPEAKER_FRONT_LEFT = 0x00000001, SPEAKER_FRONT_RIGHT = 0x00000002, SPEAKER_FRONT_CENTER = 0x00000004, SPEAKER_LOW_FREQUENCY = 0x00000008, SPEAKER_BACK_LEFT = 0x00000010, SPEAKER_BACK_RIGHT = 0x00000020, SPEAKER_FRONT_LEFT_OF_CENTER = 0x00000040, SPEAKER_FRONT_RIGHT_OF_CENTER = 0x00000080, SPEAKER_BACK_CENTER = 0x00000100, SPEAKER_SIDE_LEFT = 0x00000200, SPEAKER_SIDE_RIGHT = 0x00000400, SPEAKER_TOP_CENTER = 0x00000800, SPEAKER_TOP_FRONT_LEFT = 0x00001000, SPEAKER_TOP_FRONT_CENTER = 0x00002000, SPEAKER_TOP_FRONT_RIGHT = 0x00004000, SPEAKER_TOP_BACK_LEFT = 0x00008000, SPEAKER_TOP_BACK_CENTER = 0x00010000, SPEAKER_TOP_BACK_RIGHT = 0x00020000, SPEAKER_RESERVED = 0x7FFC0000, SPEAKER_ALL = 0x80000000 }; enum SpeakerLayoutMask { SPEAKER_MONO = (SPEAKER_FRONT_CENTER), SPEAKER_STEREO = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT), SPEAKER_2POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY), SPEAKER_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER), SPEAKER_QUAD = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT), SPEAKER_4POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT), SPEAKER_5POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT), SPEAKER_7POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER), SPEAKER_5POINT1_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT), SPEAKER_7POINT1_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT), }; //@todo verify mask values inline int ComputeChannelMask(const size_t channels) { switch (channels) { case 1: return SPEAKER_MONO; case 2: return SPEAKER_STEREO; case 3: return SPEAKER_2POINT1; case 4: return SPEAKER_QUAD; case 5: return SPEAKER_4POINT1; case 6: return SPEAKER_5POINT1; default: return -1; } } struct WavDecoder : public nqr::BaseDecoder { WavDecoder() {} virtual ~WavDecoder() {} virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override; virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector & memory) override; virtual std::vector GetSupportedFileExtensions() override; }; } // end namespace nqr #endif ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5941823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/Includes/libnyquist/WavEncoder.h0000644000000000000000000001004114735300037024301 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef WAVE_ENCODER_H #define WAVE_ENCODER_H #include "libnyquist/Common.h" #include "libnyquist/WavDecoder.h" #include "libnyquist/RiffUtils.h" namespace nqr { // This is a naieve implementation of a resampling filter where a lerp is used as a bad low-pass. // It very far from the ideal case and should be used with caution (or not at all) on signals that matter. // It is included here to upsample 44.1k to 48k for the purposes of microphone input => Opus, where the the // nominal frequencies of speech are particularly far from Nyquist. static inline void linear_resample(const double rate, const std::vector & input, std::vector & output, size_t samplesToProcess) { double virtualReadIndex = 0; double a, b, i, sample; uint32_t n = (uint32_t) (samplesToProcess - 1); while (n--) { uint32_t readIndex = static_cast(virtualReadIndex); i = virtualReadIndex - readIndex; a = input[readIndex + 0]; b = input[readIndex + 1]; sample = (1.0 - i) * a + i * b; // linear interpolate output.push_back((float) sample); virtualReadIndex += rate; } } static inline double sample_hermite_4p_3o(double x, double * y) { static double c0, c1, c2, c3; c0 = y[1]; c1 = (1.0/2.0)*(y[2]-y[0]); c2 = (y[0] - (5.0/2.0)*y[1]) + (2.0*y[2] - (1.0/2.0)*y[3]); c3 = (1.0/2.0)*(y[3]-y[0]) + (3.0/2.0)*(y[1]-y[2]); return ((c3*x+c2)*x+c1)*x+c0; } static inline void hermite_resample(const double rate, const std::vector & input, std::vector & output, size_t samplesToProcess) { double virtualReadIndex = 1; double i, sample; uint32_t n = (uint32_t) (samplesToProcess - 1); while (n--) { uint32_t readIndex = static_cast(virtualReadIndex); i = virtualReadIndex - readIndex; double samps[4] = {input[readIndex - 1], input[readIndex], input[readIndex + 1], input[readIndex + 2]}; sample = sample_hermite_4p_3o(i, samps); // cubic hermite interpolate over 4 samples output.push_back((float) sample); virtualReadIndex += rate; } } enum EncoderError { NoError, InsufficientSampleData, FileIOError, UnsupportedSamplerate, UnsupportedChannelConfiguration, UnsupportedBitdepth, UnsupportedChannelMix, BufferTooBig, }; // A simplistic encoder that takes a blob of data, conforms it to the user's // EncoderParams preference, and writes to disk. Be warned, does not support resampling! // @todo support dithering, samplerate conversion, etc. struct WavEncoder { // Assume data adheres to EncoderParams, except for bit depth and fmt static int WriteFile(const EncoderParams p, const AudioData * d, const std::string & path); }; struct OggOpusEncoder { static int WriteFile(const EncoderParams p, const AudioData * d, const std::string & path); }; } // end namespace nqr #endif ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5941823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/PremakePlugin.lua0000644000000000000000000000315314735300037021376 0ustar00if not _AK_PREMAKE then error('You must use the custom Premake5 scripts by adding the following parameter: --scripts="Scripts\\Premake"', 1) end local Plugin = {} Plugin.name = "{{name}}" Plugin.factoryheader = "../SoundEnginePlugin/{{name}}{{plugin_type}}Factory.h" Plugin.sdk = {} Plugin.sdk.static = {} Plugin.sdk.shared = {} Plugin.authoring = {} Plugin.sdk.static.includedirs = {} Plugin.sdk.static.files = { "**.cpp", "**.h", "**.hpp", "**.c", } Plugin.sdk.static.excludes = { "{{name}}{{plugin_type}}Shared.cpp" } Plugin.sdk.static.links = {} Plugin.sdk.static.libsuffix = "{{plugin_type}}" Plugin.sdk.static.libdirs = {} Plugin.sdk.static.defines = {} Plugin.sdk.static.custom = function() filter "system:Windows" systemversion "10.0.19041.0" end Plugin.sdk.shared.includedirs = {} Plugin.sdk.shared.files = { "{{name}}{{plugin_type}}Shared.cpp", "{{name}}{{plugin_type}}Factory.h", } Plugin.sdk.shared.excludes = {} Plugin.sdk.shared.links = {} Plugin.sdk.shared.libdirs = {} Plugin.sdk.shared.defines = {} Plugin.sdk.shared.custom = function() filter "system:Windows" systemversion "10.0.19041.0" end Plugin.authoring.includedirs = { "../Includes", path.join(_AK_SDK_ROOT, "samples/Common/") } Plugin.authoring.files = { "**.cpp", "**.h", "**.hpp", "**.c", "{{name}}.def", "{{name}}.xml", "{{name}}.rc", } Plugin.authoring.excludes = {} Plugin.authoring.links = {} Plugin.authoring.libdirs = {} Plugin.authoring.defines = {} Plugin.authoring.custom = function() filter "system:Windows" systemversion "10.0.19041.0" end return Plugin ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.267823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/SoundEnginePlugin/{{name}}{{plugin_type}}.cpp0000644000000000000000000002622214735300474027400 0ustar00{%- set register_send_hook = out_params|length > 0 or out_events|length > 0 -%} {{copyright}} #include "{{name}}{{plugin_type}}.h" #include "{{name}}{{plugin_type}}Params.h" #include "../{{name}}Config.h" #include "Heavy/Heavy_{{name}}.hpp" #include #include namespace {{name}}_Private { typedef struct WavHeader { uint32_t ChunkID; // 0 uint32_t ChunkSize; // 4 uint32_t Format; // 8 uint32_t Subchunk1ID; // 12 uint32_t Subchunk1Size; // 16 uint16_t AudioFormat; // 20 uint16_t NumChannels; // 22 uint32_t SampleRate; // 24 uint32_t ByteRate; // 28 uint16_t BlockAlign; // 32 uint16_t BitsPerSample; // 34 uint32_t Subchunk2ID; // 36 uint32_t Subchunk2Size; // 40 uint32_t Subchunk2Data; // 44 uint32_t Subchunk3ID; // 48 uint32_t Subchunk3Size; // 52 // data -> 56 } WavHeader; void LoadPluginMediaToHeavyTable(AK::IAkPluginContextBase* in_pWwiseCtx, HeavyContextInterface* in_pHeavyCtx, uint32_t in_uMediaIndex, uint32_t in_uTableHash, uint32_t in_uTableSizeReceiverHash) { AkUInt8* pPluginData = NULL; AkUInt32 uPluginDataSize; in_pWwiseCtx->GetPluginMedia(in_uMediaIndex, pPluginData, uPluginDataSize); // retrieve stored plugin data if (pPluginData != NULL) { // determine wav header format WavHeader h; hv_memcpy(&h, pPluginData, sizeof(WavHeader)); uint32_t offsetBytes = 0; const uint32_t dataID = 0x61746164; // 'data' const uint32_t factID = 0x74636166; // 'fact' if (h.Subchunk2ID == dataID) { offsetBytes = 44; } else if (h.Subchunk2ID == factID && h.Subchunk3ID == dataID) { offsetBytes = 56; } uint32_t newSizeBytes = uPluginDataSize - offsetBytes; if (offsetBytes > 0 && newSizeBytes > 0) { // adjust table size const uint32_t numSamples = newSizeBytes * 8 / h.BitsPerSample; in_pHeavyCtx->setLengthForTable(in_uTableHash, numSamples); float* buffer = in_pHeavyCtx->getBufferForTable(in_uTableHash); if (buffer != NULL && newSizeBytes > 0) { // copy contents and notify respective receiver hv_memcpy(buffer, (float*)(pPluginData + offsetBytes), newSizeBytes); in_pHeavyCtx->sendFloatToReceiver(in_uTableSizeReceiverHash, (float)numSamples); } } } } static void SetOutRTPC(AK::IAkPluginContextBase* in_pCtx, const char* in_szRtpcName, const uint32_t& in_uNameLen, const float& in_fValue) { AK::FNVHash32 HashFunc; const uint32_t RtpcID = HashFunc.Compute(in_szRtpcName, sizeof(char) * in_uNameLen); const AkGameObjectID ObjectID = in_pCtx->GetGameObjectInfo()->GetGameObjectID(); in_pCtx->GlobalContext()->SetRTPCValue(RtpcID, in_fValue, ObjectID, 0, AkCurveInterpolation_Linear, false); } {% if out_events|length > 0 %} static void PostOutEvent({{name}}{{plugin_type}}* in_pPlugin, const char* in_szEventName, const uint32_t& in_uNameLen) { AK::FNVHash32 HashFunc; const uint32_t EventID = HashFunc.Compute(in_szEventName, sizeof(char) * in_uNameLen); in_pPlugin->m_EventQueue.Enqueue(EventID); } {% endif %} static void OnHeavyPrint(HeavyContextInterface* in_pHeavyCtx, const char* in_szPrintName, const char* in_szMessage, const HvMessage* in_pHvMessage) { auto* pPlugin = reinterpret_cast<{{name}}{{plugin_type}}*>(in_pHeavyCtx->getUserData()); pPlugin->m_pWwiseCtx->PostMonitorMessage(in_szMessage, AK::Monitor::ErrorLevel::ErrorLevel_Message); } {% if register_send_hook %} static void OnSendMessageCallback(HeavyContextInterface *in_pHeavyCtx, const char *in_szSendName, uint32_t in_uSendHash, const HvMessage *in_pHvMessage) { auto* pPlugin = reinterpret_cast<{{name}}{{plugin_type}}*>(in_pHeavyCtx->getUserData()); if (pPlugin != nullptr && (hv_msg_isFloat(in_pHvMessage, 0) || hv_msg_isBang(in_pHvMessage, 0))) { switch (in_uSendHash) { {%- for k, v in out_params %} case {{v.hash}}: SetOutRTPC(pPlugin->m_pWwiseCtx, "{{k|lower}}", {{k|length}}, hv_msg_getFloat(in_pHvMessage, 0)); break; {%- endfor %} {%- for k, v in out_events %} case {{v.hash}}: PostOutEvent(pPlugin, "{{k|lower}}", {{k|length}}); break; {%- endfor %} default: return; } } } {%- endif %} {% if out_events|length > 0 %} static void OnGlobalCallback(AK::IAkGlobalPluginContext* in_pContext, AkGlobalCallbackLocation in_eLocation, void* in_pCookie) { if (in_eLocation != AkGlobalCallbackLocation_BeginRender) return; auto* pPlugin = reinterpret_cast<{{name}}{{plugin_type}}*>(in_pCookie); if (!pPlugin) return; const AkGameObjectID GameObjectID = pPlugin->m_pWwiseCtx->GetGameObjectInfo()->GetGameObjectID(); uint32_t uEventID = 0; while (pPlugin->m_EventQueue.Dequeue(uEventID)) { in_pContext->PostEventSync(uEventID, GameObjectID); } } {%- endif %} } AK::IAkPlugin* Create{{name}}{{plugin_type}}(AK::IAkPluginMemAlloc* in_pAllocator) { return AK_PLUGIN_NEW(in_pAllocator, {{name}}{{plugin_type}}()); } AK::IAkPluginParam* Create{{name}}{{plugin_type}}Params(AK::IAkPluginMemAlloc* in_pAllocator) { return AK_PLUGIN_NEW(in_pAllocator, {{name}}{{plugin_type}}Params()); } AK_IMPLEMENT_PLUGIN_FACTORY({{name}}{{plugin_type}}, {{"AkPluginTypeSource" if is_source else "AkPluginTypeEffect"}}, {{name}}Config::CompanyID, {{name}}Config::PluginID) {{name}}{{plugin_type}}::{{name}}{{plugin_type}}() : m_pWwiseCtx(nullptr) , m_pHeavyCtx(nullptr) , m_pParams(nullptr) , m_uSampleRate(0) { } AKRESULT {{name}}{{plugin_type}}::Init(AK::IAkPluginMemAlloc* in_pAllocator, ContextType* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) { using namespace {{name}}_Private; m_pParams = ({{name}}{{plugin_type}}Params*)in_pParams; m_pWwiseCtx = in_pContext; m_uSampleRate = in_rFormat.uSampleRate; // Initialise Heavy context m_pHeavyCtx = AK_PLUGIN_NEW(in_pAllocator, Heavy_{{name}}((double) m_uSampleRate, {{pool_sizes_kb.internal}}, {{pool_sizes_kb.inputQueue}}, {{pool_sizes_kb.outputQueue}})); m_pHeavyCtx->setUserData(this); {%- if register_send_hook %} m_pHeavyCtx->setSendHook(&OnSendMessageCallback); {% endif %} #ifndef AK_OPTIMIZED m_pHeavyCtx->setPrintHook(&OnHeavyPrint); #endif {% if is_source %} // Notify pipeline of chosen output format change. in_rFormat.channelConfig.SetStandard({{channel_config}}); {% if num_output_channels > 0 %} if (in_rFormat.GetNumChannels() != hv_getNumOutputChannels(m_pHeavyCtx)) { return AK_UnsupportedChannelConfig; } {% endif %} {% else %} {% if num_output_channels > 2 %} // Multi-channel plugins have string channel configuration requirementkk if (in_rFormat.channelConfig.uChannelMask != {{channel_config}}) { m_pWwiseCtx->PostMonitorMessage("{{name}} only supports the following channel configuration {{channel_config}}", AK::Monitor::ErrorLevel_Error); return AK_UnsupportedChannelConfig; } {% else %} if (in_rFormat.GetNumChannels() > 2) { m_pWwiseCtx->PostMonitorMessage("{{name}} only supports one and two channel bus configurations", AK::Monitor::ErrorLevel_Error); return AK_UnsupportedChannelConfig; } {% endif %} {% endif %} {%- for k, v in parameters %} hv_sendFloatToReceiver(m_pHeavyCtx, Heavy_{{name}}::Parameter::In::{{k|upper}}, m_pParams->RTPC.{{k}}); {%- endfor %} {% if out_events|length > 0 %} m_EventQueue.Init(4); m_pWwiseCtx->GlobalContext()->RegisterGlobalCallback( {{"AkPluginTypeSource" if is_source else "AkPluginTypeEffect"}}, {{name}}Config::CompanyID, {{name}}Config::PluginID, &OnGlobalCallback, AkGlobalCallbackLocation_BeginRender, this); {%- endif %} {% if tables|length > 0 %} // Initialise tables with media {%- for k, v in tables %} LoadPluginMediaToHeavyTable(m_pWwiseCtx, m_pHeavyCtx, {{loop.index-1}}, {{v.hash}}, hv_stringToHash("setTableSize-{{v.display}}")); // table '{{v.display}}' {%- endfor %} {% endif %} AK_PERF_RECORDING_RESET(); return AK_Success; } AKRESULT {{name}}{{plugin_type}}::Term(AK::IAkPluginMemAlloc* in_pAllocator) { using namespace {{name}}_Private; {% if out_events|length > 0 %} uint32_t EventID = 0; while (m_EventQueue.Dequeue(EventID)) { // the queue must be empty before termination } m_EventQueue.Term(); m_pWwiseCtx->GlobalContext()->UnregisterGlobalCallback(OnGlobalCallback, AkGlobalCallbackLocation_BeginRender); {% endif %} AK_PLUGIN_DELETE(in_pAllocator, m_pHeavyCtx); AK_PLUGIN_DELETE(in_pAllocator, this); return AK_Success; } AKRESULT {{name}}{{plugin_type}}::Reset() { return AK_Success; } AKRESULT {{name}}{{plugin_type}}::GetPluginInfo(AkPluginInfo& out_rPluginInfo) { out_rPluginInfo.eType = {{"AkPluginTypeSource" if is_source else "AkPluginTypeEffect"}}; out_rPluginInfo.bIsInPlace = true; out_rPluginInfo.bCanProcessObjects = false; out_rPluginInfo.uBuildVersion = AK_WWISESDK_VERSION_COMBINED; return AK_Success; } void {{name}}{{plugin_type}}::Execute(AkAudioBuffer* io_pBuffer) { AK_PERF_RECORDING_START("{{name}}{{plugin_type}}", 25, 30); // Retrieve RTPC values and send in as a message to context {%- for k, v in parameters %} if (m_pParams->m_paramChangeHandler.HasChanged({{loop.index-1}})) { hv_sendFloatToReceiver(m_pHeavyCtx, Heavy_{{name}}::Parameter::In::{{k|upper}}, m_pParams->RTPC.{{k}}); m_pParams->m_paramChangeHandler.ResetParamChange({{loop.index-1}}); } {%- endfor %} {% if not is_source %} // zero-pad the rest of the buffer in case the numFrames is not a multiple of 4 io_pBuffer->ZeroPadToMaxFrames(); {%- endif %} // Calculate num frames to process and retrieve buffer AkUInt16 numFramesToProcess = io_pBuffer->MaxFrames(); float *pBuffer = (float *) io_pBuffer->GetChannel(0); {% if is_source %} m_pHeavyCtx->processInline(nullptr, pBuffer, numFramesToProcess); io_pBuffer->eState = AK_DataReady; {% else %} // Check for channel configuration mismatch if (io_pBuffer->NumChannels() == 1 && ((m_pHeavyCtx->getNumInputChannels() == 2) || (m_pHeavyCtx->getNumOutputChannels() == 2))) { float *pTempBuffer[2] = { pBuffer, pBuffer }; m_pHeavyCtx->process(pTempBuffer, pTempBuffer, numFramesToProcess); } else { m_pHeavyCtx->processInline(pBuffer, pBuffer, numFramesToProcess); } {% endif %} {% if num_output_channels > 0 %} io_pBuffer->uValidFrames = numFramesToProcess; {% else %} // Edge case - a control-only plugin was built, outputting silence io_pBuffer->ZeroPadToMaxFrames(); {% endif %} AK_PERF_RECORDING_STOP("{{name}}{{plugin_type}}", 25, 30); } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5951824 hvcc-0.13.3/hvcc/generators/c2wwise/templates/SoundEnginePlugin/{{name}}{{plugin_type}}.h0000644000000000000000000000421414735300037027035 0ustar00{{copyright}} #ifndef {{name}}{{plugin_type}}_H #define {{name}}{{plugin_type}}_H #include {%- if out_events|length > 0 %} #include {%- endif %} class HeavyContextInterface; struct {{name}}{{plugin_type}}Params; class {{name}}{{plugin_type}} : public {{"AK::IAkSourcePlugin" if is_source else "AK::IAkInPlaceEffectPlugin"}} { public: using ContextType = {{"AK::IAkSourcePluginContext" if is_source else "AK::IAkEffectPluginContext"}}; {% if out_events|length > 0 %} // Note(ech): AkFifoQueue requires an allocator from AkMemoryMgr at compile time which we don't link against // We need a queue implementation that can inject AK::IAkPluginMemAlloc at runtime to avoid using default OS allocator struct SysAlloc { static AkForceInline void* Alloc(size_t in_uSize) { return malloc(in_uSize); } static AkForceInline void Free(void* in_pAddress) { free(in_pAddress); } }; {%- endif %} {{name}}{{plugin_type}}(); ~{{name}}{{plugin_type}}() = default; AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, ContextType* in_pContext, AK::IAkPluginParam* in_pParams, AkAudioFormat& in_rFormat) override; AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; AKRESULT Reset() override; AKRESULT GetPluginInfo(AkPluginInfo& out_rPluginInfo) override; void Execute(AkAudioBuffer* io_pBuffer) override; {%- if is_source %} virtual AkReal32 GetDuration() const override { return 0.f; } virtual AkReal32 GetEnvelope() const override { return 1.f; } virtual AKRESULT StopLooping() override { return AK_Success; } {%- else %} AKRESULT TimeSkip(AkUInt32 in_uFrames) override { return AK_Success; } {%- endif %} {% if out_events|length > 0 %} // Holds event IDs until global callback AkFifoQueue m_EventQueue; {%- endif %} AK::IAkPluginContextBase* m_pWwiseCtx; HeavyContextInterface *m_pHeavyCtx; // Main Heavy patch context {{name}}{{plugin_type}}Params* m_pParams; uint32_t m_uSampleRate; }; #endif // {{name}}{{plugin_type}}_H ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5951824 hvcc-0.13.3/hvcc/generators/c2wwise/templates/SoundEnginePlugin/{{name}}{{plugin_type}}Factory.h0000644000000000000000000000027514735300037030370 0ustar00{{copyright}} #ifndef {{name}}{{plugin_type}}Factory_H #define {{name}}{{plugin_type}}Factory_H AK_STATIC_LINK_PLUGIN({{name}}{{plugin_type}}) #endif // {{name}}{{plugin_type}}Factory_H ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5951824 hvcc-0.13.3/hvcc/generators/c2wwise/templates/SoundEnginePlugin/{{name}}{{plugin_type}}Params.cpp0000644000000000000000000000436414735300037030542 0ustar00{{copyright}} #include "{{name}}{{plugin_type}}Params.h" #include {{name}}{{plugin_type}}Params::{{name}}{{plugin_type}}Params(const {{name}}{{plugin_type}}Params& in_rParams) { {% if parameters|length > 0 %} RTPC = in_rParams.RTPC; m_paramChangeHandler.SetAllParamChanges(); {% endif %} } AK::IAkPluginParam* {{name}}{{plugin_type}}Params::Clone(AK::IAkPluginMemAlloc* in_pAllocator) { return AK_PLUGIN_NEW(in_pAllocator, {{name}}{{plugin_type}}Params(*this)); } AKRESULT {{name}}{{plugin_type}}Params::Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) { if (in_ulBlockSize == 0) { {%- for k, v in parameters %} RTPC.{{k}} = {{v.attributes.default}}; {%- endfor %} {% if parameters|length > 0 %} m_paramChangeHandler.SetAllParamChanges(); {% endif %} return AK_Success; } return SetParamsBlock(in_pParamsBlock, in_ulBlockSize); } AKRESULT {{name}}{{plugin_type}}Params::Term(AK::IAkPluginMemAlloc* in_pAllocator) { AK_PLUGIN_DELETE(in_pAllocator, this); return AK_Success; } AKRESULT {{name}}{{plugin_type}}Params::SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) { AKRESULT eResult = AK_Success; AkUInt8* pParamsBlock = (AkUInt8*)in_pParamsBlock; {%- for k, v in parameters %} RTPC.{{k}} = READBANKDATA(AkReal32, pParamsBlock, in_ulBlockSize); {%- endfor %} CHECKBANKDATASIZE(in_ulBlockSize, eResult); {% if parameters|length > 0 %} m_paramChangeHandler.SetAllParamChanges(); {%- endif %} return eResult; } AKRESULT {{name}}{{plugin_type}}Params::SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) { AKRESULT eResult = AK_Success; {% if parameters|length > 0 %} switch (in_paramID) { {%- for k, v in parameters %} case {{loop.index-1}}: { const float fNewValue = *((AkReal32*)in_pValue); const bool bChanged = RTPC.{{k}} != fNewValue; RTPC.{{k}} = fNewValue; if (bChanged) m_paramChangeHandler.SetParamChange({{loop.index-1}}); } break; {%- endfor %} default: eResult = AK_InvalidParameter; break; } {% endif %} return eResult; } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5951824 hvcc-0.13.3/hvcc/generators/c2wwise/templates/SoundEnginePlugin/{{name}}{{plugin_type}}Params.h0000644000000000000000000000244014735300037030200 0ustar00{{copyright}} {# force new line #} #ifndef {{name}}{{plugin_type}}Params_H #define {{name}}{{plugin_type}}Params_H #include #include {% if parameters|length > 0 %} struct {{name}}RTPCParams { {%- for k, v in parameters %} AkReal32 {{k}} = {{v.attributes.default}}; {%- endfor %} }; {% endif %} struct {{name}}{{plugin_type}}Params : public AK::IAkPluginParam { {{name}}{{plugin_type}}Params() = default; {{name}}{{plugin_type}}Params(const {{name}}{{plugin_type}}Params& in_rParams); ~{{name}}{{plugin_type}}Params() = default; IAkPluginParam* Clone(AK::IAkPluginMemAlloc* in_pAllocator) override; AKRESULT Init(AK::IAkPluginMemAlloc* in_pAllocator, const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; AKRESULT Term(AK::IAkPluginMemAlloc* in_pAllocator) override; AKRESULT SetParamsBlock(const void* in_pParamsBlock, AkUInt32 in_ulBlockSize) override; AKRESULT SetParam(AkPluginParamID in_paramID, const void* in_pValue, AkUInt32 in_ulParamSize) override; {% if parameters|length > 0 %} AK::AkFXParameterChangeHandler<{{parameters|length}}> m_paramChangeHandler; {{name}}RTPCParams RTPC; {% endif %} }; #endif // {{name}}{{plugin_type}}Params_H ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5951824 hvcc-0.13.3/hvcc/generators/c2wwise/templates/SoundEnginePlugin/{{name}}{{plugin_type}}Shared.cpp0000644000000000000000000000030414735300037030513 0ustar00{{copyright}} #include #include "{{name}}{{plugin_type}}Factory.h" #include DEFINEDUMMYASSERTHOOK; DEFINE_PLUGIN_REGISTER_HOOK; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5951824 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/Win32/stdafx.h0000644000000000000000000000427214735300037022754 0ustar00/** * Copyright (c) 2015 Enzien Audio, Ltd. * * 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. * * 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. */ #ifndef _HV_WWISE_STDAFX_H_ #define _HV_WWISE_STDAFX_H_ #ifndef VC_EXTRALEAN #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers #endif #include #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit #include // MFC core and standard components #include // MFC extensions #ifndef _AFX_NO_OLE_SUPPORT #include // MFC OLE classes #include // MFC OLE dialog classes #include // MFC Automation classes #endif // _AFX_NO_OLE_SUPPORT #ifndef _AFX_NO_DB_SUPPORT #include // MFC ODBC database classes #endif // _AFX_NO_DB_SUPPORT #ifndef _AFX_NO_DAO_SUPPORT #include // MFC DAO database classes #endif // _AFX_NO_DAO_SUPPORT #include // MFC support for Internet Explorer 4 Common Controls #ifndef _AFX_NO_AFXCMN_SUPPORT #include // MFC support for Windows Common Controls #endif // _AFX_NO_AFXCMN_SUPPORT #include "shlwapi.h" #endif // _HV_WWISE_STDAFX_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5951824 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/Win32/{{name}}PluginGUI.cpp0000644000000000000000000001217214735300037025440 0ustar00{{copyright}} #include "{{name}}PluginGUI.h" #include "../resource.h" #include "stdafx.h" using namespace AK::Wwise::Plugin; namespace {{name}}_Private { static bool SaveAudioFileToTableId(ObjectMedia& in_pObjectMedia, const uint32_t& in_uTableId) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); static TCHAR BASED_CODE szFilter[] = _T("Audio Files (*.wav)|*.wav|"); CFileDialog Dialog(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter); if (Dialog.DoModal() == IDOK) { const bool bOk = in_pObjectMedia.SetMediaSource(Dialog.GetPathName(), in_uTableId, true); if (bOk) { in_pObjectMedia.InvalidateMediaSource(in_uTableId); return true; } } return false; }; } {{name}}PluginGUI::{{name}}PluginGUI() : m_hwndPropView(nullptr) , m_hwndObjPane(nullptr) , m_uiBigDialogID(IDD_HV_{{name|upper}}_PLUGIN_BIG) , m_uiSmallDialogID(IDD_HV_{{name|upper}}_PLUGIN_SMALL) {%- if (parameters|length + sends|length + tables|length) > 10 %} , m_iScrollPos(0) {% endif -%} { } bool {{name}}PluginGUI::GetDialog(eDialog in_eDialog, uint32_t& out_uiDialogID, PopulateTableItem*& out_pTable) const { switch (in_eDialog) { case SettingsDialog: out_uiDialogID = m_uiBigDialogID; out_pTable = nullptr; return true; case ContentsEditorDialog: out_uiDialogID = m_uiSmallDialogID; out_pTable = nullptr; return true; } return false; } bool {{name}}PluginGUI::WindowProc(eDialog in_eDialog, HWND in_hWnd, uint32_t in_message, WPARAM in_wParam, LPARAM in_lParam, LRESULT& out_lResult) { using namespace {{name}}_Private; switch (in_message) { case WM_INITDIALOG: { if (in_eDialog == ContentsEditorDialog) { m_hwndObjPane = in_hWnd; } else if (in_eDialog == SettingsDialog) { m_hwndPropView = in_hWnd; {% if (parameters|length + sends|length + tables|length) > 10 -%} RECT rect; if (GetClientRect(in_hWnd, &rect)) { // Create Scrollbar CreateWindowEx(0, L"SCROLLBAR", (PTSTR) NULL, WS_CHILD | WS_VISIBLE | SBS_VERT | SBS_RIGHTALIGN, rect.left, rect.top, rect.right, rect.bottom - GetSystemMetrics(SM_CYVTHUMB), // thumbwidth in_hWnd, (HMENU) NULL, GetResourceHandle(), (PVOID) NULL); SCROLLINFO si = {0}; si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_ALL; si.nMin = 0; si.nMax = 2500; si.nPage = (rect.bottom - rect.top); si.nPos = 0; si.nTrackPos = 0; SetScrollInfo(in_hWnd, SB_VERT, &si, true); m_iScrollPos = 0; } {%- endif %} } break; } {% if (parameters|length + sends|length + tables|length) > 10 -%} case WM_SIZE: { break; } case WM_VSCROLL: { auto action = LOWORD(in_wParam); HWND hScroll = (HWND) in_lParam; int pos = -1; if (action == SB_THUMBPOSITION || action == SB_THUMBTRACK) { pos = HIWORD(in_wParam); } else if (action == SB_LINEDOWN) { pos = m_iScrollPos + 30; } else if (action == SB_LINEUP) { pos = m_iScrollPos - 30; } if (pos == -1) { break; } SCROLLINFO si = {0}; si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_POS; si.nPos = pos; si.nTrackPos = 0; SetScrollInfo(in_hWnd, SB_VERT, &si, true); GetScrollInfo(in_hWnd, SB_VERT, &si); pos = si.nPos; POINT pt; pt.x = 0; pt.y = pos - m_iScrollPos; auto hdc = GetDC(in_hWnd); LPtoDP(hdc, &pt, 1); ReleaseDC(in_hWnd, hdc); ScrollWindow(in_hWnd, 0, -pt.y, NULL, NULL); m_iScrollPos = pos; break; } {%- endif %} case WM_DESTROY: { if (in_eDialog == SettingsDialog) { m_hwndPropView = nullptr; } else if ( in_eDialog == ContentsEditorDialog ) { m_hwndObjPane = nullptr; } break; } // Catch window command actions (regardless if it is object pane or property // view) to enable/disable controls case WM_COMMAND: { {%- if tables|length > 0 %} // catch button clicks switch (HIWORD(in_wParam)) { case BN_CLICKED: { switch (LOWORD(in_wParam)) { {%- for k, v in tables %} case IDC_BUTTON_HV_TABLE_{{k|upper}}: return SaveAudioFileToTableId(m_objectMedia, {{loop.index-1}}); // {{v.display}} {%- endfor %} default: break; } } default: break; } {%- endif %} break; } case WM_ENABLE: { // Enable/Disable all child controls HWND hWnd = ::GetWindow(in_hWnd, GW_CHILD); while(hWnd) { ::EnableWindow(hWnd, in_wParam == TRUE); hWnd = ::GetWindow(hWnd, GW_HWNDNEXT); } return true; } } out_lResult = 0; return false; } ADD_AUDIOPLUGIN_CLASS_TO_CONTAINER( {{name}}, {{name}}PluginGUI, {{name}}{{plugin_type}} ); ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5951824 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/Win32/{{name}}PluginGUI.h0000644000000000000000000000151414735300037025103 0ustar00{{copyright}} #pragma once #include "../{{name}}Plugin.h" class {{name}}PluginGUI final : public AK::Wwise::Plugin::PluginMFCWindows<> , public AK::Wwise::Plugin::GUIWindows , public AK::Wwise::Plugin::RequestObjectMedia { public: {{name}}PluginGUI(); bool GetDialog(AK::Wwise::Plugin::eDialog in_eDialog, uint32_t& out_uiDialogID, AK::Wwise::Plugin::PopulateTableItem*& out_pTable) const override; bool WindowProc(AK::Wwise::Plugin::eDialog in_eDialog, HWND in_hWnd, uint32_t in_message, WPARAM in_wParam, LPARAM in_lParam, LRESULT& out_lResult ) override; private: HWND m_hwndPropView; HWND m_hwndObjPane; const uint32_t m_uiBigDialogID; const uint32_t m_uiSmallDialogID; {% if (parameters|length + sends|length + tables|length) > 10 -%} int32_t m_iScrollPos; {% endif -%} }; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5951824 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/libnyquist/AudioDecoder.cpp0000644000000000000000000001077114735300037025647 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libnyquist/AudioDecoder.h" #include "libnyquist/WavDecoder.h" //#include "WavPackDecoder.h" //#include "FlacDecoder.h" //#include "VorbisDecoder.h" //#include "OpusDecoder.h" //#include "CafDecoder.h" //#include "MusepackDecoder.h" //#include "ModplugDecoder.h" using namespace nqr; NyquistIO::NyquistIO() { BuildDecoderTable(); } NyquistIO::~NyquistIO() { } void NyquistIO::Load(AudioData * data, const std::string & path) { if (IsFileSupported(path)) { if (decoderTable.size()) { auto fileExtension = ParsePathForExtension(path); auto decoder = GetDecoderForExtension(fileExtension); try { decoder->LoadFromPath(data, path); } catch (const std::exception & e) { std::cerr << "Caught internal exception: " << e.what() << std::endl; } } else throw std::runtime_error("No available decoders."); } else { throw UnsupportedExtensionEx(); } } void NyquistIO::Load(AudioData * data, std::string extension, const std::vector & buffer) { if (decoderTable.find(extension) == decoderTable.end()) { throw UnsupportedExtensionEx(); } if (decoderTable.size()) { auto decoder = GetDecoderForExtension(extension); try { decoder->LoadFromBuffer(data, buffer); } catch (const std::exception & e) { std::cerr << "Caught internal exception: " << e.what() << std::endl; } } else { throw std::runtime_error("No available decoders."); } } bool NyquistIO::IsFileSupported(const std::string path) const { auto fileExtension = ParsePathForExtension(path); if (decoderTable.find(fileExtension) == decoderTable.end()) { return false; } else { return true; } } std::string NyquistIO::ParsePathForExtension(const std::string & path) const { if (path.find_last_of(".") != std::string::npos) return path.substr(path.find_last_of(".") + 1); return std::string(""); } std::shared_ptr NyquistIO::GetDecoderForExtension(const std::string ext) { if (decoderTable.size()) { return decoderTable[ext]; } else throw std::runtime_error("No available decoders."); return nullptr; } void NyquistIO::AddDecoderToTable(std::shared_ptr decoder) { auto supportedExtensions = decoder->GetSupportedFileExtensions(); for (const auto ext : supportedExtensions) { if (decoderTable.count(ext) >= 1) throw std::runtime_error("decoder already exists for extension."); decoderTable.insert(DecoderPair(ext, decoder)); } } void NyquistIO::BuildDecoderTable() { AddDecoderToTable(std::make_shared()); //AddDecoderToTable(std::make_shared()); //AddDecoderToTable(std::make_shared()); //AddDecoderToTable(std::make_shared()); //AddDecoderToTable(std::make_shared()); //AddDecoderToTable(std::make_shared()); //AddDecoderToTable(std::make_shared()); //AddDecoderToTable(std::make_shared()); }././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5951824 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/libnyquist/Common.cpp0000644000000000000000000001626714735300037024556 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libnyquist/Common.h" using namespace nqr; NyquistFileBuffer nqr::ReadFile(std::string pathToFile) { //std::cout << "[Debug] Open: " << pathToFile << std::endl; FILE * audioFile = fopen(pathToFile.c_str(), "rb"); if (!audioFile) { throw std::runtime_error("file not found"); } fseek(audioFile, 0, SEEK_END); size_t lengthInBytes = ftell(audioFile); fseek(audioFile, 0, SEEK_SET); // Allocate temporary buffer std::vector fileBuffer(lengthInBytes); size_t elementsRead = fread(fileBuffer.data(), 1, lengthInBytes, audioFile); if (elementsRead == 0 || fileBuffer.size() < 64) { throw std::runtime_error("error reading file or file too small"); } NyquistFileBuffer data = {std::move(fileBuffer), elementsRead}; fclose(audioFile); // Copy out to user return data; } // Src data is aligned to PCMFormat // @todo normalize? void nqr::ConvertToFloat32(float * dst, const uint8_t * src, const size_t N, PCMFormat f) { assert(f != PCM_END); if (f == PCM_U8) { const uint8_t * dataPtr = reinterpret_cast(src); for (size_t i = 0; i < N; ++i) dst[i] = uint8_to_float32(dataPtr[i]); } else if (f == PCM_S8) { const int8_t * dataPtr = reinterpret_cast(src); for (size_t i = 0; i < N; ++i) dst[i] = int8_to_float32(dataPtr[i]); } else if (f == PCM_16) { const int16_t * dataPtr = reinterpret_cast(src); for (size_t i = 0; i < N; ++i) dst[i] = int16_to_float32(Read16(dataPtr[i])); } else if (f == PCM_24) { const uint8_t * dataPtr = reinterpret_cast(src); size_t c = 0; for (size_t i = 0; i < N; ++i) { int32_t sample = Pack(dataPtr[c], dataPtr[c+1], dataPtr[c+2]); dst[i] = int24_to_float32(sample); // Packed types don't need addtional endian helpers c += 3; } } else if (f == PCM_32) { const int32_t * dataPtr = reinterpret_cast(src); for (size_t i = 0; i < N; ++i) dst[i] = int32_to_float32(Read32(dataPtr[i])); } //@todo add int64 format else if (f == PCM_FLT) { const float * dataPtr = reinterpret_cast(src); for (size_t i = 0; i < N; ++i) dst[i] = (float) Read32(dataPtr[i]); } else if (f == PCM_DBL) { const double * dataPtr = reinterpret_cast(src); for (size_t i = 0; i < N; ++i) dst[i] = (float) Read64(dataPtr[i]); } } // Src data is always aligned to 4 bytes (WavPack, primarily) void nqr::ConvertToFloat32(float * dst, const int32_t * src, const size_t N, PCMFormat f) { assert(f != PCM_END); if (f == PCM_16) { for (size_t i = 0; i < N; ++i) dst[i] = int16_to_float32(Read32(src[i])); } else if (f == PCM_24) { const uint8_t * dataPtr = reinterpret_cast(src); size_t c = 0; for (size_t i = 0; i < N; ++i) { int32_t sample = Pack(dataPtr[c], dataPtr[c+1], dataPtr[c+2]); dst[i] = int24_to_float32(sample); c += 4; // +4 for next 4 byte boundary } } else if (f == PCM_32) { for (size_t i = 0; i < N; ++i) dst[i] = int32_to_float32(Read32(src[i])); } } void nqr::ConvertToFloat32(float * dst, const int16_t * src, const size_t N, PCMFormat f) { assert(f != PCM_END); if (f == PCM_16) { for (size_t i = 0; i < N; ++i) dst[i] = int16_to_float32(Read16(src[i])); } } void nqr::ConvertFromFloat32(uint8_t * dst, const float * src, const size_t N, PCMFormat f, DitherType t) { assert(f != PCM_END); Dither dither(t); if (f == PCM_U8) { uint8_t * destPtr = reinterpret_cast(dst); for (size_t i = 0; i < N; ++i) destPtr[i] = (uint8_t) dither((float) lroundf(float32_to_uint8(src[i]))); } else if (f == PCM_S8) { int8_t * destPtr = reinterpret_cast(dst); for (size_t i = 0; i < N; ++i) destPtr[i] = (int8_t) dither((float) lroundf(float32_to_int8(src[i]))); } else if (f == PCM_16) { int16_t * destPtr = reinterpret_cast(dst); for (size_t i = 0; i < N; ++i) destPtr[i] =(int16_t) dither((float) lroundf(float32_to_int16(src[i]))); } else if (f == PCM_24) { uint8_t * destPtr = reinterpret_cast(dst); size_t c = 0; for (size_t i = 0; i < N; ++i) { int32_t sample = (int32_t) dither((float) lroundf(float32_to_int24(src[i]))); auto unpacked = Unpack(sample); // Handles endian swap destPtr[c] = unpacked[0]; destPtr[c+1] = unpacked[1]; destPtr[c+2] = unpacked[2]; c += 3; } } else if (f == PCM_32) { int32_t * destPtr = reinterpret_cast(dst); for (size_t i = 0; i < N; ++i) destPtr[i] = (int32_t) dither((float) lroundf(float32_to_int32(src[i]))); } } int nqr::GetFormatBitsPerSample(PCMFormat f) { switch(f) { case PCM_U8: case PCM_S8: return 8; case PCM_16: return 16; case PCM_24: return 24; case PCM_32: case PCM_FLT: return 32; case PCM_64: case PCM_DBL: return 64; default: return 0; } } PCMFormat nqr::MakeFormatForBits(int bits, bool floatingPt, bool isSigned) { switch(bits) { case 8: return (isSigned) ? PCM_S8 : PCM_U8; case 16: return PCM_16; case 24: return PCM_24; case 32: return (floatingPt) ? PCM_FLT : PCM_32; case 64: return (floatingPt) ? PCM_DBL : PCM_64; default: return PCM_END; } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5951824 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/libnyquist/RiffUtils.cpp0000644000000000000000000000520314735300037025221 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libnyquist/RiffUtils.h" using namespace nqr; ChunkHeaderInfo nqr::ScanForChunk(const std::vector & fileData, uint32_t chunkMarker) { // D[n] aligned to 16 bytes now const uint16_t * d = reinterpret_cast(fileData.data()); for (size_t i = 0; i < fileData.size() / sizeof(uint16_t); i++) { // This will be in machine endianess uint32_t m = Pack(Read16(d[i]), Read16(d[i+1])); if (m == chunkMarker) { uint32_t cSz = Pack(Read16(d[i+2]), Read16(d[i+3])); return {(uint32_t (i * sizeof(uint16_t))), cSz}; // return i in bytes to the start of the data } else continue; } return {0, 0}; }; WaveChunkHeader nqr::MakeWaveHeader(const EncoderParams param, const int sampleRate) { WaveChunkHeader header; int bitdepth = GetFormatBitsPerSample(param.targetFormat); header.fmt_id = GenerateChunkCode('f', 'm', 't', ' '); header.chunk_size = 16; header.format = (param.targetFormat <= PCMFormat::PCM_32) ? WaveFormatCode::FORMAT_PCM : WaveFormatCode::FORMAT_IEEE; header.channel_count = param.channelCount; header.sample_rate = sampleRate; header.data_rate = sampleRate * param.channelCount * (bitdepth / 8); header.frame_size = param.channelCount * (bitdepth / 8); header.bit_depth = bitdepth; return header; } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5961823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/libnyquist/WavDecoder.cpp0000644000000000000000000002044514735300037025342 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libnyquist/WavDecoder.h" #include "libnyquist/RiffUtils.h" #include "libnyquist/IMA4Util.h" using namespace nqr; ////////////////////// // Public Interface // ////////////////////// void WavDecoder::LoadFromPath(AudioData * data, const std::string & path) { auto fileBuffer = nqr::ReadFile(path); return LoadFromBuffer(data, fileBuffer.buffer); } void WavDecoder::LoadFromBuffer(AudioData * data, const std::vector & memory) { ////////////////////// // Read RIFF Header // ////////////////////// //@todo swap methods for rifx RiffChunkHeader riffHeader = {}; memcpy(&riffHeader, memory.data(), 12); // Files should be 2-byte aligned // @tofix: enforce this // bool usePaddingShort = ((riffHeader.file_size % sizeof(uint16_t)) == 1) ? true : false; // Check RIFF if (riffHeader.id_riff != GenerateChunkCode('R', 'I', 'F', 'F')) { // Check RIFX + FFIR if (riffHeader.id_riff == GenerateChunkCode('R', 'I', 'F', 'X') || riffHeader.id_riff == GenerateChunkCode('F', 'F', 'I', 'R')) { // We're not RIFF, and we don't match RIFX or FFIR either throw std::runtime_error("libnyquist doesn't support big endian files"); } else { throw std::runtime_error("bad RIFF/RIFX/FFIR file header"); } } if (riffHeader.id_wave != GenerateChunkCode('W', 'A', 'V', 'E')) throw std::runtime_error("bad WAVE header"); auto expectedSize = (memory.size() - riffHeader.file_size); if (expectedSize != sizeof(uint32_t) * 2) { throw std::runtime_error("declared size of file less than file size"); //@todo warning instead of runtime_error } ////////////////////// // Read WAVE Header // ////////////////////// auto WaveChunkInfo = ScanForChunk(memory, GenerateChunkCode('f', 'm', 't', ' ')); if (WaveChunkInfo.offset == 0) throw std::runtime_error("couldn't find fmt chunk"); assert(WaveChunkInfo.size == 16 || WaveChunkInfo.size == 18 || WaveChunkInfo.size == 20 || WaveChunkInfo.size == 40); WaveChunkHeader wavHeader = {}; memcpy(&wavHeader, memory.data() + WaveChunkInfo.offset, sizeof(WaveChunkHeader)); if (wavHeader.chunk_size < 16) throw std::runtime_error("format chunk too small"); //@todo validate wav header (sane sample rate, bit depth, etc) data->channelCount = wavHeader.channel_count; data->sampleRate = wavHeader.sample_rate; data->frameSize = wavHeader.frame_size; auto bit_depth = wavHeader.bit_depth; switch (bit_depth) { case 4: data->sourceFormat = PCMFormat::PCM_16; break; // for IMA ADPCM case 8: data->sourceFormat = PCMFormat::PCM_U8; break; case 16: data->sourceFormat = PCMFormat::PCM_16; break; case 24: data->sourceFormat = PCMFormat::PCM_24; break; case 32: data->sourceFormat = (wavHeader.format == WaveFormatCode::FORMAT_IEEE) ? PCMFormat::PCM_FLT : PCMFormat::PCM_32; break; case 64: data->sourceFormat = (wavHeader.format == WaveFormatCode::FORMAT_IEEE) ? PCMFormat::PCM_DBL : PCMFormat::PCM_64; break; } //std::cout << wavHeader << std::endl; bool scanForFact = false; bool grabExtensibleData = false; bool adpcmEncoded = false; if (wavHeader.format == WaveFormatCode::FORMAT_PCM) { } else if (wavHeader.format == WaveFormatCode::FORMAT_IEEE) { scanForFact = true; } else if (wavHeader.format == WaveFormatCode::FORMAT_IMA_ADPCM) { adpcmEncoded = true; scanForFact = true; } else if (wavHeader.format == WaveFormatCode::FORMAT_EXT) { // Used when (1) PCM data has more than 16 bits; (2) channels > 2; (3) bits/sample !== container size; (4) channel/speaker mapping specified //std::cout << "[format id] extended" << std::endl; scanForFact = true; grabExtensibleData = true; } else if (wavHeader.format == WaveFormatCode::FORMAT_UNKNOWN) { throw std::runtime_error("unknown wave format"); } //////////////////////////// // Read Additional Chunks // //////////////////////////// FactChunk factChunk; if (scanForFact) { auto FactChunkInfo = ScanForChunk(memory, GenerateChunkCode('f', 'a', 'c', 't')); if (FactChunkInfo.size) memcpy(&factChunk, memory.data() + FactChunkInfo.offset, sizeof(FactChunk)); } if (grabExtensibleData) { ExtensibleData extData = {}; memcpy(&extData, memory.data() + WaveChunkInfo.offset + sizeof(WaveChunkHeader), sizeof(ExtensibleData)); // extData can be compared against the multi-channel masks defined in the header // eg. extData.channel_mask == SPEAKER_5POINT1 } //@todo smpl chunk could be useful ///////////////////// // Read Bext Chunk // ///////////////////// auto BextChunkInfo = ScanForChunk(memory, GenerateChunkCode('b', 'e', 'x', 't')); BextChunk bextChunk = {}; if (BextChunkInfo.size) { memcpy(&bextChunk, memory.data() + BextChunkInfo.offset, sizeof(BextChunk)); } ///////////////////// // Read DATA Chunk // ///////////////////// auto DataChunkInfo = ScanForChunk(memory, GenerateChunkCode('d', 'a', 't', 'a')); if (DataChunkInfo.offset == 0) throw std::runtime_error("couldn't find data chunk"); DataChunkInfo.offset += 2 * sizeof(uint32_t); // ignore the header and size fields if (adpcmEncoded) { ADPCMState s; s.frame_size = wavHeader.frame_size; s.firstDataBlockByte = 0; s.dataSize = DataChunkInfo.size; s.currentByte = 0; s.inBuffer = const_cast(memory.data() + DataChunkInfo.offset); size_t totalSamples = (factChunk.sample_length * wavHeader.channel_count); // Samples per channel times channel count std::vector adpcm_pcm16(totalSamples * 2, 0); // Each frame decodes into twice as many pcm samples uint32_t frameOffset = 0; uint32_t frameCount = DataChunkInfo.size / s.frame_size; for (uint32_t i = 0; i < frameCount; ++i) { decode_ima_adpcm(s, adpcm_pcm16.data() + frameOffset, wavHeader.channel_count); s.inBuffer += s.frame_size; frameOffset += (s.frame_size * 2) - (8 * wavHeader.channel_count); } data->lengthSeconds = ((float) totalSamples / (float) wavHeader.sample_rate) / wavHeader.channel_count; data->samples.resize(totalSamples); ConvertToFloat32(data->samples.data(), adpcm_pcm16.data(), totalSamples, data->sourceFormat); } else { data->lengthSeconds = ((float) DataChunkInfo.size / (float) wavHeader.sample_rate) / wavHeader.frame_size; size_t totalSamples = (DataChunkInfo.size / wavHeader.frame_size) * wavHeader.channel_count; data->samples.resize(totalSamples); ConvertToFloat32(data->samples.data(), memory.data() + DataChunkInfo.offset, totalSamples, data->sourceFormat); } } std::vector WavDecoder::GetSupportedFileExtensions() { return {"wav", "wave"}; } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5961823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/libnyquist/WavEncoder.cpp0000644000000000000000000003420214735300037025350 0ustar00/* Copyright (c) 2015, Dimitri Diakopoulos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "libnyquist/WavEncoder.h" using namespace nqr; static inline void to_bytes(uint8_t value, char * arr) { arr[0] = (value)& 0xFF; } static inline void to_bytes(uint16_t value, char * arr) { arr[0] = (value)& 0xFF; arr[1] = (value >> 8) & 0xFF; } static inline void to_bytes(uint32_t value, char * arr) { arr[0] = (value)& 0xFF; arr[1] = (value >> 8) & 0xFF; arr[2] = (value >> 16) & 0xFF; arr[3] = (value >> 24) & 0xFF; } //////////////////////////// // Wave File Encoding // //////////////////////////// int WavEncoder::WriteFile(const EncoderParams p, const AudioData * d, const std::string & path) { assert(d->samples.size() > 0); // Cast away const because we know what we are doing (Hopefully?) float * sampleData = const_cast(d->samples.data()); size_t sampleDataSize = d->samples.size(); std::vector sampleDataOptionalMix; if (sampleDataSize <= 32) { return EncoderError::InsufficientSampleData; } if (d->channelCount < 1 || d->channelCount > 8) { return EncoderError::UnsupportedChannelConfiguration; } // Handle Channel Mixing -- // Mono => Stereo if (d->channelCount == 1 && p.channelCount == 2) { sampleDataOptionalMix.resize(sampleDataSize * 2); MonoToStereo(sampleData, sampleDataOptionalMix.data(), sampleDataSize); // Mix // Re-point data sampleData = sampleDataOptionalMix.data(); sampleDataSize = sampleDataOptionalMix.size(); } // Stereo => Mono else if (d->channelCount == 2 && p.channelCount == 1) { sampleDataOptionalMix.resize(sampleDataSize / 2); StereoToMono(sampleData, sampleDataOptionalMix.data(), sampleDataSize); // Mix // Re-point data sampleData = sampleDataOptionalMix.data(); sampleDataSize = sampleDataOptionalMix.size(); } else if (d->channelCount == p.channelCount) { // No op } else { return EncoderError::UnsupportedChannelMix; } // -- End Channel Mixing auto maxFileSizeInBytes = std::numeric_limits::max(); auto samplesSizeInBytes = (sampleDataSize * GetFormatBitsPerSample(p.targetFormat)) / 8; // 64 arbitrary if ((samplesSizeInBytes - 64) >= maxFileSizeInBytes) { return EncoderError::BufferTooBig; } // Don't support PC64 or PCDBL if (GetFormatBitsPerSample(p.targetFormat) > 32) { return EncoderError::UnsupportedBitdepth; } std::ofstream fout(path.c_str(), std::ios::out | std::ios::binary); if (!fout.is_open()) { return EncoderError::FileIOError; } char * chunkSizeBuff = new char[4]; // Initial size (this is changed after we're done writing the file) to_bytes(uint32_t(36), chunkSizeBuff); // RIFF file header fout.write(GenerateChunkCodeChar('R', 'I', 'F', 'F'), 4); fout.write(chunkSizeBuff, 4); fout.write(GenerateChunkCodeChar('W', 'A', 'V', 'E'), 4); // Fmt header auto header = MakeWaveHeader(p, d->sampleRate); fout.write(reinterpret_cast(&header), sizeof(WaveChunkHeader)); auto sourceBits = GetFormatBitsPerSample(d->sourceFormat); auto targetBits = GetFormatBitsPerSample(p.targetFormat); //////////////////////////// //@todo - channel mixing! // //////////////////////////// // Write out fact chunk if (p.targetFormat == PCM_FLT) { uint32_t four = 4; uint32_t dataSz = int(sampleDataSize / p.channelCount); fout.write(GenerateChunkCodeChar('f', 'a', 'c', 't'), 4); fout.write(reinterpret_cast(&four), 4); fout.write(reinterpret_cast(&dataSz), 4); // Number of samples (per channel) } // Data header fout.write(GenerateChunkCodeChar('d', 'a', 't', 'a'), 4); // + data chunk size to_bytes(uint32_t(samplesSizeInBytes), chunkSizeBuff); fout.write(chunkSizeBuff, 4); if (targetBits <= sourceBits && p.targetFormat != PCM_FLT) { // At most need this number of bytes in our copy std::vector samplesCopy(samplesSizeInBytes); ConvertFromFloat32(samplesCopy.data(), sampleData, sampleDataSize, p.targetFormat, p.dither); fout.write(reinterpret_cast(samplesCopy.data()), samplesSizeInBytes); } else { // Handle PCFLT. Coming in from AudioData ensures we start with 32 bits, so we're fine // since we've also rejected formats with more than 32 bits above. fout.write(reinterpret_cast(sampleData), samplesSizeInBytes); } // Padding byte if (isOdd(samplesSizeInBytes)) { const char * zero = ""; fout.write(zero, 1); } // Find size long totalSize = (long) fout.tellp(); // Modify RIFF header fout.seekp(4); // Total size of the file, less 8 bytes for the RIFF header to_bytes(uint32_t(totalSize - 8), chunkSizeBuff); fout.write(chunkSizeBuff, 4); delete[] chunkSizeBuff; return EncoderError::NoError; } ////////////////////////////// //// Opus File Encoding // ////////////////////////////// // //#include "opus/opusfile/include/opusfile.h" //#include "ogg/ogg.h" // //typedef std::pair metadata_t; // //class OggWriter //{ // void write_to_ostream(bool flush) // { // while (ogg_stream_pageout(&oss, &page)) // { // ostream->write(reinterpret_cast(page.header), static_cast(page.header_len)); // ostream->write(reinterpret_cast(page.body), static_cast(page.body_len)); // } // if (flush && ogg_stream_flush(&oss, &page)) // { // ostream->write(reinterpret_cast(page.header), static_cast(page.header_len)); // ostream->write(reinterpret_cast(page.body), static_cast(page.body_len)); // } // } // // std::vector make_header(int channel_count, int preskip, long sample_rate, int gain) // { // std::vector header; // // std::array steam_count = { { 0x0, 0x1, 0x1, 0x2, 0x2, 0x3, 0x4, 0x5, 0x5 } }; // std::array coupled_streacount = { { 0x0, 0x0, 0x1, 0x1, 0x2, 0x2, 0x2, 0x2, 0x3 } }; // // std::array chan_map_1 = { { 0x0 } }; // std::array chan_map_2 = { { 0x0, 0x1 } }; // // std::array _preamble = { { 'O', 'p', 'u', 's', 'H', 'e', 'a', 'd', 0x1 } }; // std::array _channel_count; // std::array _preskip; // std::array _sample_rate; // std::array _gain; // std::array _channel_family = { { 0x1 } }; // // to_bytes(uint8_t(channel_count), _channel_count.data()); // to_bytes(uint16_t(preskip), _preskip.data()); // to_bytes(uint32_t(sample_rate), _sample_rate.data()); // to_bytes(uint16_t(gain), _gain.data()); // // header.insert(header.end(), _preamble.cbegin(), _preamble.cend()); // header.insert(header.end(), _channel_count.cbegin(), _channel_count.cend()); // header.insert(header.end(), _preskip.cbegin(), _preskip.cend()); // header.insert(header.end(), _sample_rate.cbegin(), _sample_rate.cend()); // header.insert(header.end(), _gain.cbegin(), _gain.cend()); // header.insert(header.end(), _channel_family.cbegin(), _channel_family.cend()); // header.push_back(steam_count[channel_count]); // header.push_back(coupled_streacount[channel_count]); // // switch (channel_count) // { // case 1: header.insert(header.end(), chan_map_1.cbegin(), chan_map_1.cend()); break; // case 2: header.insert(header.end(), chan_map_2.cbegin(), chan_map_2.cend()); break; // default: throw std::runtime_error("couldn't map channel data"); // } // // return header; // } // // std::vector make_tags(const std::string & vendor, const std::vector & metadata) // { // std::vector tags; // // std::array _preamble = { { 'O', 'p', 'u', 's', 'T', 'a', 'g', 's' } }; // std::array _vendor_length; // std::array _metadata_count; // // to_bytes(uint32_t(vendor.size()), _vendor_length.data()); // to_bytes(uint32_t(metadata.size()), _metadata_count.data()); // // tags.insert(tags.end(), _preamble.cbegin(), _preamble.cend()); // tags.insert(tags.end(), _vendor_length.cbegin(), _vendor_length.cend()); // tags.insert(tags.end(), vendor.cbegin(), vendor.cend()); // tags.insert(tags.end(), _metadata_count.cbegin(), _metadata_count.cend()); // // // Process metadata. // for (const auto & metadata_entry : metadata) // { // std::array _metadata_entry_length; // std::string entry = metadata_entry.first + "=" + metadata_entry.second; // to_bytes(uint32_t(entry.size()), _metadata_entry_length.data()); // tags.insert(tags.end(), _metadata_entry_length.cbegin(), _metadata_entry_length.cend()); // tags.insert(tags.end(), entry.cbegin(), entry.cend()); // } // // return tags; // } // // ogg_int64_t packet_number; // ogg_int64_t granule; // ogg_page page; // ogg_stream_state oss; // // int channel_count; // long sample_rate; // int bits_per_sample; // std::ofstream * ostream; // std::string description; // std::vector metadata; // //public: // // OggWriter(int channel_count, long sample_rate, int bits_per_sample, std::ofstream & stream, const std::vector & md) // { // this->channel_count = channel_count; // this->sample_rate = sample_rate; // this->bits_per_sample = bits_per_sample; // this->ostream = &stream; // this->metadata = md; // // int oggInitErr, packetErr; // // ogg_packet header_packet; // ogg_packet tags_packet; // std::vector header_vector; // std::vector tags_vector; // // description = "Ogg"; // packet_number = 0; // granule = 0; // // // Validate parameters // if (channel_count < 1 && channel_count > 255) throw std::runtime_error("Channel count must be between 1 and 255."); // // // Initialize the Ogg stream. // oggInitErr = ogg_stream_init(&oss, 12345); // if (oggInitErr) throw std::runtime_error("Could not initialize the Ogg stream state."); // // // Initialize the header packet. // header_vector = make_header(channel_count, 3840, sample_rate, 0); // header_packet.packet = reinterpret_cast(header_vector.data()); // header_packet.bytes = header_vector.size(); // header_packet.b_o_s = 1; // header_packet.e_o_s = 0; // header_packet.granulepos = 0; // header_packet.packetno = packet_number++; // // // Initialize tags // tags_vector = make_tags("libnyquist", metadata); // tags_packet.packet = reinterpret_cast(tags_vector.data()); // tags_packet.bytes = tags_vector.size(); // tags_packet.b_o_s = 0; // tags_packet.e_o_s = 0; // tags_packet.granulepos = 0; // tags_packet.packetno = packet_number++; // // // Write header page // packetErr = ogg_stream_packetin(&oss, &header_packet); // if (packetErr) throw std::runtime_error("Could not write header packet to the Ogg stream."); // write_to_ostream(true); // // // Write tags page // packetErr = ogg_stream_packetin(&oss, &tags_packet); // if (packetErr) throw std::runtime_error("Could not write tags packet to the Ogg stream."); // write_to_ostream(true); // } // // ~OggWriter() // { // write_to_ostream(true); // ogg_stream_clear(&oss); // } // // bool write(char * data, std::streamsize length, size_t sampleCount, bool end) // { // int err; // ogg_packet packet; // // granule += sampleCount; // // packet.packet = reinterpret_cast(data); // packet.bytes = static_cast(length); // packet.b_o_s = 0; // packet.e_o_s = end ? 1 : 0; // packet.granulepos = granule; // packet.packetno = packet_number++; // // err = ogg_stream_packetin(&oss, &packet); // // if (err) throw std::runtime_error("could not write packet to stream"); // // write_to_ostream(false); // // return true; // } // //}; // //#define OPUS_MAX_PACKET_SIZE (1024 * 8) //#define OPUS_FRAME_SIZE 960 // //// Opus only supports a 48k samplerate... M //// This encoder only supports mono for the time being //int OggOpusEncoder::WriteFile(const EncoderParams p, const AudioData * d, const std::string & path) //{ // assert(d->samples.size() > 0); // //assert(d->sampleRate == 48000); // // float * sampleData = const_cast(d->samples.data()); // const size_t sampleDataSize = d->samples.size(); // // int opus_error; // OpusEncoder * enc; // enc = opus_encoder_create(48000, 1, OPUS_APPLICATION_AUDIO, &opus_error); // if (!enc) throw std::runtime_error("opus_encoder_create caused an error!"); // // std::ofstream fout(path.c_str(), std::ios::out | std::ios::binary); // // std::vector oggMetadata = { { "artist", "dimitri" } }; // OggWriter writer(d->channelCount, d->sampleRate, GetFormatBitsPerSample(d->sourceFormat), fout, oggMetadata); // // std::vector outBuffer(OPUS_MAX_PACKET_SIZE); // // int framesToEncode = (sampleDataSize / OPUS_FRAME_SIZE) - 1; // fixme // // while (framesToEncode >= 0) // { // auto encoded_size = opus_encode_float(enc, sampleData, OPUS_FRAME_SIZE, outBuffer.data(), OPUS_MAX_PACKET_SIZE); // // if (encoded_size < 0) // { // std::cerr << "Bad Opus Status: " << encoded_size << std::endl; // return EncoderError::FileIOError; // } // // writer.write((char*)outBuffer.data(), encoded_size, OPUS_FRAME_SIZE, (framesToEncode == 0) ? true : false); // // framesToEncode--; // sampleData += OPUS_FRAME_SIZE; // } // // fout.close(); // // opus_encoder_destroy(enc); // // return EncoderError::NoError; //} // //#undef OPUS_MAX_PACKET_SIZE././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5961823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/resource.h0000644000000000000000000000235514735300037022410 0ustar00{{copyright}} #ifndef _HV_{{name|upper}}_WWISE_RESOURCE_H_ #define _HV_{{name|upper}}_WWISE_RESOURCE_H_ #define IDD_HV_{{name|upper}}_PLUGIN_SMALL 15 #define IDD_HV_{{name|upper}}_PLUGIN_BIG 16 #define IDC_STATIC_PARAMETER_IN_GROUP 4000 #define IDC_STATIC_PARAMETER_OUT_GROUP 5000 #define IDC_STATIC_TABLE_GROUP 6000 // Auto-generated Heavy parameters {% for k, v in parameters %} #define IDC_STATIC_HV_PARAM_{{k|upper}} {{4000 + (loop.index*3)}} #define IDC_RANGE_HV_PARAM_{{k|upper}} {{4001 + (loop.index*3)}} #define IDS_HV_PARAM_{{k|upper}} {{4002 + (loop.index*3)}} {%- endfor %} {% for k, v in sends %} #define IDC_STATIC_HV_PARAM_OUT_{{k|upper}} {{5000 + (loop.index*3)}} {%- endfor %} {% for k, v in tables %} #define IDC_STATIC_HV_TABLE_{{k|upper}} {{6000 + (loop.index*2)}} #define IDC_BUTTON_HV_TABLE_{{k|upper}} {{6001 + (loop.index*2)}} {%- endfor %} // Next default values for new objects #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 4015 #define _APS_NEXT_COMMAND_VALUE 32771 #define _APS_NEXT_CONTROL_VALUE 4037 #define _APS_NEXT_SYMED_VALUE 4004 #endif #endif #endif // _HV_{{name|upper}}_WWISE_RESOURCE_H_ {# force new line #} ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5961823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/{{name}}.def0000644000000000000000000000002414735300037022757 0ustar00LIBRARY "" EXPORTS ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5961823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/{{name}}.rc0000644000000000000000000001411414735300037022632 0ustar00// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (United States) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) ///////////////////////////////////////////////////////////////////////////// // // String Table // {%- if parameters|length > 0 %} STRINGTABLE BEGIN {%- for k, v in parameters %} IDS_HV_PARAM_{{k|upper}} "{{v.display}}" {%- endfor %} END {%- endif %} #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // English (Canada) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENC) LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_CAN #pragma code_page(1252) #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "#define AK_WWISESDK_SAMPLE_FILEDESC ""{{name}} Wwise plug-in generated by Heavy""\r\n" "#define AK_WWISESDK_SAMPLE_INTERNALNAME ""{{name}}.dll""\r\n" "#define AK_WWISESDK_SAMPLE_ORIGINALFILE ""{{name}}.dll""\r\n" "#include ""AkWwiseSDKVersion.rc""\r\n" "#define _AFX_NO_SPLITTER_RESOURCES\r\n" "#define _AFX_NO_OLE_RESOURCES\r\n" "#define _AFX_NO_TRACKER_RESOURCES\r\n" "#define _AFX_NO_PROPERTY_RESOURCES\r\n" "\r\n" "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" "LANGUAGE 9, 1\r\n" "#pragma code_page(1252)\r\n" "#include ""afxres.rc"" // Standard components\r\n" "#endif\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Dialog // IDD_HV_{{name|upper}}_PLUGIN_BIG DIALOGEX 0, 0, 518, 280 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPCHILDREN FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN {%- set maxParamNameLength = 15 %} {%- set offset = 0 %} {%- if parameters|length > 0 %} {%- set offset = parameters|length*20+25 %} {%- for k, v in parameters %} {%- if k|length > maxParamNameLength %} {%- set maxParamNameLength = k|length %} {%- endif %} {%- endfor %} GROUPBOX "In Parameters", IDC_STATIC_PARAMETER_IN_GROUP, 5, 3, {{maxParamNameLength*10+65}}, {{parameters|length*20+20}} {%- for k, v in parameters %} LTEXT "{{v.display}}", IDC_STATIC_HV_PARAM_{{k|upper}}, 25, {{((loop.index-1)*20)+20}}, {{maxParamNameLength*5}}, 13, WS_TABSTOP LTEXT "Class=SuperRange;Prop={{k}}", IDC_RANGE_HV_PARAM_{{k|upper}}, {{maxParamNameLength*5}}+45, {{((loop.index-1)*20)+20}}, 80, 13, WS_BORDER | WS_TABSTOP {%- endfor %} {%- endif %} {%- if sends|length > 0 %} GROUPBOX "Out Parameters", IDC_STATIC_PARAMETER_OUT_GROUP, 5, {{offset+5}}, {{maxParamNameLength*10+65}}, {{sends|length*20+20}} {%- for k, v in sends %} LTEXT "{{k|lower}}", IDC_STATIC_HV_PARAM_OUT_{{k|upper}}, 25, {{((loop.index-1)*20)+offset+20}}, {{maxParamNameLength*5}}, 13, WS_TABSTOP {%- endfor %} {%- set offset = offset + sends|length*20+25 %} {%- endif %} {%- if tables|length > 0 %} {%- for k, v in tables %} {%- if k|length > maxParamNameLength %} {%- set maxParamNameLength = k|length %} {%- endif %} {%- endfor %} GROUPBOX "Tables", IDC_STATIC_TABLE_GROUP, 5, {{offset+5}}, {{maxParamNameLength*10+65}}, {{tables|length*20+20}} {%- for k, v in tables %} LTEXT "{{v.display}}", IDC_STATIC_HV_TABLE_{{k|upper}}, 25, {{((loop.index-1)*20)+offset+20}}, {{maxParamNameLength*5}}, 13, WS_TABSTOP PUSHBUTTON "Load Sample", IDC_BUTTON_HV_TABLE_{{k|upper}}, {{maxParamNameLength*5}}+45, {{((loop.index-1)*20)+offset+20}}, 50, 13 {%- endfor %} {%- endif %} END IDD_HV_{{name|upper}}_PLUGIN_SMALL DIALOGEX 0, 0, {{(parameters|length) * 50}}, 13 STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN {%- for k, v in parameters %} {% if loop.index < 4 -%} LTEXT "Class=SuperRange;Prop={{k}};Title={{v.display}};", IDC_RANGE_HV_PARAM_{{k|upper}}, {{((loop.index-1)*50)}}, 0, 50, 13, WS_BORDER | WS_TABSTOP {%- endif %} {%- endfor %} END ///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO // #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN IDD_HV_{{name|upper}}_PLUGIN_BIG, DIALOG BEGIN END IDD_HV_{{name|upper}}_PLUGIN_SMALL, DIALOG BEGIN RIGHTMARGIN, 196 VERTGUIDE, 2 END END #endif // APSTUDIO_INVOKED #endif // English (Canada) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // #define AK_WWISESDK_SAMPLE_FILEDESC "{{name}} Wwise plug-in generated by Heavy" #define AK_WWISESDK_SAMPLE_INTERNALNAME "{{name}}.dll" #define AK_WWISESDK_SAMPLE_ORIGINALFILE "{{name}}.dll" #include "AkWwiseSDKVersion.rc" #define _AFX_NO_SPLITTER_RESOURCES #define _AFX_NO_OLE_RESOURCES #define _AFX_NO_TRACKER_RESOURCES #define _AFX_NO_PROPERTY_RESOURCES #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) LANGUAGE 9, 1 #pragma code_page(1252) #include "afxres.rc" // Standard components #endif ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED {# force new line #} ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5961823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/{{name}}.xml0000644000000000000000000001067714735300037023040 0ustar00 {{copyright}} {%- if plugin_type == "Source" %} {% if tables|length > 0 -%} true true true true true true true {% else -%} {% endif -%} {%- if parameters|length > 0 %} {%- for k, v in parameters %} {{v.attributes.default}} {{loop.index-1}} {{v.attributes.min}} {{v.attributes.max}} {%- endfor %} {%- endif %} {%- elif plugin_type == "FX" %} true true true true true true true true true true true true true true true true true true {%- if parameters|length > 0 %} {%- for k, v in parameters %} {{v.attributes.default}} {{loop.index-1}} {{v.attributes.min}} {{v.attributes.max}} {%- endfor %} {%- endif %} {%- endif %} {# force new line #} ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5961823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/{{name}}Plugin.cpp0000644000000000000000000000573714735300037024202 0ustar00{{copyright}} #include "{{name}}Plugin.h" #include "../SoundEnginePlugin/{{name}}{{plugin_type}}Factory.h" #include "libnyquist/WavDecoder.h" #include "libnyquist/WavEncoder.h" #include #include #include #include bool {{name}}Plugin::GetBankParameters(const GUID & in_guidPlatform, AK::Wwise::Plugin::DataWriter& in_dataWriter) const { {%- for k, v in parameters %} in_dataWriter.WriteReal32(m_propertySet.GetReal32(in_guidPlatform, "{{k}}")); {%- endfor %} return true; } void {{name}}Plugin::NotifyPluginMediaChanged() { m_host.NotifyInternalDataChanged(AK::IAkPluginParam::ALL_PLUGIN_DATA_ID, true); } AK::Wwise::Plugin::ConversionResult {{name}}Plugin::ConvertFile( const GUID& in_guidPlatform, const BasePlatformID& in_basePlatform, const AkOSChar* in_szSourceFile, const AkOSChar* in_szDestFile, AkUInt32 in_uSampleRate, AkUInt32 in_uBlockLength, AK::Wwise::Plugin::IProgress* in_pProgress, AK::Wwise::Plugin::IWriteString* io_pError) const { if (wcslen(in_szSourceFile) > 0) { // convert input file to 32bit floating point wav nqr::NyquistIO loader; std::shared_ptr fileData = std::make_shared(); std::string inPath = std::wstring_convert>().to_bytes(in_szSourceFile); loader.Load(fileData.get(), inPath); std::string outPath = std::wstring_convert>().to_bytes(in_szDestFile); nqr::WavEncoder::WriteFile({ 1, nqr::PCM_FLT, nqr::DITHER_NONE }, fileData.get(), outPath); } else { // Note(joe): because we create dummy media sources for the patch tables the input file here doesn't exist // but we still need to create a dummy output file to avoid errors std::ofstream outFile(in_szDestFile); outFile.close(); } return AK::Wwise::Plugin::ConversionSuccess; } uint32_t {{name}}Plugin::GetCurrentConversionSettingsHash( const GUID& in_guidPlatform, AkUInt32 in_uSampleRate, AkUInt32 in_uBlockLength) const { const auto numMedia = m_objectMedia.GetMediaSourceCount(); uint32_t hash = in_uSampleRate ^ in_uBlockLength; AK::FNVHash32 hashFunc; AkOSChar szMediaFileName[_MAX_PATH]; for (int32_t mediaIdx = 0; mediaIdx < numMedia; ++mediaIdx) { const uint32_t fileNameSize = m_objectMedia.GetMediaSourceFileName(szMediaFileName, _MAX_PATH, mediaIdx); if (fileNameSize > 0) { for (int i = 0; i < fileNameSize; ++i) { szMediaFileName[i] = tolower(szMediaFileName[i]); } hash = hash * 31 + static_cast(hashFunc.Compute(szMediaFileName, fileNameSize)); } } return hash; } DEFINE_AUDIOPLUGIN_CONTAINER({{name}}); EXPORT_AUDIOPLUGIN_CONTAINER({{name}}); ADD_AUDIOPLUGIN_CLASS_TO_CONTAINER({{name}}, {{name}}Plugin, {{name}}{{plugin_type}}); DEFINE_PLUGIN_REGISTER_HOOK DEFINEDUMMYASSERTHOOK; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5961823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/WwisePlugin/{{name}}Plugin.h0000644000000000000000000000231414735300037023633 0ustar00{{copyright}} #pragma once #include class {{name}}Plugin final : public AK::Wwise::Plugin::AudioPlugin , public AK::Wwise::Plugin::RequestHost , public AK::Wwise::Plugin::RequestObjectMedia , public AK::Wwise::Plugin::MediaConverter { public: {{name}}Plugin() = default; ~{{name}}Plugin() = default; bool GetBankParameters(const GUID & in_guidPlatform, AK::Wwise::Plugin::DataWriter& in_dataWriter) const override; void NotifyPluginMediaChanged() override; AK::Wwise::Plugin::ConversionResult ConvertFile( const GUID& in_guidPlatform, const BasePlatformID& in_basePlatform, const AkOSChar* in_szSourceFile, const AkOSChar* in_szDestFile, AkUInt32 in_uSampleRate, AkUInt32 in_uBlockLength, AK::Wwise::Plugin::IProgress* in_pProgress, AK::Wwise::Plugin::IWriteString* io_pError ) const override; uint32_t GetCurrentConversionSettingsHash( const GUID& in_guidPlatform, AkUInt32 in_uSampleRate = 0, AkUInt32 in_uBlockLength = 0 ) const override; }; DECLARE_AUDIOPLUGIN_CONTAINER({{name}}); // Exposes our PluginContainer structure that contains the info for our plugin ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5961823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/bundle_template.json0000644000000000000000000000122014735300037022160 0ustar00{ "id": "Heavy.{{name}}.${year}_${major}_${minor}_${build}", "name": "{{name}}", "tag": "{{name}}", "description": "", "vendor": "Heavy", "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", "type": "plugin", "productDependentData": { "targetWwiseVersion": { "year": ${year}, "major": ${major} } }, "version": { "year": ${year}, "major": ${major}, "minor": ${minor}, "build": ${build} }, "eulas": [], "labels": [], "links": [], "documentation": [] } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5961823 hvcc-0.13.3/hvcc/generators/c2wwise/templates/{{name}}Config.h0000644000000000000000000000034514735300037021327 0ustar00{{copyright}} #ifndef {{name}}Config_H #define {{name}}Config_H namespace {{name}}Config { static const unsigned short CompanyID = 64; static const unsigned short PluginID = {{plugin_id}}; } #endif // {{name}}Config_H ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7592068 hvcc-0.13.3/hvcc/generators/copyright/__init__.py0000644000000000000000000000000014435670357016670 0ustar00././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1727976067.272552 hvcc-0.13.3/hvcc/generators/copyright/copyright_manager.py0000644000000000000000000000400414677551203020637 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import datetime import os from typing import Optional def get_default_copyright_text() -> str: with open(os.path.join(os.path.dirname(__file__), "default_template.txt"), "r") as f: copyright = f.read().format(datetime.datetime.now().year) return copyright def get_copyright_for_c(copyright_text: Optional[str] = None) -> str: """ Returns an input string as a C-formatted comment, otherwise a default copyright statement if the input is None. """ return comment_for_c(copyright_text or get_default_copyright_text()) def get_copyright_for_xml(copyright_text: Optional[str] = None) -> str: """ Returns an input string as an xml comment, otherwise a default copyright statement if the input is None. """ return comment_for_xml(copyright_text or get_default_copyright_text()) def comment_for_c(comment: str) -> str: """ Returns the input string as a C-formatted comment, suitable for copyright statements. """ if "\n" in comment: return "/**\n * {0}\n */".format("\n * ".join(comment.split("\n"))) else: return f"/** {comment} */" def comment_for_xml(comment: str) -> str: """ Returns the input string as a XML comment, suitable for copyright statements. """ if "\n" in comment: return f"" else: return f"" ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7592068 hvcc-0.13.3/hvcc/generators/copyright/default_template.txt0000644000000000000000000000304214435670357020650 0ustar00Copyright (c) {0} Enzien Audio, Ltd. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the phrase "powered by heavy", the heavy logo, and a hyperlink to https://enzienaudio.com, all in a visible form. 2.1 If the Application is distributed in a store system (for example, the Apple "App Store" or "Google Play"), the phrase "powered by heavy" shall be included in the app description or the copyright text as well as the in the app itself. The heavy logo will shall be visible in the app itself as well. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1727976067.272552 hvcc-0.13.3/hvcc/generators/filters.py0000644000000000000000000000435514677551203014606 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2021-2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import hashlib import os def filter_max(i: int, j: int) -> int: """Calculate the maximum of two integers. """ return max(int(i), int(j)) def filter_plugin_id(s: str) -> int: """ Return a unique id from patch name [0...32767 """ sh = hashlib.md5(s.encode('utf-8')) sd = sh.hexdigest()[:4] return int(sd, 16) & 0x7FFF def filter_string_cap(s: str, li: int) -> str: """Returns a truncated string with ellipsis if it exceeds a certain length. """ return s if (len(s) <= li) else f"{s[0:li - 3]}..." def filter_templates(template_name: str) -> bool: return False if os.path.basename(template_name) in [".DS_Store"] else True def filter_uniqueid(s: str) -> str: """ Return a unique id (in hexadecimal) for the Plugin interface. """ sh = hashlib.md5(s.encode('utf-8')) sd = sh.hexdigest().upper()[0:8] return f"0x{sd}" def filter_xcode_build(s: str) -> str: """Return a build hash suitable for use in an Xcode project file. """ s = f"{s}_build" sh = hashlib.md5(s.encode('utf-8')) return sh.hexdigest().upper()[0:24] def filter_xcode_copy(s: str) -> str: """Return a copyref hash suitable for use in an Xcode project file. """ s = f"{s}_copy" sh = hashlib.md5(s.encode('utf-8')) return sh.hexdigest().upper()[0:24] def filter_xcode_fileref(s: str) -> str: """Return a fileref hash suitable for use in an Xcode project file. """ s = f"{s}_fileref" sh = hashlib.md5(s.encode('utf-8')) return sh.hexdigest().upper()[0:24] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.267823 hvcc-0.13.3/hvcc/generators/ir2c/ControlBinop.py0000644000000000000000000001064214735300474016376 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlBinop(HeavyObject): # a dictionary translating from the operation argument to the C case __OPERATION_DICT = { "__add": "HV_BINOP_ADD", "__add_k": "HV_BINOP_ADD", "__sub": "HV_BINOP_SUBTRACT", "__sub_k": "HV_BINOP_SUBTRACT", "__mul": "HV_BINOP_MULTIPLY", "__mul_k": "HV_BINOP_MULTIPLY", "__div": "HV_BINOP_DIVIDE", "__div_k": "HV_BINOP_DIVIDE", "__intdiv": "HV_BINOP_INT_DIV", "__intdiv_k": "HV_BINOP_INT_DIV", "__shiftleft": "HV_BINOP_BIT_LEFTSHIFT", "__shiftleft_k": "HV_BINOP_BIT_LEFTSHIFT", "__shiftright": "HV_BINOP_BIT_RIGHTSHIFT", "__shiftright_k": "HV_BINOP_BIT_RIGHTSHIFT", "__and": "HV_BINOP_BIT_AND", "__and_k": "HV_BINOP_BIT_AND", "__or": "HV_BINOP_BIT_OR", "__or_k": "HV_BINOP_BIT_OR", "__^": "HV_BINOP_BIT_XOR", "__==": "HV_BINOP_EQL_EQL", "__!=": "HV_BINOP_NOT_EQL", "__logand": "HV_BINOP_LOGICAL_AND", "__logand_k": "HV_BINOP_LOGICAL_AND", "__logor": "HV_BINOP_LOGICAL_OR", "__logor_k": "HV_BINOP_LOGICAL_OR", "__eq": "HV_BINOP_EQ", "__eq_k": "HV_BINOP_EQ", "__neq": "HV_BINOP_NEQ", "__neq_k": "HV_BINOP_NEQ", "__lt": "HV_BINOP_LESS_THAN", "__lt_k": "HV_BINOP_LESS_THAN", "__lte": "HV_BINOP_LESS_THAN_EQL", "__lte_k": "HV_BINOP_LESS_THAN_EQL", "__gt": "HV_BINOP_GREATER_THAN", "__gt_k": "HV_BINOP_GREATER_THAN", "__gte": "HV_BINOP_GREATER_THAN_EQL", "__gte_k": "HV_BINOP_GREATER_THAN_EQL", "__max": "HV_BINOP_MAX", "__max_k": "HV_BINOP_MAX", "__min": "HV_BINOP_MIN", "__min_k": "HV_BINOP_MIN", "__pow": "HV_BINOP_POW", "__pow_k": "HV_BINOP_POW", "__atan2": "HV_BINOP_ATAN2", "__atan2_k": "HV_BINOP_ATAN2", "__unimod": "HV_BINOP_MOD_UNIPOLAR", "__unimod_k": "HV_BINOP_MOD_UNIPOLAR", "__bimod": "HV_BINOP_MOD_BIPOLAR", "__bimod_k": "HV_BINOP_MOD_BIPOLAR" } c_struct = "ControlBinop" preamble = "cBinop" @classmethod def handles_type(cls, obj_type: str) -> bool: """Returns true if the object type can be handled by this class """ return obj_type in cls.__OPERATION_DICT @classmethod def get_C_header_set(cls) -> set: return {"HvControlBinop.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlBinop.h", "HvControlBinop.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: if obj_type.endswith("_k"): return [] else: obj_arg = float(list(args.values())[0]) return [f"cBinop_init(&cBinop_{obj_id}, {obj_arg}f); // {obj_type}"] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] # no need to free any control binop objects @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: if obj_type.endswith("_k"): return [ "cBinop_k_onMessage(_c, NULL, {0}, {1}f, {2}, m, &cBinop_{3}_sendMessage);".format( cls.__OPERATION_DICT[obj_type[:-2]], float(args["k"]), inlet_index, obj_id) ] else: return [ "cBinop_onMessage(_c, &Context(_c)->cBinop_{0}, {1}, {2}, m, &cBinop_{0}_sendMessage);".format( obj_id, cls.__OPERATION_DICT[obj_type], inlet_index) ] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.267823 hvcc-0.13.3/hvcc/generators/ir2c/ControlCast.py0000644000000000000000000000275014735300474016222 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlCast(HeavyObject): __OPERATION_DICT = { "__cast_b": "HV_CAST_BANG", "__cast_f": "HV_CAST_FLOAT", "__cast_s": "HV_CAST_SYMBOL" } c_struct = "ControlCast" preamble = "cCast" @classmethod def get_C_header_set(cls) -> set: return {"HvControlCast.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlCast.h", "HvControlCast.c"} @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ "cCast_onMessage(_c, {1}, 0, m, &cCast_{0}_sendMessage);".format( obj_id, cls.__OPERATION_DICT[obj_type]) ] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.267823 hvcc-0.13.3/hvcc/generators/ir2c/ControlDelay.py0000644000000000000000000000505314735300474016365 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Callable, Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IROnMessage, IRObjectdict class ControlDelay(HeavyObject): c_struct = "ControlDelay" preamble = "cDelay" @classmethod def get_C_header_set(cls) -> set: return {"HvControlDelay.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlDelay.h", "HvControlDelay.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "{0}_init(this, &{0}_{1}, {2}f);".format( cls.preamble, obj_id, float(args["delay"])) ] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] # no need to free any control binop objects @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ "{0}_onMessage(_c, &Context(_c)->{0}_{1}, {2}, m, " "&{0}_{1}_sendMessage);".format( cls.preamble, obj_id, inlet_index) ] @classmethod def get_C_impl( cls, obj_type: str, obj_id: str, on_message_list: List[List[IROnMessage]], get_obj_class: Callable, objects: Dict[str, IRObjectdict] ) -> List[str]: send_message_list = [ f"cDelay_{obj_id}_sendMessage(HeavyContextInterface *_c, int letIn, const HvMessage *const m) {{" ] send_message_list.append(f"cDelay_clearExecutingMessage(&Context(_c)->cDelay_{obj_id}, m);") send_message_list.extend( cls._get_on_message_list(on_message_list[0], get_obj_class, objects)) send_message_list.append("}") # end function return send_message_list ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlIf.py0000644000000000000000000000341314735300474015663 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlIf(HeavyObject): c_struct = "ControlIf" preamble = "cIf" @classmethod def get_C_header_set(cls) -> set: return {"HvControlIf.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlIf.h", "HvControlIf.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "{0}_init(&{0}_{1}, {2});".format( cls.preamble, obj_id, "true" if float(args["k"]) != 0.0 else "false" )] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] # no need to free any control binop objects @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ "{0}_onMessage(_c, &Context(_c)->{0}_{1}, {2}, m, " "&{0}_{1}_sendMessage);".format(cls.preamble, obj_id, inlet_index) ] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlMessage.py0000644000000000000000000000652014735300474016713 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import re from typing import Callable, Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRObjectdict, IROnMessage class ControlMessage(HeavyObject): preamble = "cMsg" @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [f"cMsg_{obj_id}_sendMessage(_c, 0, m);"] @classmethod def get_C_impl( cls, obj_type: str, obj_id: str, on_message_list: List[List[IROnMessage]], get_obj_class: Callable, objects: Dict[str, IRObjectdict], ) -> List[str]: send_message_list = [ f"cMsg_{obj_id}_sendMessage(HeavyContextInterface *_c, int letIn, const HvMessage *const n) {{" ] if len(objects[obj_id].args["local"]) > 0: # declare the outgoing messages (if there are any) send_message_list.append("HvMessage *m = nullptr;") # for each message for m in objects[obj_id].args["local"]: # construct the message send_message_list.append(f"m = HV_MESSAGE_ON_STACK({len(m)});") send_message_list.append(f"msg_init(m, {len(m)}, msg_getTimestamp(n));") for i in range(len(m)): e = m[i] # get the message element try: # is the message a float? send_message_list.append(f"msg_setFloat(m, {i}, {float(e)}f);") except Exception: if e in ["bang"]: # is the message a bang? send_message_list.append(f"msg_setBang(m, {i});") elif re.match(r"\$[\d]+", e): send_message_list.append(f"msg_setElementToFrom(m, {i}, n, {int(e[1:]) - 1});") elif e == "@HV_N_SIMD": # NOTE(mhroth): messages can contain special arguments # which are interpreted differently than other strings send_message_list.append(f"msg_setFloat(m, {i}, static_cast(HV_N_SIMD));") else: send_message_list.append(f"msg_setSymbol(m, {i}, \"{e}\");") # send the message to all receiving objects for om in on_message_list[0]: send_message_list.extend( get_obj_class(objects[om.id].type).get_C_onMessage( objects[om.id].type, om.id, om.inletIndex, objects[om.id].args)) send_message_list.append("}") # end function return send_message_list ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlPack.py0000644000000000000000000000333114735300474016202 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlPack(HeavyObject): """Prints the first value in a message to the console""" c_struct = "ControlPack" preamble = "cPack" @classmethod def get_C_header_set(cls) -> set: return {"HvControlPack.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlPack.h", "HvControlPack.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "cPack_init(&cPack_{0}, {1}, {2});".format( obj_id, len(args["values"]), ", ".join(["{0}f".format(float(x)) for x in args["values"]])) ] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ "cPack_onMessage(_c, &Context(_c)->cPack_{0}, {1}, m, &cPack_{0}_sendMessage);".format( obj_id, inlet_index) ] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlPrint.py0000644000000000000000000000364714735300474016432 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Callable, Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRObjectdict, IROnMessage class ControlPrint(HeavyObject): """Prints the first value in a message to the console""" preamble = "cPrint" @classmethod def get_C_header_set(cls) -> set: return {"HvControlPrint.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlPrint.h", "HvControlPrint.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [f"cPrint_onMessage(_c, m, \"{args['label']}\");"] @classmethod def get_C_decl(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_impl( cls, obj_type: str, obj_id: str, on_message_list: List[List[IROnMessage]], get_obj_class: Callable, objects: Dict[str, IRObjectdict] ) -> List[str]: return [] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlRandom.py0000644000000000000000000000334214735300474016546 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlRandom(HeavyObject): c_struct = "ControlRandom" preamble = "cRandom" @classmethod def get_C_header_set(cls) -> set: return {"HvControlRandom.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlRandom.h", "HvControlRandom.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "{0}_init(&{0}_{1}, {2});".format( cls.preamble, obj_id, int(args["seed"])) ] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] # no need to free any control binop objects @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ "{0}_onMessage(_c, &Context(_c)->{0}_{1}, {2}, m, " "&{0}_{1}_sendMessage);".format(cls.preamble, obj_id, inlet_index) ] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlReceive.py0000644000000000000000000000205114735300474016704 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlReceive(HeavyObject): c_struct = "ControlReceive" preamble = "cReceive" @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [f"cReceive_{obj_id}_sendMessage(_c, 0, m);"] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlSend.py0000644000000000000000000000437314735300474016224 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Callable, Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRObjectdict, IROnMessage class ControlSend(HeavyObject): c_struct = "ControlSend" preamble = "cSend" @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [f"cSend_{obj_id}_sendMessage(_c, 0, m);"] @classmethod def get_C_impl( cls, obj_type: str, obj_id: str, on_message_list: List[List[IROnMessage]], get_obj_class: Callable, objects: Dict[str, IRObjectdict] ) -> List[str]: # Note(joe): if no corresponding receivers exist and there's no extern indicator # then there is not much need to generate code stub send_message_list = [ "{0}_{1}_sendMessage(HeavyContextInterface *_c, int letIn, const HvMessage *m) {{".format( cls.get_preamble(obj_type), obj_id)] if objects[obj_id].args.get("extern", False): # call the send hook send_name = objects[obj_id].args["name"] send_message_list.append("if (_c->getSendHook() != nullptr) _c->getSendHook()(_c, \"{0}\", {1}, m);".format( send_name, cls.get_hash_string(send_name))) # a send has only one (implicit!) outlet send_message_list.extend( cls._get_on_message_list(on_message_list[0], get_obj_class, objects)) send_message_list.append("}") # end function return send_message_list ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlSlice.py0000644000000000000000000000332114735300474016362 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlSlice(HeavyObject): c_struct = "ControlSlice" preamble = "cSlice" @classmethod def get_C_header_set(cls) -> set: return {"HvControlSlice.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlSlice.h", "HvControlSlice.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "cSlice_init(&cSlice_{0}, {1}, {2});".format( obj_id, int(args["index"]), int(args["length"]))] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] # nothing to free @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ f"cSlice_onMessage(_c, &Context(_c)->cSlice_{obj_id}, {inlet_index}, m, &cSlice_{obj_id}_sendMessage);" ] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlSwitchcase.py0000644000000000000000000000626214735300474017427 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Callable, Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IROnMessage, IRObjectdict class ControlSwitchcase(HeavyObject): c_struct = "ControlSwitchase" preamble = "cSwichcase" @classmethod def get_C_def(cls, obj_type: str, obj_id: str) -> List[str]: return [] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_decl(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ f"cSwitchcase_{obj_id}_onMessage(HeavyContextInterface *, void *, int letIn, " "const HvMessage *const, void *);" ] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [f"cSwitchcase_{obj_id}_onMessage(_c, NULL, {inlet_index}, m, NULL);"] @classmethod def get_C_impl( cls, obj_type: str, obj_id: str, on_message_list: List[List[IROnMessage]], get_obj_class: Callable, objects: Dict[str, IRObjectdict] ) -> List[str]: # generate the onMessage implementation out_list = [ f"cSwitchcase_{obj_id}_onMessage(HeavyContextInterface *_c, void *o, int letIn, " f"const HvMessage *const m, void *sendMessage) {{" ] out_list.append("int msgIndex = 0;") out_list.append("switch (msg_getHash(m, msgIndex)) {") out_list.append(f"case {cls.get_hash_string('symbol')}: {{ // \"symbol\"") out_list.append("msgIndex = 1;") out_list.append("break;") out_list.append("}") # end symbol case out_list.append("}") # end type switch out_list.append("switch (msg_getHash(m, msgIndex)) {") cases = objects[obj_id].args["cases"] for i, c in enumerate(cases): hv_hash = cls.get_hash_string(c) out_list.append(f"case {hv_hash}: {{ // \"{c}\"") out_list.extend( cls._get_on_message_list(on_message_list[i], get_obj_class, objects)) out_list.append("break;") out_list.append("}") out_list.append("default: {") out_list.extend( cls._get_on_message_list(on_message_list[-1], get_obj_class, objects)) out_list.append("break;") out_list.append("}") # end default out_list.append("}") # end switch out_list.append("}") # end function return out_list ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlSystem.py0000644000000000000000000000243014735300474016607 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlSystem(HeavyObject): c_struct = "ControlSystem" preamble = "cSystem" @classmethod def get_C_header_set(cls) -> set: return {"HvControlSystem.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlSystem.h", "HvControlSystem.c"} @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [f"cSystem_onMessage(_c, NULL, {inlet_index}, m, &cSystem_{obj_id}_sendMessage);"] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlTabhead.py0000644000000000000000000000316514735300474016661 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlTabhead(HeavyObject): """Handles __tabhead """ c_struct = "ControlTabhead" preamble = "cTabhead" @classmethod def get_C_header_set(cls) -> set: return {"HvControlTabhead.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlTabhead.h", "HvControlTabhead.c"} @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [f"cTabhead_init(&cTabhead_{obj_id}, &hTable_{args['table_id']});"] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [f"cTabhead_onMessage(_c, &Context(_c)->cTabhead_{obj_id}, 0, m, &cTabhead_{obj_id}_sendMessage);"] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlTabread.py0000644000000000000000000000340714735300474016672 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlTabread(HeavyObject): c_struct = "ControlTabread" preamble = "cTabread" @classmethod def get_C_header_set(cls) -> set: return {"HvControlTabread.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlTabread.h", "HvControlTabread.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "cTabread_init(&cTabread_{0}, &hTable_{1}); // {2}".format( obj_id, args["table_id"], args["table"]) ] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ "cTabread_onMessage(_c, &Context(_c)->cTabread_{0}, {1}, m, &cTabread_{0}_sendMessage);".format( obj_id, inlet_index) ] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlTabwrite.py0000644000000000000000000000342214735300474017106 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlTabwrite(HeavyObject): c_struct = "ControlTabwrite" preamble = "cTabwrite" @classmethod def get_C_header_set(cls) -> set: return {"HvControlTabwrite.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlTabwrite.h", "HvControlTabwrite.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "cTabwrite_init(&cTabwrite_{0}, &hTable_{1}); // {2}".format( obj_id, args["table_id"], args["table"]) ] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ "cTabwrite_onMessage(_c, &Context(_c)->cTabwrite_{0}, {1}, m, &cTabwrite_{0}_sendMessage);".format( obj_id, inlet_index) ] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlUnop.py0000644000000000000000000000506514735300474016253 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlUnop(HeavyObject): # a dictionary translating from the operation argument to the C case __OPERATION_DICT = { "__cos": "HV_UNOP_COS", "__acos": "HV_UNOP_ACOS", "__cosh": "HV_UNOP_COSH", "__acosh": "HV_UNOP_ACOSH", "__sin": "HV_UNOP_SIN", "__asin": "HV_UNOP_ASIN", "__sinh": "HV_UNOP_SINH", "__asinh": "HV_UNOP_ASINH", "__tan": "HV_UNOP_TAN", "__atan": "HV_UNOP_ATAN", "__tanh": "HV_UNOP_TANH", "__atanh": "HV_UNOP_ATANH", "__log": "HV_UNOP_LOG", "__log10": "HV_UNOP_LOG10", "__log2": "HV_UNOP_LOG2", "__exp": "HV_UNOP_EXP", "__abs": "HV_UNOP_ABS", "__sqrt": "HV_UNOP_SQRT", "__ceil": "HV_UNOP_CEIL", "__floor": "HV_UNOP_FLOOR", "__round": "HV_UNOP_ROUND" } c_struct = "ControlUnop" preamble = "cUnop" @classmethod def handles_type(cls, obj_type: str) -> bool: """Returns true if the object type can be handled by this class """ return obj_type in cls.__OPERATION_DICT @classmethod def get_C_header_set(cls) -> set: return {"HvControlUnop.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlUnop.h", "HvControlUnop.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ "cUnop_onMessage(_c, {1}, m, &cUnop_{0}_sendMessage);".format( obj_id, cls.__OPERATION_DICT[obj_type]) ] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/ControlVar.py0000644000000000000000000000414214735300474016055 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class ControlVar(HeavyObject): """An object which holds a variable. In this case only a float. NOTE(mhroth): maybe in the future this can hold any data structure, such as a generic message. At the moment, the memory churn is deemed unnecessary. """ c_struct = "ControlVar" preamble = "cVar" @classmethod def get_C_header_set(cls) -> set: return {"HvControlVar.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvControlVar.h", "HvControlVar.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: if isinstance(args["k"], str): return [ "cVar_init_s(&cVar_{0}, \"{1}\");".format( obj_id, args["k"])] else: return [ "cVar_init_f(&cVar_{0}, {1}f);".format( obj_id, float(args["k"]))] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ "cVar_onMessage(_c, &Context(_c)->cVar_{0}, {1}, m, &cVar_{0}_sendMessage);".format( obj_id, inlet_index) ] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/HeavyObject.py0000644000000000000000000001517014735300474016172 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from struct import unpack, pack from typing import Callable, Dict, List, Union from hvcc.types.IR import IROnMessage, IRSignalList, IRBuffer, IRObjectdict class HeavyObject: c_struct = "" preamble = "" __C_BUFFER_DICT = { "~f>": "Bf", "~i>": "Bi", "input": "I", "output": "O", "zero": "ZERO" } @classmethod def get_C_struct(cls, obj_type: str = "") -> str: return cls.c_struct @classmethod def get_preamble(cls, obj_type: str) -> str: return cls.preamble @classmethod def get_C_header_set(self) -> set: return set() @classmethod def get_C_file_set(self) -> set: return set() @classmethod def get_C_def(cls, obj_type: str, obj_id: str) -> List[str]: return ["{0} {1}_{2};".format( cls.get_C_struct(obj_type), cls.get_preamble(obj_type), obj_id)] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return ["{0}_free(&{0}_{1});".format( cls.get_preamble(obj_type), obj_id)] @classmethod def get_C_decl(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return ["{0}_{1}_sendMessage(HeavyContextInterface *, int, const HvMessage *);".format( cls.get_preamble(obj_type), obj_id)] @classmethod def get_C_impl( cls, obj_type: str, obj_id: str, on_message_list: List[List[IROnMessage]], get_obj_class: Callable, objects: Dict[str, IRObjectdict] ) -> List[str]: send_message_list = [ "{0}_{1}_sendMessage(HeavyContextInterface *_c, int letIn, const HvMessage *m) {{".format( cls.get_preamble(obj_type), obj_id)] if len(on_message_list) == 1: # if there is only one outlet, skip the switch-case template send_message_list.extend( cls._get_on_message_list(on_message_list[0], get_obj_class, objects)) else: send_message_list.append("switch (letIn) {") for i in range(len(on_message_list)): send_message_list.append(f"case {i}: {{") send_message_list.extend( cls._get_on_message_list(on_message_list[i], get_obj_class, objects)) send_message_list.append("break;") send_message_list.append("}") # end case send_message_list.append("default: return;") send_message_list.append("}") # end switch send_message_list.append("}") # end function return send_message_list @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: raise NotImplementedError("method get_C_init not implemented") @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: raise NotImplementedError("method get_C_onMessage not implemented") @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: raise NotImplementedError("method get_C_process not implemented") @classmethod def get_table_data_decl(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: raise NotImplementedError("method get_table_data_decl not implemented") @classmethod def _get_on_message_list( cls, on_message_list: List[IROnMessage], get_obj_class: Callable, objects: Dict[str, IRObjectdict] ) -> List: out_list = [] for om in on_message_list: out_list.extend( get_obj_class(objects[om.id].type).get_C_onMessage( objects[om.id].type, om.id, om.inletIndex, objects[om.id].args)) return out_list @classmethod def _c_buffer(cls, buffer_dict: IRBuffer) -> str: """ Returns the C represenation of the given buffer. """ if buffer_dict.type == "zero": return cls.__C_BUFFER_DICT[buffer_dict.type] else: return "{0}{1}".format( cls.__C_BUFFER_DICT[buffer_dict.type], buffer_dict.index) @classmethod def get_hash(cls, x: Union[float, str]) -> int: """ Compute the message element hash used by msg_getHash(). Returns a 32-bit integer. """ if isinstance(x, float) or isinstance(x, int): # interpret the float bytes as an unsigned integer return unpack("@I", pack("@f", float(x)))[0] elif x == "bang": return 0xFFFFFFFF elif isinstance(x, str): # this hash is based MurmurHash2 # http://en.wikipedia.org/wiki/MurmurHash # https://sites.google.com/site/murmurhash/ x = str(x) m = 0x5bd1e995 r = 24 h = len(x) i = 0 while i < len(x) & ~0x3: k = unpack("@I", bytes(x[i:i + 4], encoding='utf-8'))[0] k = (k * m) & 0xFFFFFFFF k ^= k >> r k = (k * m) & 0xFFFFFFFF h = (h * m) & 0xFFFFFFFF h ^= k i += 4 n = len(x) & 0x3 x = x[i:i + n] if n >= 3: h ^= (ord(x[2]) << 16) & 0xFFFFFFFF if n >= 2: h ^= (ord(x[1]) << 8) & 0xFFFFFFFF if n >= 1: h ^= ord(x[0]) h = (h * m) & 0xFFFFFFFF h ^= h >> 13 h = (h * m) & 0xFFFFFFFF h ^= h >> 15 return h else: raise Exception("Message element hashes can only be computed for float and string types.") @classmethod def get_hash_string(cls, x: Union[float, str]) -> str: """ Returns the hash as a hex string. """ return f"0x{cls.get_hash(x):X}" ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/HeavyTable.py0000644000000000000000000000466414735300474016021 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject class HeavyTable(HeavyObject): """Outputs code for the table object. """ c_struct = "HvTable" preamble = "hTable" @classmethod def get_C_header_set(self) -> set: return {"HvTable.h"} @classmethod def get_C_file_set(self) -> set: return {"HvTable.h", "HvTable.c"} @classmethod def get_table_data_decl(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: if len(args.get("values", [])) > 0: return [ "float hTable_{0}_data[{1}] = {{{2}}};".format( obj_id, len(args["values"]), ", ".join([f"{float(v)}f" for v in args["values"]]))] else: return [] @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: if len(args.get("values", [])) > 0: return [ "hTable_initWithData(&hTable_{0}, {1}, hTable_{0}_data);".format( obj_id, len(args["values"]))] else: return [ "hTable_init(&hTable_{0}, {1});".format( obj_id, int(args.get("size", 256)))] # 1KB default memory allocation @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return ["{0}_free(&{0}_{1});".format( cls.preamble, obj_id)] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ f"hTable_onMessage(_c, &Context(_c)->hTable_{obj_id}, {inlet_index}, m, &hTable_{obj_id}_sendMessage);" ] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1734329071.247243 hvcc-0.13.3/hvcc/generators/ir2c/PrettyfyC.py0000644000000000000000000000327114727741357015731 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os from typing import List class PrettyfyC: @classmethod def prettyfy_file( cls, file_in: str, file_out: str, indent: int = 0, step: int = 2, delete_input_on_finish: bool = False ) -> None: with open(file_in, "r") as f: with open(file_out, "w") as g: for line in f: indent -= line.count("}") new_line = (" " * (step * indent)) + line g.write(new_line + os.linesep) indent += line.count("{") if delete_input_on_finish: os.remove(file_in) @classmethod def prettyfy_list( cls, list_in: List, indent: int = 0, step: int = 2 ) -> List: g = [] for line in list_in: indent -= line.count("}") new_line = (" " * (step * indent)) + line g.append(new_line) indent += line.count("{") return g ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/SignalBiquad.py0000644000000000000000000000635214735300474016334 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalBiquad(HeavyObject): """Handles the biquad~ object. """ c_struct = "SignalBiquad" preamble = "sBiquad" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalBiquad.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalBiquad.h", "HvSignalBiquad.c"} @classmethod def get_C_def(cls, obj_type: str, obj_id: str) -> List[str]: if obj_type == "__biquad_k~f": return [f"SignalBiquad_k sBiquad_k_{obj_id};"] elif obj_type == "__biquad~f": return [f"SignalBiquad sBiquad_s_{obj_id};"] else: raise Exception() @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: if obj_type == "__biquad_k~f": return ["sBiquad_k_init(&sBiquad_k_{0}, {1}f, {2}f, {3}f, {4}f, {5}f);".format( obj_id, float(args["ff0"]), float(args["ff1"]), float(args["ff2"]), float(args["fb1"]), float(args["fb2"]))] elif obj_type == "__biquad~f": return [f"sBiquad_init(&sBiquad_s_{obj_id});"] else: raise Exception() @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [f"sBiquad_k_onMessage(&Context(_c)->sBiquad_k_{obj_id}, {inlet_index}, m);"] @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: if obj_type == "__biquad_k~f": return [ "__hv_biquad_k_f(&sBiquad_k_{0}, VIf({1}), VOf({2}));".format( process_dict.id, cls._c_buffer(process_dict.inputBuffers[0]), cls._c_buffer(process_dict.outputBuffers[0]) )] elif obj_type == "__biquad~f": return [ "__hv_biquad_f(&sBiquad_s_{0}, {1}, {2});".format( process_dict.id, ", ".join([f"VIf({cls._c_buffer(b)})" for b in process_dict.inputBuffers]), ", ".join([f"VOf({cls._c_buffer(b)})" for b in process_dict.outputBuffers]) )] else: raise Exception(f"Incorrect obj_type {obj_type} for SignalBiquad") ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/SignalCPole.py0000644000000000000000000000443514735300474016131 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalCPole(HeavyObject): """Handles the __cpole~f object. """ c_struct = "SignalCPole" preamble = "sCPole" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalCPole.h", "HvSignalDel1.h", "HvMath.h"} @classmethod def get_C_file_set(cls) -> set: return { "HvSignalCPole.h", "HvSignalCPole.c", "HvSignalDel1.h", "HvSignalDel1.c", "HvMath.h" } @classmethod def get_C_def(cls, obj_type: str, obj_id: str) -> List[str]: return [f"SignalCPole sCPole_{obj_id};"] @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [f"sCPole_init(&sCPole_{obj_id});"] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "__hv_cpole_f(&sCPole_{0}, VIf({1}), VIf({2}), VIf({3}), VIf({4}), VOf({5}), VOf({6}));".format( process_dict.id, cls._c_buffer(process_dict.inputBuffers[0]), cls._c_buffer(process_dict.inputBuffers[1]), cls._c_buffer(process_dict.inputBuffers[2]), cls._c_buffer(process_dict.inputBuffers[3]), cls._c_buffer(process_dict.outputBuffers[0]), cls._c_buffer(process_dict.outputBuffers[1]))] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2688231 hvcc-0.13.3/hvcc/generators/ir2c/SignalConvolution.py0000644000000000000000000000406014735300474017440 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalConvolution(HeavyObject): c_struct = "SignalConvolution" preamble = "sConv" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalConvolution.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalConvolution.h", "HvSignalConvolution.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "sConv_init(&sConv_{0}, &hTable_{1}, {2});".format( obj_id, args["table_id"], int(args["size"])) ] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ "sConv_onMessage(_c, &Context(_c)->sConv_{0}, {1}, m, NULL);".format( obj_id, inlet_index) ] @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "__hv_conv_f(&sConv_{0}, VIf({1}), VOf({2}));".format( process_dict.id, cls._c_buffer(process_dict.inputBuffers[0]), cls._c_buffer(process_dict.outputBuffers[0]) ) ] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalDel1.py0000644000000000000000000000356714735300474015721 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalDel1(HeavyObject): """Handles the __del1~f object. """ c_struct = "SignalDel1" preamble = "sDel1" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalDel1.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalDel1.h", "HvSignalDel1.c"} @classmethod def get_C_def(cls, obj_type: str, obj_id: str) -> List[str]: return [f"SignalDel1 sDel1_{obj_id};"] @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [f"sDel1_init(&sDel1_{obj_id});"] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "__hv_del1_f(&sDel1_{0}, VIf({1}), VOf({2}));".format( process_dict.id, cls._c_buffer(process_dict.inputBuffers[0]), cls._c_buffer(process_dict.outputBuffers[0]))] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalEnvelope.py0000644000000000000000000000333314735300474016700 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalEnvelope(HeavyObject): c_struct = "SignalEnvelope" preamble = "sEnv" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalEnvelope.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalEnvelope.h", "HvSignalEnvelope.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "sEnv_init(&sEnv_{0}, {1}, {2});".format( obj_id, int(args["windowSize"]), int(args["period"])) ] @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "sEnv_process(this, &sEnv_{0}, VIf({1}), &sEnv_{0}_sendMessage);".format( process_dict.id, cls._c_buffer(process_dict.inputBuffers[0]) ) ] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalLine.py0000644000000000000000000000365514735300474016021 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalLine(HeavyObject): c_struct = "SignalLine" preamble = "sLine" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalLine.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalLine.h", "HvSignalLine.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ f"sLine_init(&sLine_{obj_id});" ] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] # nothing to free @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ f"sLine_onMessage(_c, &Context(_c)->sLine_{obj_id}, {inlet_index}, m, NULL);" ] @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "__hv_line_f(&sLine_{0}, VOf({1}));".format( process_dict.id, cls._c_buffer(process_dict.outputBuffers[0]) ) ] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalLorenz.py0000644000000000000000000000442714735300474016401 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalLorenz(HeavyObject): c_struct = "SignalLorenz" preamble = "sLorenz" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalLorenz.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalLorenz.h", "HvSignalLorenz.c", "HvMath.h"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "sLorenz_init(&sLorenz_{0}, {1}f, {2}f, {3}f);".format( obj_id, float(args["x"]), float(args["y"]), float(args["z"])) ] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] # nothing to free @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ "sLorenz_onMessage(_c, &Context(_c)->sLorenz_{0}, {1}, m);".format( obj_id, inlet_index) ] @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "__hv_lorenz_f(&sLorenz_{0}, {1}, {2});".format( process_dict.id, ", ".join(["VIf({0})".format(cls._c_buffer(b)) for b in process_dict.inputBuffers]), ", ".join(["VOf({0})".format(cls._c_buffer(b)) for b in process_dict.outputBuffers]) ) ] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalMath.py0000644000000000000000000000715314735300474016020 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalMath(HeavyObject): """Handles the math objects. """ # translation from operation to function preamble __OPERATION_DICT = { "__add~f": "__hv_add_f", "__add~i": "__hv_add_i", "__sub~f": "__hv_sub_f", "__sub~i": "__hv_sub_i", "__mul~f": "__hv_mul_f", "__mul~i": "__hv_mul_i", "__div~f": "__hv_div_f", "__div~i": "__hv_div_i", "__log2~f": "__hv_log2_f", "__cos~f": "__hv_cos_f", "__acos~f": "__hv_acos_f", "__cosh~f": "__hv_cosh_f", "__acosh~f": "__hv_acosh_f", "__sin~f": "__hv_sin_f", "__asin~f": "__hv_asin_f", "__sinh~f": "__hv_sinh_f", "__asinh~f": "__hv_asinh_f", "__tan~f": "__hv_tan_f", "__atan~f": "__hv_atan_f", "__atan2~f": "__hv_atan2_f", "__tanh~f": "__hv_tanh_f", "__atanh~f": "__hv_atanh_f", "__exp~f": "__hv_exp_f", "__pow~f": "__hv_pow_f", "__pow~i": "__hv_pow_i", "__sqrt~f": "__hv_sqrt_f", "__rsqrt~f": "__hv_rsqrt_f", "__abs~f": "__hv_abs_f", "__abs~i": "__hv_abs_i", "__max~f": "__hv_max_f", "__max~i": "__hv_max_i", "__min~f": "__hv_min_f", "__min~i": "__hv_min_i", "__neg~f": "__hv_neg_f", "__gt~f": "__hv_gt_f", "__gt~i": "__hv_gt_i", "__gte~f": "__hv_gte_f", "__gte~i": "__hv_gte_i", "__lt~f": "__hv_lt_f", "__lt~i": "__hv_lt_i", "__lte~f": "__hv_lte_f", "__lte~i": "__hv_lte_i", "__eq~f": "__hv_eq_f", "__neq~f": "__hv_neq_f", "__fma~f": "__hv_fma_f", "__fms~f": "__hv_fms_f", "__floor~f": "__hv_floor_f", "__ceil~f": "__hv_ceil_f", "__cast~fi": "__hv_cast_fi", "__cast~if": "__hv_cast_if", "__and~f": "__hv_and_f", # binary and "__andnot~f": "__hv_andnot_f", "__or~f": "__hv_or_f", # binary or } @classmethod def handles_type(cls, obj_type: str) -> bool: """Returns true if the object type can be handled by this class """ return obj_type in cls.__OPERATION_DICT @classmethod def get_C_header_set(cls) -> set: return {"HvMath.h"} @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "{0}({1}, {2});".format( cls.__OPERATION_DICT[obj_type], ", ".join(["VI{0}({1})".format( "i" if b.type == "~i>" else "f", cls._c_buffer(b)) for b in process_dict.inputBuffers]), ", ".join(["VO{0}({1})".format( "i" if b.type == "~i>" else "f", cls._c_buffer(b)) for b in process_dict.outputBuffers]) )] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalPhasor.py0000644000000000000000000000545114735300474016362 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalPhasor(HeavyObject): c_struct = "SignalPhasor" preamble = "sPhasor" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalPhasor.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalPhasor.h", "HvSignalPhasor.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: if obj_type == "__phasor~f": return [f"sPhasor_init(&sPhasor_{obj_id}, sampleRate);"] elif obj_type == "__phasor_k~f": return [f"sPhasor_k_init(&sPhasor_{obj_id}, {args['frequency']}f, sampleRate);"] else: raise Exception() @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: if obj_type == "__phasor~f": return [f"sPhasor_onMessage(_c, &Context(_c)->sPhasor_{obj_id}, {inlet_index}, m);"] elif obj_type == "__phasor_k~f": return [f"sPhasor_k_onMessage(_c, &Context(_c)->sPhasor_{obj_id}, {inlet_index}, m);"] else: raise Exception() @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: if obj_type == "__phasor~f": return [ "__hv_phasor_f(&sPhasor_{0}, VIf({1}), VOf({2}));".format( process_dict.id, cls._c_buffer(process_dict.inputBuffers[0]), cls._c_buffer(process_dict.outputBuffers[0]) ) ] elif obj_type == "__phasor_k~f": return [ "__hv_phasor_k_f(&sPhasor_{0}, VOf({1}));".format( process_dict.id, cls._c_buffer(process_dict.outputBuffers[0]) ) ] else: raise Exception(f"Unknown object type \"{obj_type}\".") ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalRPole.py0000644000000000000000000000410714735300474016144 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalRPole(HeavyObject): """Handles the __rpole~f object. """ c_struct = "SignalRpole" preamble = "sRPole" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalRPole.h", "HvSignalDel1.h", "HvMath.h"} @classmethod def get_C_file_set(cls) -> set: return { "HvSignalRPole.h", "HvSignalRPole.c", "HvSignalDel1.h", "HvSignalDel1.c", "HvMath.h" } @classmethod def get_C_def(cls, obj_type: str, obj_id: str) -> List[str]: return [f"SignalRPole sRPole_{obj_id};"] @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [f"sRPole_init(&sRPole_{obj_id});"] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "__hv_rpole_f(&sRPole_{0}, VIf({1}), VIf({2}), VOf({3}));".format( process_dict.id, cls._c_buffer(process_dict.inputBuffers[0]), cls._c_buffer(process_dict.inputBuffers[1]), cls._c_buffer(process_dict.outputBuffers[0]))] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalSamphold.py0000644000000000000000000000371114735300474016672 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalSamphold(HeavyObject): c_struct = "SignalSamphold" preamble = "sSamphold" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalSamphold.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalSamphold.h", "HvSignalSamphold.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [f"sSamphold_init(&sSamphold_{obj_id});"] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: raise Exception() @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "__hv_samphold_f(&sSamphold_{0}, VIf({1}), VIf({2}), VOf({3}));".format( process_dict.id, cls._c_buffer(process_dict.inputBuffers[0]), cls._c_buffer(process_dict.inputBuffers[1]), cls._c_buffer(process_dict.outputBuffers[0]))] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalSample.py0000644000000000000000000000404514735300474016345 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalSample(HeavyObject): c_struct = "SignalSample" preamble = "sSample" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalSample.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalSample.h", "HvSignalSample.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [f"sSample_init(&sSample_{obj_id});"] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] # nothing to free @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [ "{0}_onMessage(_c, &Context(_c)->{0}_{1}, {2}, m);".format( cls.preamble, obj_id, inlet_index) ] @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "__hv_sample_f(this, &sSample_{0}, VIf({1}), &{2}_{0}_sendMessage);".format( process_dict.id, cls._c_buffer(process_dict.inputBuffers[0]), cls.preamble ) ] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalTabhead.py0000644000000000000000000000366514735300474016463 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalTabhead(HeavyObject): """Handles __tabhead~f """ c_struct = "SignalTabhead" preamble = "sTabhead" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalTabread.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalTabread.h", "HvSignalTabread.c"} @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [f"sTabhead_init(&sTabhead_{obj_id}, &hTable_{args['table_id']});"] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [] # TODO(mhroth): deal with this later @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "__hv_tabhead_f(&sTabhead_{0}, {1});".format( process_dict.id, ", ".join([f"VOf({cls._c_buffer(b)})" for b in process_dict.outputBuffers]) )] ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalTabread.py0000644000000000000000000000710414735300474016465 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalTabread(HeavyObject): """Handles __tabread~if, __tabread~f, __tabreadu~f, __tabread_stoppable~f """ c_struct = "SignalTabread" preamble = "sTabread" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalTabread.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalTabread.h", "HvSignalTabread.c"} @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [ "sTabread_init(&sTabread_{0}, &hTable_{1}, {2});".format( obj_id, args["table_id"], "true" if obj_type in {"__tabread~f", "__tabread_stoppable~f"} else "false")] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: if obj_type in ["__tabread~f", "__tabreadu~f", "__tabread_stoppable~f"]: return [ "sTabread_onMessage(_c, &Context(_c)->sTabread_{0}, {1}, m, &sTabread_{0}_sendMessage);".format( obj_id, inlet_index)] else: # "__tabread~if" return [f"sTabread_onMessage(_c, &Context(_c)->sTabread_{obj_id}, {inlet_index}, m, NULL);"] @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: if obj_type == "__tabread~if": return [ "__hv_tabread_if(&sTabread_{0}, {1}, {2});".format( process_dict.id, ", ".join([f"VIi({cls._c_buffer(b)})" for b in process_dict.inputBuffers]), ", ".join([f"VOf({cls._c_buffer(b)})" for b in process_dict.outputBuffers]) )] elif obj_type == "__tabread~f": return [ "__hv_tabread_f(&sTabread_{0}, {1});".format( process_dict.id, ", ".join([f"VOf({cls._c_buffer(b)})" for b in process_dict.outputBuffers]) )] elif obj_type == "__tabread_stoppable~f": return [ "__hv_tabread_stoppable_f(this, &sTabread_{0}, {1}, &{2}_{0}_sendMessage);".format( process_dict.id, ", ".join([f"VOf({cls._c_buffer(b)})" for b in process_dict.outputBuffers]), cls.preamble )] elif obj_type == "__tabreadu~f": return [ "__hv_tabreadu_f(&sTabread_{0}, {1});".format( process_dict.id, ", ".join([f"VOf({cls._c_buffer(b)})" for b in process_dict.outputBuffers]) )] else: raise Exception() ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalTabwrite.py0000644000000000000000000000457614735300474016716 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalTabwrite(HeavyObject): """Handles __tabwrite~f """ c_struct = "SignalTabwrite" preamble = "sTabwrite" @classmethod def get_C_header_set(cls) -> set: return {"HvSignalTabwrite.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalTabwrite.h", "HvSignalTabwrite.c"} @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [f"sTabwrite_init(&sTabwrite_{obj_id}, &hTable_{args['table_id']});"] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: return [f"sTabwrite_onMessage(_c, &Context(_c)->sTabwrite_{obj_id}, {inlet_index}, m, NULL);"] @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: if obj_type == "__tabwrite~f": return [ "__hv_tabwrite_f(&sTabwrite_{0}, {1});".format( process_dict.id, ", ".join([f"VIf({cls._c_buffer(b)})" for b in process_dict.inputBuffers]) )] elif obj_type == "__tabwrite_stoppable~f": return [ "__hv_tabwrite_stoppable_f(&sTabwrite_{0}, {1});".format( process_dict.id, ", ".join([f"VIf({cls._c_buffer(b)})" for b in process_dict.inputBuffers]) )] else: raise Exception() ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.269823 hvcc-0.13.3/hvcc/generators/ir2c/SignalVar.py0000644000000000000000000001077214735300474015660 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, List from .HeavyObject import HeavyObject from hvcc.types.IR import IRSignalList class SignalVar(HeavyObject): __OPERATION_DICT = { "__var~f": "sVarf", "__var~i": "sVari", "__var_k~f": "__hv_var_k_f", "__var_k~i": "__hv_var_k_i", "__varwrite~f": "__hv_varwrite_f", "__varwrite~i": "__hv_varwrite_i", "__varread~f": "__hv_varread_f", "__varread~i": "__hv_varread_i" } @classmethod def get_C_struct(cls, obj_type: str = "") -> str: if obj_type == "__var~f": return "SignalVarf" elif obj_type == "__var~i": return "SignalVari" else: raise Exception() @classmethod def get_preamble(cls, obj_type: str) -> str: return cls.__OPERATION_DICT[obj_type] @classmethod def handles_type(cls, obj_type: str) -> bool: """Returns true if the object type can be handled by this class """ return obj_type in cls.__OPERATION_DICT @classmethod def get_C_header_set(cls) -> set: return {"HvSignalVar.h"} @classmethod def get_C_file_set(cls) -> set: return {"HvSignalVar.h", "HvSignalVar.c"} @classmethod def get_C_init(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: assert obj_type in ["__var~f", "__var~i"], obj_type return [ "{0}_init(&{0}_{1}, {2}, {3}, {4});".format( SignalVar.__OPERATION_DICT[obj_type], obj_id, f"{float(args['k'])}f" if obj_type.endswith("f") else int(args["k"]), f"{float(args['step'])}f" if obj_type.endswith("f") else int(args["step"]), "true" if args["reverse"] else "false")] @classmethod def get_C_free(cls, obj_type: str, obj_id: str, args: Dict) -> List[str]: return [] @classmethod def get_C_onMessage(cls, obj_type: str, obj_id: str, inlet_index: int, args: Dict) -> List[str]: assert obj_type in ["__var~f", "__var~i"] return [ "{0}_onMessage(_c, &Context(_c)->{0}_{1}, m);".format( cls.__OPERATION_DICT[obj_type], obj_id)] @classmethod def get_C_process(cls, process_dict: IRSignalList, obj_type: str, obj_id: str, args: Dict) -> List[str]: fmt = obj_type[-1] if obj_type in ["__var~f", "__var~i"]: # NOTE(mhroth): signal rate variables do not process anything return [] elif obj_type in ["__varwrite~f", "__varwrite~i"]: return [ "__hv_varwrite_{1}(&sVar{1}_{0}, VI{1}({2}));".format( args["var_id"], fmt, cls._c_buffer(process_dict.inputBuffers[0]) )] elif obj_type in ["__var_k~f", "__var_k~i"]: if args["k"] == 0.0 and args.get("step", 0.0) == 0.0: return ["__hv_zero_{0}(VO{0}({1}));".format( fmt, cls._c_buffer(process_dict.outputBuffers[0]))] else: c = [float(args["k"] + i * args.get("step", 0.0)) for i in range(8)] cx = ", ".join(["{0}f".format(f) for f in c]) if fmt == "f" else ", ".join([str(int(i)) for i in c]) return ["__hv_var_k_{0}{3}(VO{0}({1}), {2});".format( fmt, cls._c_buffer(process_dict.outputBuffers[0]), cx, "_r" if args.get("reverse", False) else "")] elif obj_type in ["__varread~f", "__varread~i"]: return [ "__hv_varread_{1}(&sVar{1}_{0}, VO{1}({2}));".format( args["var_id"], fmt, cls._c_buffer(process_dict.outputBuffers[0]) )] else: raise Exception("") ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7612069 hvcc-0.13.3/hvcc/generators/ir2c/__init__.py0000644000000000000000000000000014435670357015517 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735983617.1410897 hvcc-0.13.3/hvcc/generators/ir2c/ir2c.py0000644000000000000000000003067314736201001014616 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import argparse import jinja2 import json import os import shutil import time from collections import Counter from collections import OrderedDict from typing import Dict, List, Optional, Type, Union from hvcc.generators.ir2c.PrettyfyC import PrettyfyC from hvcc.generators.copyright import copyright_manager from hvcc.generators.ir2c.ControlBinop import ControlBinop from hvcc.generators.ir2c.ControlCast import ControlCast from hvcc.generators.ir2c.ControlDelay import ControlDelay from hvcc.generators.ir2c.ControlIf import ControlIf from hvcc.generators.ir2c.ControlMessage import ControlMessage from hvcc.generators.ir2c.ControlPack import ControlPack from hvcc.generators.ir2c.ControlPrint import ControlPrint from hvcc.generators.ir2c.ControlReceive import ControlReceive from hvcc.generators.ir2c.ControlRandom import ControlRandom from hvcc.generators.ir2c.ControlSend import ControlSend from hvcc.generators.ir2c.ControlSlice import ControlSlice from hvcc.generators.ir2c.ControlSwitchcase import ControlSwitchcase from hvcc.generators.ir2c.ControlSystem import ControlSystem from hvcc.generators.ir2c.ControlTabhead import ControlTabhead from hvcc.generators.ir2c.ControlTabread import ControlTabread from hvcc.generators.ir2c.ControlTabwrite import ControlTabwrite from hvcc.generators.ir2c.ControlUnop import ControlUnop from hvcc.generators.ir2c.ControlVar import ControlVar from hvcc.generators.ir2c.HeavyObject import HeavyObject from hvcc.generators.ir2c.HeavyTable import HeavyTable from hvcc.generators.ir2c.SignalConvolution import SignalConvolution from hvcc.generators.ir2c.SignalBiquad import SignalBiquad from hvcc.generators.ir2c.SignalCPole import SignalCPole from hvcc.generators.ir2c.SignalDel1 import SignalDel1 from hvcc.generators.ir2c.SignalEnvelope import SignalEnvelope from hvcc.generators.ir2c.SignalLine import SignalLine from hvcc.generators.ir2c.SignalLorenz import SignalLorenz from hvcc.generators.ir2c.SignalMath import SignalMath from hvcc.generators.ir2c.SignalPhasor import SignalPhasor from hvcc.generators.ir2c.SignalRPole import SignalRPole from hvcc.generators.ir2c.SignalSample import SignalSample from hvcc.generators.ir2c.SignalSamphold import SignalSamphold from hvcc.generators.ir2c.SignalTabhead import SignalTabhead from hvcc.generators.ir2c.SignalTabread import SignalTabread from hvcc.generators.ir2c.SignalTabwrite import SignalTabwrite from hvcc.generators.ir2c.SignalVar import SignalVar from hvcc.types.compiler import CompilerResp, ExternInfo from hvcc.types.IR import IRGraph class ir2c: __OBJECT_CLASS_DICT = { "__delay": ControlDelay, "__if": ControlIf, "__print": ControlPrint, "__random": ControlRandom, "__var": ControlVar, "__table": HeavyTable, "__cast_b": ControlCast, "__cast_f": ControlCast, "__cast_s": ControlCast, "__message": ControlMessage, "__system": ControlSystem, "__receive": ControlReceive, "__switchcase": ControlSwitchcase, "__conv~f": SignalConvolution, "__biquad~f": SignalBiquad, "__biquad_k~f": SignalBiquad, "__env~f": SignalEnvelope, "__line~f": SignalLine, "__lorenz~f": SignalLorenz, "__del1~f": SignalDel1, "__tabread~if": SignalTabread, "__tabread~f": SignalTabread, "__tabreadu~f": SignalTabread, "__tabread_stoppable~f": SignalTabread, "__tabhead~f": SignalTabhead, "__tabwrite~f": SignalTabwrite, "__tabwrite_stoppable~f": SignalTabwrite, "__phasor~f": SignalPhasor, "__phasor_k~f": SignalPhasor, "__sample~f": SignalSample, "__samphold~f": SignalSamphold, "__slice": ControlSlice, "__send": ControlSend, "__tabhead": ControlTabhead, "__tabread": ControlTabread, "__tabwrite": ControlTabwrite, "__pack": ControlPack, "__rpole~f": SignalRPole, "__cpole~f": SignalCPole } # the base set of C files necessary for the patch __BASE_FILE_SET = { "HeavyContextInterface.hpp", "HeavyContext.hpp", "HeavyContext.cpp", "HvHeavy.h", "HvHeavyInternal.h", "HvHeavy.cpp", "HvUtils.h", "HvUtils.c", "HvMath.h", "HvMessageQueue.h", "HvMessageQueue.c", "HvMessagePool.h", "HvMessagePool.c", "HvTable.h", "HvTable.c", "HvMessage.h", "HvMessage.c", "HvLightPipe.h", "HvLightPipe.c" } @classmethod def filter_hvhash(cls, x: Union[float, str]) -> str: """ Return the hash string of an object. """ return HeavyObject.get_hash_string(x) @classmethod def filter_extern(cls, d: Dict) -> Dict: """ Return a dictionary of objects that are externed. """ return {k: v for k, v in d.items() if v.extern} @classmethod def get_class(cls, obj_type: str) -> Type[HeavyObject]: if SignalMath.handles_type(obj_type): return SignalMath elif ControlBinop.handles_type(obj_type): return ControlBinop elif ControlUnop.handles_type(obj_type): return ControlUnop elif SignalVar.handles_type(obj_type): return SignalVar elif obj_type in ir2c.__OBJECT_CLASS_DICT: return ir2c.__OBJECT_CLASS_DICT[obj_type] else: raise Exception(f"No class found for object type \"{obj_type}\".") @classmethod def compile( cls, hv_ir_path: str, static_dir: str, output_dir: str, externs: ExternInfo, copyright: Optional[str] = None, nodsp: Optional[bool] = False ) -> CompilerResp: """ Compiles a HeavyIR file into a C. Returns a tuple of compile time in seconds, a notification dictionary, and a HeavyIR object counter. """ # keep track of the total compile time tick = time.time() # establish the jinja environment env = jinja2.Environment() env.filters["hvhash"] = cls.filter_hvhash env.filters["extern"] = cls.filter_extern env.loader = jinja2.FileSystemLoader( os.path.join(os.path.dirname(__file__), "templates")) # read the hv.ir.json file with open(hv_ir_path, "r") as f: ir = IRGraph(**json.load(f)) # generate the copyright copyright = copyright_manager.get_copyright_for_c(copyright) # # Parse the hv.ir data structure and generate C-language strings. # # generate set of header files to include include_set = set([x for o in ir.objects.values() for x in ir2c.get_class(o.type).get_C_header_set()]) # generate set of files to add to project file_set = set([x for o in ir.objects.values() for x in ir2c.get_class(o.type).get_C_file_set()]) file_set.update(ir2c.__BASE_FILE_SET) # generate object definition and initialisation list init_list: List = [] free_list = [] def_list = [] decl_list = [] for obj_id in ir.init.order: o = ir.objects[obj_id] obj_class = ir2c.get_class(o.type) init_list.extend(obj_class.get_C_init(o.type, obj_id, o.args)) def_list.extend(obj_class.get_C_def(o.type, obj_id)) free_list.extend(obj_class.get_C_free(o.type, obj_id, o.args)) impl_list = [] for msg in ir.control.sendMessage: obj_id = msg.id o = ir.objects[obj_id] obj_class = ir2c.get_class(o.type) impl = obj_class.get_C_impl( o.type, obj_id, msg.onMessage, ir2c.get_class, ir.objects) impl_list.append("\n".join(PrettyfyC.prettyfy_list(impl))) decl_list.extend(obj_class.get_C_decl(o.type, obj_id, o.args)) # generate static table data initialisers table_data_list: List = [] for k, v in ir.tables.items(): o = ir.objects[v.id] obj_class = ir2c.get_class(o.type) table_data_list.extend(obj_class.get_table_data_decl( o.type, v.id, o.args)) # generate the list of functions to process process_list: List = [] for sig in ir.signal.processOrder: obj_id = sig.id o = ir.objects[obj_id] process_list.extend(ir2c.get_class(o.type).get_C_process( sig, o.type, obj_id, o.args)) # # Load the C-language template files and use the parsed strings to fill them in. # # make the output directory if necessary if not os.path.exists(output_dir): os.makedirs(output_dir) # the project name to be used as a part of file and function names name = ir.name.escaped # ensure that send_receive dictionary is alphabetised by the receiver key send_receive = OrderedDict(sorted([(k, v) for k, v in ir.control.receivers.items()], key=lambda x: x[0])) # write HeavyContext.h with open(os.path.join(output_dir, f"Heavy_{name}.hpp"), "w") as f: f.write(env.get_template("Heavy_NAME.hpp").render( name=name, include_set=include_set, decl_list=decl_list, def_list=def_list, signal=ir.signal, copyright=copyright, externs=externs)) # write C++ implementation with open(os.path.join(output_dir, f"Heavy_{name}.cpp"), "w") as f: f.write(env.get_template("Heavy_NAME.cpp").render( name=name, signal=ir.signal, init_list=init_list, free_list=free_list, impl_list=impl_list, send_receive=send_receive, send_table=ir.tables, process_list=process_list, table_data_list=table_data_list, copyright=copyright, nodsp=nodsp)) # write C API, hv_NAME.h with open(os.path.join(output_dir, f"Heavy_{name}.h"), "w") as f: f.write(env.get_template("Heavy_NAME.h").render( name=name, copyright=copyright, externs=externs)) # copy static files to output directory for f in file_set: shutil.copy2( src=os.path.join(static_dir, str(f)), dst=os.path.join(output_dir, str(f))) # generate HeavyIR object counter ir_counter = Counter([obj.type for obj in ir.objects.values()]) return CompilerResp( stage="ir2c", in_dir=os.path.dirname(hv_ir_path), in_file=os.path.basename(hv_ir_path), out_dir=output_dir, compile_time=(time.time() - tick), obj_counter=ir_counter ) def main() -> None: parser = argparse.ArgumentParser( description="A Heavy.IR to C-language translator.") parser.add_argument( "hv_ir_path", help="The path to the Heavy.IR file to read.") parser.add_argument( "--static_dir", default="./static", help="The path to the static C files.") parser.add_argument( "--output_dir", default="./out", help="") parser.add_argument( "--copyright", default=None, help="A string indicating the owner of the copyright.") parser.add_argument("-v", "--verbose", action="count") args = parser.parse_args() externs = ExternInfo() results = ir2c.compile( args.hv_ir_path, args.static_dir, args.output_dir, externs, args.copyright) if args.verbose: print("Total ir2c time: {0:.2f}ms".format(results.compile_time * 1000)) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739952822.5703619 hvcc-0.13.3/hvcc/generators/ir2c/ir2c_perf.py0000644000000000000000000001013514755311267015642 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import argparse import json import os from collections import Counter, defaultdict from typing import Dict from hvcc.types.IR import HeavyIRType, IRGraph class ir2c_perf: @classmethod def perf( cls, ir: IRGraph, blocksize: int = 512, mhz: int = 1000, verbose: bool = False ) -> Dict[str, Counter]: # read the hv.ir.json file with open(os.path.join(os.path.dirname(__file__), "../../core/json/heavy.ir.json"), "r") as f: HEAVY_IR_JSON = HeavyIRType(**json.load(f)).root objects: Counter = Counter() perf: Counter = Counter() per_object_perf: Dict[str, Counter] = defaultdict(Counter) for o in ir.signal.processOrder: obj_id = o.id obj_type = ir.objects[obj_id].type if obj_type in HEAVY_IR_JSON.keys(): objects[obj_type] += 1 obj_perf = HEAVY_IR_JSON[obj_type].perf assert obj_perf is not None c = Counter(obj_perf.model_dump()) perf = perf + c per_object_perf[obj_type] = per_object_perf[obj_type] + c else: print(f"ERROR: Unknown object type {obj_type}") if verbose: print("AVX: {0} cycles / {1} cycles per frame".format(perf["avx"], perf["avx"] / 8.0)) print(" {0} frames @ {1}MHz >= {2:.2f}us".format( blocksize, mhz, blocksize * perf["avx"] / 8.0 / mhz)) print() # new line print("SSE: {0} cycles / {1} cycles per frame".format(perf["sse"], perf["sse"] / 4.0)) print(" {0} frames @ {1}MHz >= {2:.2f}us".format( blocksize, mhz, blocksize * perf["sse"] / 4.0 / mhz)) print() # new line print("NEON: {0} cycles / {1} cycles per frame".format(perf["neon"], perf["neon"] / 4.0)) print(" {0} frames @ {1}MHz >= {2:.2f}us".format( blocksize, mhz, blocksize * perf["neon"] / 4.0 / mhz)) print() # new line print("{0:<4} {1:<5} {2:<16} {3}".format("CPU%", "#Objs", "Object Type", "Performance")) print("==== ===== ================ ===========") # print object in order of highest load items = per_object_perf.items() # items.sort(key=lambda o: o[1]["avx"], reverse=True) for k, v in items: if perf["avx"] > 0: print( "{2:>2.2g}% {3:<5} {0:<16} {1}".format(k, v, int(100.0 * v["avx"] / perf["avx"]), objects[k]) ) return per_object_perf def main() -> None: parser = argparse.ArgumentParser( description="A Heavy.IR to C-language translator.") parser.add_argument( "hv_ir_path", help="The path to the Heavy.IR file to read.") parser.add_argument("--mhz", default=1000, type=float, help="the CPU clock frequency in MHz") parser.add_argument("--blocksize", default=64, type=int, help="the number of frames per block") parser.add_argument("-v", "--verbose", action="count") args = parser.parse_args() # read the hv.ir.json file with open(args.hv_ir_path, "r") as f: ir = json.load(f) ir2c_perf.perf(ir, args.blocksize, args.mhz, args.verbose) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7612069 hvcc-0.13.3/hvcc/generators/ir2c/static/HeavyContext.cpp0000644000000000000000000002217314435670357020041 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HeavyContext.hpp" #include "HvTable.h" void defaultSendHook(HeavyContextInterface *context, const char *sendName, hv_uint32_t sendHash, const HvMessage *msg) { HeavyContext *thisContext = reinterpret_cast(context); const hv_uint32_t numBytes = sizeof(ReceiverMessagePair) + msg_getSize(msg) - sizeof(HvMessage); ReceiverMessagePair *p = reinterpret_cast(hLp_getWriteBuffer(&thisContext->outQueue, numBytes)); if (p != nullptr) { p->receiverHash = sendHash; msg_copyToBuffer(msg, (char *) &p->msg, msg_getSize(msg)); hLp_produce(&thisContext->outQueue, numBytes); } else { hv_assert(false && "::defaultSendHook - The out message queue is full and cannot accept more messages until they " "have been processed. Try increasing the outQueueKb size in the new_with_options() constructor."); } } HeavyContext::HeavyContext(double sampleRate, int poolKb, int inQueueKb, int outQueueKb) : sampleRate(sampleRate) { hv_assert(sampleRate > 0.0); // sample rate must be positive hv_assert(poolKb > 0); hv_assert(inQueueKb > 0); hv_assert(outQueueKb >= 0); blockStartTimestamp = 0; printHook = nullptr; userData = nullptr; // if outQueueKb is positive, then the outQueue is allocated and the default sendhook is set. // Otherwise outQueue and the sendhook are set to NULL. sendHook = (outQueueKb > 0) ? &defaultSendHook : nullptr; HV_SPINLOCK_RELEASE(inQueueLock); HV_SPINLOCK_RELEASE(outQueueLock); numBytes = sizeof(HeavyContext); numBytes += mq_initWithPoolSize(&mq, poolKb); numBytes += hLp_init(&inQueue, inQueueKb * 1024); numBytes += hLp_init(&outQueue, outQueueKb * 1024); // outQueueKb value of 0 sets everything to NULL } HeavyContext::~HeavyContext() { mq_free(&mq); hLp_free(&inQueue); hLp_free(&outQueue); } bool HeavyContext::sendBangToReceiver(hv_uint32_t receiverHash) { HvMessage *m = HV_MESSAGE_ON_STACK(1); msg_initWithBang(m, 0); bool success = sendMessageToReceiver(receiverHash, 0.0, m); return success; } bool HeavyContext::sendFloatToReceiver(hv_uint32_t receiverHash, float f) { HvMessage *m = HV_MESSAGE_ON_STACK(1); msg_initWithFloat(m, 0, f); bool success = sendMessageToReceiver(receiverHash, 0.0, m); return success; } bool HeavyContext::sendSymbolToReceiver(hv_uint32_t receiverHash, const char *s) { hv_assert(s != nullptr); HvMessage *m = HV_MESSAGE_ON_STACK(1); msg_initWithSymbol(m, 0, (char *) s); bool success = sendMessageToReceiver(receiverHash, 0.0, m); return success; } bool HeavyContext::sendMessageToReceiverV(hv_uint32_t receiverHash, double delayMs, const char *format, ...) { hv_assert(delayMs >= 0.0); hv_assert(format != nullptr); va_list ap; va_start(ap, format); const int numElem = (int) hv_strlen(format); HvMessage *m = HV_MESSAGE_ON_STACK(numElem); msg_init(m, numElem, blockStartTimestamp + (hv_uint32_t) (hv_max_d(0.0, delayMs)*getSampleRate()/1000.0)); for (int i = 0; i < numElem; i++) { switch (format[i]) { case 'b': msg_setBang(m, i); break; case 'f': msg_setFloat(m, i, (float) va_arg(ap, double)); break; case 'h': msg_setHash(m, i, (int) va_arg(ap, int)); break; case 's': msg_setSymbol(m, i, (char *) va_arg(ap, char *)); break; default: break; } } va_end(ap); bool success = sendMessageToReceiver(receiverHash, delayMs, m); return success; } bool HeavyContext::sendMessageToReceiver(hv_uint32_t receiverHash, double delayMs, HvMessage *m) { hv_assert(delayMs >= 0.0); hv_assert(m != nullptr); const hv_uint32_t timestamp = blockStartTimestamp + (hv_uint32_t) (hv_max_d(0.0, delayMs)*(getSampleRate()/1000.0)); ReceiverMessagePair *p = nullptr; HV_SPINLOCK_ACQUIRE(inQueueLock); const hv_uint32_t numBytes = sizeof(ReceiverMessagePair) + msg_getSize(m) - sizeof(HvMessage); p = (ReceiverMessagePair *) hLp_getWriteBuffer(&inQueue, numBytes); if (p != nullptr) { p->receiverHash = receiverHash; msg_copyToBuffer(m, (char *) &p->msg, msg_getSize(m)); msg_setTimestamp(&p->msg, timestamp); hLp_produce(&inQueue, numBytes); } else { hv_assert(false && "::sendMessageToReceiver - The input message queue is full and cannot accept more messages until they " "have been processed. Try increasing the inQueueKb size in the new_with_options() constructor."); } HV_SPINLOCK_RELEASE(inQueueLock); return (p != nullptr); } bool HeavyContext::cancelMessage(HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { return mq_removeMessage(&mq, m, sendMessage); } HvMessage *HeavyContext::scheduleMessageForObject(const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *), int letIndex) { HvMessage *n = mq_addMessageByTimestamp(&mq, m, letIndex, sendMessage); return n; } float *HeavyContext::getBufferForTable(hv_uint32_t tableHash) { HvTable *t = getTableForHash(tableHash); if (t != nullptr) { return hTable_getBuffer(t); } else return nullptr; } int HeavyContext::getLengthForTable(hv_uint32_t tableHash) { HvTable *t = getTableForHash(tableHash); if (t != nullptr) { return hTable_getLength(t); } else return 0; } bool HeavyContext::setLengthForTable(hv_uint32_t tableHash, hv_uint32_t newSampleLength) { HvTable *t = getTableForHash(tableHash); if (t != nullptr) { hTable_resize(t, newSampleLength); return true; } else return false; } void HeavyContext::lockAcquire() { HV_SPINLOCK_ACQUIRE(inQueueLock); } bool HeavyContext::lockTry() { HV_SPINLOCK_TRY(inQueueLock); } void HeavyContext::lockRelease() { HV_SPINLOCK_RELEASE(inQueueLock); } void HeavyContext::setInputMessageQueueSize(int inQueueKb) { hv_assert(inQueueKb > 0); hLp_free(&inQueue); hLp_init(&inQueue, inQueueKb*1024); } void HeavyContext::setOutputMessageQueueSize(int outQueueKb) { hv_assert(outQueueKb > 0); hLp_free(&outQueue); hLp_init(&outQueue, outQueueKb*1024); } bool HeavyContext::getNextSentMessage(hv_uint32_t *destinationHash, HvMessage *outMsg, hv_size_t msgLengthBytes) { *destinationHash = 0; ReceiverMessagePair *p = nullptr; hv_assert((sendHook == &defaultSendHook) && "::getNextSentMessage - this function won't do anything if the msg outQueue " "size is 0, or you've overriden the default sendhook."); if (sendHook == &defaultSendHook) { HV_SPINLOCK_ACQUIRE(outQueueLock); if (hLp_hasData(&outQueue)) { hv_uint32_t numBytes = 0; p = reinterpret_cast(hLp_getReadBuffer(&outQueue, &numBytes)); hv_assert((p != nullptr) && "::getNextSentMessage - something bad happened."); hv_assert(numBytes >= sizeof(ReceiverMessagePair)); hv_assert((numBytes <= msgLengthBytes) && "::getNextSentMessage - the sent message is bigger than the message " "passed to handle it."); *destinationHash = p->receiverHash; hv_memcpy(outMsg, &p->msg, numBytes); hLp_consume(&outQueue); } HV_SPINLOCK_RELEASE(outQueueLock); } return (p != nullptr); } hv_uint32_t HeavyContext::getHashForString(const char *str) { return hv_string_to_hash(str); } HvTable *_hv_table_get(HeavyContextInterface *c, hv_uint32_t tableHash) { hv_assert(c != nullptr); return reinterpret_cast(c)->getTableForHash(tableHash); } void _hv_scheduleMessageForReceiver(HeavyContextInterface *c, hv_uint32_t receiverHash, HvMessage *m) { hv_assert(c != nullptr); reinterpret_cast(c)->scheduleMessageForReceiver(receiverHash, m); } HvMessage *_hv_scheduleMessageForObject(HeavyContextInterface *c, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *), int letIndex) { hv_assert(c != nullptr); HvMessage *n = reinterpret_cast(c)->scheduleMessageForObject( m, sendMessage, letIndex); return n; } #ifdef __cplusplus extern "C" { #endif HvTable *hv_table_get(HeavyContextInterface *c, hv_uint32_t tableHash) { return _hv_table_get(c, tableHash); } void hv_scheduleMessageForReceiver(HeavyContextInterface *c, hv_uint32_t receiverHash, HvMessage *m) { _hv_scheduleMessageForReceiver(c, receiverHash, m); } HvMessage *hv_scheduleMessageForObject(HeavyContextInterface *c, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *), int letIndex) { return _hv_scheduleMessageForObject(c, m, sendMessage, letIndex); } #ifdef __cplusplus } #endif ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7612069 hvcc-0.13.3/hvcc/generators/ir2c/static/HeavyContext.hpp0000644000000000000000000001024614435670357020044 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTEXT_H_ #define _HEAVY_CONTEXT_H_ #include "HeavyContextInterface.hpp" #include "HvLightPipe.h" #include "HvMessageQueue.h" #include "HvMath.h" struct HvTable; class HeavyContext : public HeavyContextInterface { public: HeavyContext(double sampleRate, int poolKb=10, int inQueueKb=2, int outQueueKb=0); virtual ~HeavyContext(); int getSize() override { return (int) numBytes; } double getSampleRate() override { return sampleRate; } hv_uint32_t getCurrentSample() override { return blockStartTimestamp; } float samplesToMilliseconds(hv_uint32_t numSamples) override { return (float) (1000.0*numSamples/sampleRate); } hv_uint32_t millisecondsToSamples(float ms) override { return (hv_uint32_t) (hv_max_f(0.0f,ms)*sampleRate/1000.0); } void setUserData(void *x) override { userData = x; } void *getUserData() override { return userData; } // hook management void setSendHook(HvSendHook_t *f) override { sendHook = f; } HvSendHook_t *getSendHook() override { return sendHook; } void setPrintHook(HvPrintHook_t *f) override { printHook = f; } HvPrintHook_t *getPrintHook() override { return printHook; } // message scheduling bool sendMessageToReceiver(hv_uint32_t receiverHash, double delayMs, HvMessage *m) override; bool sendMessageToReceiverV(hv_uint32_t receiverHash, double delayMs, const char *fmt, ...) override; bool sendFloatToReceiver(hv_uint32_t receiverHash, float f) override; bool sendBangToReceiver(hv_uint32_t receiverHash) override; bool sendSymbolToReceiver(hv_uint32_t receiverHash, const char *symbol) override; bool cancelMessage(HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) override; // table manipulation float *getBufferForTable(hv_uint32_t tableHash) override; int getLengthForTable(hv_uint32_t tableHash) override; bool setLengthForTable(hv_uint32_t tableHash, hv_uint32_t newSampleLength) override; // lock control void lockAcquire() override; bool lockTry() override; void lockRelease() override; // message queue management void setInputMessageQueueSize(int inQueueKb) override; void setOutputMessageQueueSize(int outQueueKb) override; bool getNextSentMessage(hv_uint32_t *destinationHash, HvMessage *outMsg, hv_size_t msgLength) override; // utility functions static hv_uint32_t getHashForString(const char *str); protected: virtual HvTable *getTableForHash(hv_uint32_t tableHash) = 0; friend HvTable *_hv_table_get(HeavyContextInterface *, hv_uint32_t); virtual void scheduleMessageForReceiver(hv_uint32_t receiverHash, HvMessage *m) = 0; friend void _hv_scheduleMessageForReceiver(HeavyContextInterface *, hv_uint32_t, HvMessage *); HvMessage *scheduleMessageForObject(const HvMessage *, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *), int); friend HvMessage *_hv_scheduleMessageForObject(HeavyContextInterface *, const HvMessage *, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *), int); friend void defaultSendHook(HeavyContextInterface *, const char *, hv_uint32_t, const HvMessage *); // object state double sampleRate; hv_uint32_t blockStartTimestamp; hv_size_t numBytes; HvMessageQueue mq; HvSendHook_t *sendHook; HvPrintHook_t *printHook; void *userData; HvLightPipe inQueue; HvLightPipe outQueue; hv_atomic_bool inQueueLock; hv_atomic_bool outQueueLock; }; #endif // _HEAVY_CONTEXT_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7612069 hvcc-0.13.3/hvcc/generators/ir2c/static/HeavyContextInterface.hpp0000644000000000000000000002654614435670357021677 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTEXT_INTERFACE_H_ #define _HEAVY_CONTEXT_INTERFACE_H_ #include "HvUtils.h" #ifndef _HEAVY_DECLARATIONS_ #define _HEAVY_DECLARATIONS_ class HeavyContextInterface; struct HvMessage; typedef enum { HV_PARAM_TYPE_PARAMETER_IN, HV_PARAM_TYPE_PARAMETER_OUT, HV_PARAM_TYPE_EVENT_IN, HV_PARAM_TYPE_EVENT_OUT } HvParameterType; typedef struct HvParameterInfo { const char *name; // the human readable parameter name hv_uint32_t hash; // an integer identified used by heavy for this parameter HvParameterType type; // type of this parameter float minVal; // the minimum value of this parameter float maxVal; // the maximum value of this parameter float defaultVal; // the default value of this parameter } HvParameterInfo; typedef void (HvSendHook_t) (HeavyContextInterface *context, const char *sendName, hv_uint32_t sendHash, const HvMessage *msg); typedef void (HvPrintHook_t) (HeavyContextInterface *context, const char *printName, const char *str, const HvMessage *msg); #endif // _HEAVY_DECLARATIONS_ class HeavyContextInterface { public: HeavyContextInterface() {} virtual ~HeavyContextInterface() {}; /** Returns the read-only user-assigned name of this patch. */ virtual const char *getName() = 0; /** Returns the number of input channels with which this context has been configured. */ virtual int getNumInputChannels() = 0; /** Returns the number of output channels with which this context has been configured. */ virtual int getNumOutputChannels() = 0; /** * Returns the total size in bytes of the context. * This value may change if tables are resized. */ virtual int getSize() = 0; /** Returns the sample rate with which this context has been configured. */ virtual double getSampleRate() = 0; /** Returns the current patch time in samples. This value is always exact. */ virtual hv_uint32_t getCurrentSample() = 0; virtual float samplesToMilliseconds(hv_uint32_t numSamples) = 0; /** Converts milliseconds to samples. Input is limited to non-negative range. */ virtual hv_uint32_t millisecondsToSamples(float ms) = 0; /** Sets a user-definable value. This value is never manipulated by Heavy. */ virtual void setUserData(void *x) = 0; /** Returns the user-defined data. */ virtual void *getUserData() = 0; /** * Set the send hook. The function is called whenever a message is sent to any send object. * Messages returned by this function should NEVER be freed. If the message must persist, call * hv_msg_copy() first. */ virtual void setSendHook(HvSendHook_t *f) = 0; /** Returns the send hook, or NULL if unset. */ virtual HvSendHook_t *getSendHook() = 0; /** Set the print hook. The function is called whenever a message is sent to a print object. */ virtual void setPrintHook(HvPrintHook_t *f) = 0; /** Returns the print hook, or NULL if unset. */ virtual HvPrintHook_t *getPrintHook() = 0; /** * Processes one block of samples for a patch instance. The buffer format is an array of float channel arrays. * If the context has not input or output channels, the respective argument may be NULL. * The number of samples to to tbe processed should be a multiple of 1, 4, or 8, depending on if * no, SSE or NEON, or AVX optimisation is being used, respectively. * e.g. [[LLLL][RRRR]] * * @return The number of samples processed. * * This function is NOT thread-safe. It is assumed that only the audio thread will execute this function. */ virtual int process(float **inputBuffers, float **outputBuffer, int n) = 0; /** * Processes one block of samples for a patch instance. The buffer format is an uninterleaved float array of channels. * If the context has not input or output channels, the respective argument may be NULL. * The number of samples to to tbe processed should be a multiple of 1, 4, or 8, depending on if * no, SSE or NEON, or AVX optimisation is being used, respectively. * e.g. [LLLLRRRR] * * @return The number of samples processed. * * This function is NOT thread-safe. It is assumed that only the audio thread will execute this function. */ virtual int processInline(float *inputBuffers, float *outputBuffer, int n) = 0; /** * Processes one block of samples for a patch instance. The buffer format is an interleaved float array of channels. * If the context has not input or output channels, the respective argument may be NULL. * The number of samples to to tbe processed should be a multiple of 1, 4, or 8, depending on if * no, SSE or NEON, or AVX optimisation is being used, respectively. * e.g. [LRLRLRLR] * * @return The number of samples processed. * * This function is NOT thread-safe. It is assumed that only the audio thread will execute this function. */ virtual int processInlineInterleaved(float *inputBuffers, float *outputBuffer, int n) = 0; /** * Sends a formatted message to a receiver that can be scheduled for the future. * The receiver is addressed with its hash, which can also be determined using hv_stringToHash(). * This function is thread-safe. * * @return True if the message was accepted. False if the message could not fit onto * the message queue to be processed this block. */ virtual bool sendMessageToReceiver(hv_uint32_t receiverHash, double delayMs, HvMessage *m) = 0; /** * Sends a formatted message to a receiver that can be scheduled for the future. * The receiver is addressed with its hash, which can also be determined using hv_stringToHash(). * This function is thread-safe. * * @return True if the message was accepted. False if the message could not fit onto * the message queue to be processed this block. */ virtual bool sendMessageToReceiverV(hv_uint32_t receiverHash, double delayMs, const char *fmt, ...) = 0; /** * A convenience function to send a float to a receiver to be processed immediately. * The receiver is addressed with its hash, which can also be determined using hv_stringToHash(). * This function is thread-safe. * * @return True if the message was accepted. False if the message could not fit onto * the message queue to be processed this block. */ virtual bool sendFloatToReceiver(hv_uint32_t receiverHash, float f) = 0; /** * A convenience function to send a bang to a receiver to be processed immediately. * The receiver is addressed with its hash, which can also be determined using hv_stringToHash(). * This function is thread-safe. * * @return True if the message was accepted. False if the message could not fit onto * the message queue to be processed this block. */ virtual bool sendBangToReceiver(hv_uint32_t receiverHash) = 0; /** * A convenience function to send a symbol to a receiver to be processed immediately. * The receiver is addressed with its hash, which can also be determined using hv_stringToHash(). * This function is thread-safe. * * @return True if the message was accepted. False if the message could not fit onto * the message queue to be processed this block. */ virtual bool sendSymbolToReceiver(hv_uint32_t receiverHash, const char *symbol) = 0; /** * Cancels a previously scheduled message. * * @param sendMessage May be NULL. */ virtual bool cancelMessage(HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)=nullptr) = 0; /** * Returns information about each parameter such as name, hash, and range. * The total number of parameters is always returned. * * @param index The parameter index. * @param info A pointer to a HvParameterInfo struct. May be null. * * @return The total number of parameters. */ virtual int getParameterInfo(int index, HvParameterInfo *info) = 0; /** Returns a pointer to the raw buffer backing this table. DO NOT free it. */ virtual float *getBufferForTable(hv_uint32_t tableHash) = 0; /** Returns the length of this table in samples. */ virtual int getLengthForTable(hv_uint32_t tableHash) = 0; /** * Resizes the table to the given length. * * Existing contents are copied to the new table. Remaining space is cleared * if the table is longer than the original, truncated otherwise. * * @param tableHash The table identifier. * @param newSampleLength The new length of the table, in samples. * * @return False if the table could not be found. True otherwise. */ virtual bool setLengthForTable(hv_uint32_t tableHash, hv_uint32_t newSampleLength) = 0; /** * Acquire the input message queue lock. * * This function will block until the message lock as been acquired. * Typical applications will not require the use of this function. */ virtual void lockAcquire() = 0; /** * Try to acquire the input message queue lock. * * If the lock has been acquired, hv_lock_release() must be called to release it. * Typical applications will not require the use of this function. * * @return Returns true if the lock has been acquired, false otherwise. */ virtual bool lockTry() = 0; /** * Release the input message queue lock. * * Typical applications will not require the use of this function. */ virtual void lockRelease() = 0; /** * Set the size of the input message queue in kilobytes. * * The buffer is reset and all existing contents are lost on resize. * * @param inQueueKb Must be positive i.e. at least one. */ virtual void setInputMessageQueueSize(int inQueueKb) = 0; /** * Set the size of the output message queue in kilobytes. * * The buffer is reset and all existing contents are lost on resize. * Only the default sendhook uses the outgoing message queue. If the default * sendhook is not being used, then this function is not useful. * * @param outQueueKb Must be postive i.e. at least one. */ virtual void setOutputMessageQueueSize(int outQueueKb) = 0; /** * Get the next message in the outgoing queue, will also consume the message. * Returns false if there are no messages. * * @param destinationHash a hash of the name of the receiver the message was sent to. * @param outMsg message pointer that is filled by the next message contents. * @param msgLengthBytes max length of outMsg in bytes. * * @return True if there is a message in the outgoing queue. */ virtual bool getNextSentMessage(hv_uint32_t *destinationHash, HvMessage *outMsg, hv_size_t msgLengthBytes) = 0; /** Returns a 32-bit hash of any string. Returns 0 if string is NULL. */ static hv_uint32_t getHashForString(const char *str); }; #endif // _HEAVY_CONTEXT_INTERFACE_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7612069 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlBinop.c0000644000000000000000000000775014435670357017772 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlBinop.h" hv_size_t cBinop_init(ControlBinop *o, float k) { o->k = k; return 0; } static float cBinop_perform_op(BinopType op, float f, float k) { switch (op) { case HV_BINOP_ADD: return f + k; case HV_BINOP_SUBTRACT: return f - k; case HV_BINOP_MULTIPLY: return f * k; case HV_BINOP_DIVIDE: return (k != 0.0f) ? (f/k) : 0.0f; case HV_BINOP_INT_DIV: { const int ik = (int) k; return (ik != 0) ? (float) (((int) f) / ik) : 0.0f; } case HV_BINOP_MOD_BIPOLAR: { const int ik = (int) k; return (ik != 0) ? (float) (((int) f) % ik) : 0.0f; } case HV_BINOP_MOD_UNIPOLAR: { f = (k == 0.0f) ? 0.0f : (float) ((int) f % (int) k); return (f < 0.0f) ? f + hv_abs_f(k) : f; } case HV_BINOP_BIT_LEFTSHIFT: return (float) (((int) f) << ((int) k)); case HV_BINOP_BIT_RIGHTSHIFT: return (float) (((int) f) >> ((int) k)); case HV_BINOP_BIT_AND: return (float) ((int) f & (int) k); case HV_BINOP_BIT_XOR: return (float) ((int) f ^ (int) k); case HV_BINOP_BIT_OR: return (float) ((int) f | (int) k); case HV_BINOP_EQ: return (f == k) ? 1.0f : 0.0f; case HV_BINOP_NEQ: return (f != k) ? 1.0f : 0.0f; case HV_BINOP_LOGICAL_AND: return ((f == 0.0f) || (k == 0.0f)) ? 0.0f : 1.0f; case HV_BINOP_LOGICAL_OR: return ((f == 0.0f) && (k == 0.0f)) ? 0.0f : 1.0f; case HV_BINOP_LESS_THAN: return (f < k) ? 1.0f : 0.0f; case HV_BINOP_LESS_THAN_EQL: return (f <= k) ? 1.0f : 0.0f; case HV_BINOP_GREATER_THAN: return (f > k) ? 1.0f : 0.0f; case HV_BINOP_GREATER_THAN_EQL: return (f >= k) ? 1.0f : 0.0f; case HV_BINOP_MAX: return hv_max_f(f, k); case HV_BINOP_MIN: return hv_min_f(f, k); case HV_BINOP_POW: return (f > 0.0f) ? hv_pow_f(f, k) : 0.0f; case HV_BINOP_ATAN2: return ((f == 0.0f) && (k == 0.0f)) ? 0.0f : hv_atan2_f(f, k); default: return 0.0f; } } void cBinop_onMessage(HeavyContextInterface *_c, ControlBinop *o, BinopType op, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { switch (letIn) { case 0: { if (msg_isFloat(m, 0)) { // Note(joe): supporting Pd's ability to perform operations of packs // of floats is likely to not be supported in the future. if (msg_isFloat(m, 1)) o->k = msg_getFloat(m, 1); HvMessage *n = HV_MESSAGE_ON_STACK(1); float f = cBinop_perform_op(op, msg_getFloat(m, 0), o->k); msg_initWithFloat(n, msg_getTimestamp(m), f); sendMessage(_c, 0, n); } break; } case 1: { if (msg_isFloat(m, 0)) { o->k = msg_getFloat(m, 0); } break; } default: break; } } void cBinop_k_onMessage(HeavyContextInterface *_c, void *o, BinopType op, float k, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { if (msg_isFloat(m, 0)) { // NOTE(mhroth): Heavy does not support sending bangs to binop objects to return the previous output float f = (msg_isFloat(m, 1)) ? msg_getFloat(m, 1) : k; HvMessage *n = HV_MESSAGE_ON_STACK(1); f = cBinop_perform_op(op, msg_getFloat(m, 0), f); msg_initWithFloat(n, msg_getTimestamp(m), f); sendMessage(_c, 0, n); } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlBinop.h0000644000000000000000000000376114435670357017775 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_BINOP_H_ #define _HEAVY_CONTROL_BINOP_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef enum BinopType { HV_BINOP_ADD, HV_BINOP_SUBTRACT, HV_BINOP_MULTIPLY, HV_BINOP_DIVIDE, HV_BINOP_INT_DIV, HV_BINOP_MOD_BIPOLAR, HV_BINOP_MOD_UNIPOLAR, HV_BINOP_BIT_LEFTSHIFT, HV_BINOP_BIT_RIGHTSHIFT, HV_BINOP_BIT_AND, HV_BINOP_BIT_XOR, HV_BINOP_BIT_OR, HV_BINOP_EQ, HV_BINOP_NEQ, HV_BINOP_LOGICAL_AND, HV_BINOP_LOGICAL_OR, HV_BINOP_LESS_THAN, HV_BINOP_LESS_THAN_EQL, HV_BINOP_GREATER_THAN, HV_BINOP_GREATER_THAN_EQL, HV_BINOP_MAX, HV_BINOP_MIN, HV_BINOP_POW, HV_BINOP_ATAN2 } BinopType; typedef struct ControlBinop { float k; } ControlBinop; hv_size_t cBinop_init(ControlBinop *o, float k); void cBinop_onMessage(HeavyContextInterface *_c, ControlBinop *o, BinopType op, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); void cBinop_k_onMessage(HeavyContextInterface *_c, void *o, BinopType op, float k, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_BINOP_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlCast.c0000644000000000000000000000377014435670357017613 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlCast.h" void cCast_onMessage(HeavyContextInterface *_c, CastType castType, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { switch (castType) { case HV_CAST_BANG: { HvMessage *n = HV_MESSAGE_ON_STACK(1); msg_initWithBang(n, msg_getTimestamp(m)); sendMessage(_c, 0, n); break; } case HV_CAST_FLOAT: { if (msg_isFloat(m, 0)) { HvMessage *n = HV_MESSAGE_ON_STACK(1); msg_initWithFloat(n, msg_getTimestamp(m), msg_getFloat(m, 0)); sendMessage(_c, 0, n); } break; } case HV_CAST_SYMBOL: { switch (msg_getType(m, 0)) { case HV_MSG_BANG: { HvMessage *n = HV_MESSAGE_ON_STACK(1); msg_initWithSymbol(n, msg_getTimestamp(m), "bang"); sendMessage(_c, 0, n); break; } case HV_MSG_FLOAT: { HvMessage *n = HV_MESSAGE_ON_STACK(1); msg_initWithSymbol(n, msg_getTimestamp(m), "float"); sendMessage(_c, 0, n); break; } case HV_MSG_SYMBOL: { sendMessage(_c, 0, m); break; } default: return; } break; } default: return; } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlCast.h0000644000000000000000000000235014435670357017611 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_CAST_H_ #define _HEAVY_CONTROL_CAST_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef enum CastType { HV_CAST_BANG, HV_CAST_FLOAT, HV_CAST_SYMBOL } CastType; void cCast_onMessage(HeavyContextInterface *_c, CastType castType, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_CAST_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlDelay.c0000644000000000000000000000701514435670357017753 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlDelay.h" hv_size_t cDelay_init(HeavyContextInterface *_c, ControlDelay *o, float delayMs) { o->delay = hv_millisecondsToSamples(_c, delayMs); hv_memclear(o->msgs, __HV_DELAY_MAX_MESSAGES*sizeof(HvMessage *)); return 0; } void cDelay_onMessage(HeavyContextInterface *_c, ControlDelay *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { switch (letIn) { case 0: { if (msg_compareSymbol(m, 0, "flush")) { // send all messages immediately for (int i = 0; i < __HV_DELAY_MAX_MESSAGES; i++) { HvMessage *n = o->msgs[i]; if (n != NULL) { msg_setTimestamp(n, msg_getTimestamp(m)); // update the timestamp to now sendMessage(_c, 0, n); // send the message hv_cancelMessage(_c, n, sendMessage); // then clear it // NOTE(mhroth): there may be a problem here if a flushed message causes a clear message to return // to this object in the same step } } hv_memclear(o->msgs, __HV_DELAY_MAX_MESSAGES*sizeof(HvMessage *)); } else if (msg_compareSymbol(m, 0, "clear")) { // cancel (clear) all (pending) messages for (int i = 0; i < __HV_DELAY_MAX_MESSAGES; i++) { HvMessage *n = o->msgs[i]; if (n != NULL) { hv_cancelMessage(_c, n, sendMessage); } } hv_memclear(o->msgs, __HV_DELAY_MAX_MESSAGES*sizeof(HvMessage *)); } else { hv_uint32_t ts = msg_getTimestamp(m); msg_setTimestamp((HvMessage *) m, ts+o->delay); // update the timestamp to set the delay int i; for (i = 0; i < __HV_DELAY_MAX_MESSAGES; i++) { if (o->msgs[i] == NULL) { o->msgs[i] = hv_scheduleMessageForObject(_c, m, sendMessage, 0); break; } } hv_assert((i < __HV_DELAY_MAX_MESSAGES) && // scheduled message limit reached "[__delay] cannot track any more messages. Try increasing the size of __HV_DELAY_MAX_MESSAGES."); msg_setTimestamp((HvMessage *) m, ts); // return to the original timestamp } break; } case 1: { if (msg_isFloat(m,0)) { // set delay in milliseconds (cannot be negative!) o->delay = hv_millisecondsToSamples(_c, msg_getFloat(m,0)); } break; } case 2: { if (msg_isFloat(m,0)) { // set delay in samples (cannot be negative!) o->delay = (hv_uint32_t) hv_max_f(0.0f, msg_getFloat(m,0)); } break; } default: break; } } void cDelay_clearExecutingMessage(ControlDelay *o, const HvMessage *m) { for (int i = 0; i < __HV_DELAY_MAX_MESSAGES; ++i) { if (o->msgs[i] == m) { o->msgs[i] = NULL; break; } } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlDelay.h0000644000000000000000000000272614435670357017764 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_DELAY_H_ #define _HEAVY_CONTROL_DELAY_H_ #define __HV_DELAY_MAX_MESSAGES 8 #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct ControlDelay { hv_uint32_t delay; // delay in samples HvMessage *msgs[__HV_DELAY_MAX_MESSAGES]; } ControlDelay; hv_size_t cDelay_init(HeavyContextInterface *_c, ControlDelay *o, float delayMs); void cDelay_onMessage(HeavyContextInterface *_c, ControlDelay *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); void cDelay_clearExecutingMessage(ControlDelay *o, const HvMessage *m); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_DELAY_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlIf.c0000644000000000000000000000257514435670357017261 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlIf.h" hv_size_t cIf_init(ControlIf *o, bool k) { o->k = k; return 0; } void cIf_onMessage(HeavyContextInterface *_c, ControlIf *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { switch (letIn) { case 0: { // a "true" if will send the message from the right outlet // a "false" if gets sent out of the left outlet sendMessage(_c, o->k ? 1 : 0, m); break; } case 1: { if (msg_isFloat(m, 0)) { o->k = (msg_getFloat(m, 0) != 0.0f); } break; } default: return; } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlIf.h0000644000000000000000000000234214435670357017256 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_IF_H_ #define _HEAVY_CONTROL_IF_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct ControlIf { bool k; } ControlIf; hv_size_t cIf_init(ControlIf *o, bool k); void cIf_onMessage(HeavyContextInterface *_c, ControlIf *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_IF_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlPack.c0000644000000000000000000000471114435670357017573 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlPack.h" hv_size_t cPack_init(ControlPack *o, int nargs, ...) { hv_size_t numBytes = msg_getCoreSize(nargs); o->msg = (HvMessage *) hv_malloc(numBytes); hv_assert(o->msg != NULL); msg_init(o->msg, nargs, 0); // variable arguments are used as float initialisers for the pack elements va_list ap; va_start(ap, nargs); for (int i = 0; i < nargs; ++i) { msg_setFloat(o->msg, i, (float) va_arg(ap, double)); } va_end(ap); return numBytes; } void cPack_free(ControlPack *o) { hv_free(o->msg); } void cPack_onMessage(HeavyContextInterface *_c, ControlPack *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { // ensure let index is less than number elements in internal msg int numElements = msg_getNumElements(o->msg); switch (letIn) { case 0: { // first inlet stores all values of input msg and triggers an output for (int i = hv_min_i(numElements, msg_getNumElements(m))-1; i >= 0; --i) { switch (msg_getType(m, i)) { case HV_MSG_FLOAT: msg_setFloat(o->msg, i, msg_getFloat(m, i)); break; case HV_MSG_SYMBOL: case HV_MSG_HASH: msg_setHash(o->msg, i, msg_getHash(m, i)); break; default: break; } } msg_setTimestamp(o->msg, msg_getTimestamp(m)); sendMessage(_c, 0, o->msg); break; } default: { // rest of inlets just store values switch (msg_getType(m, 0)) { case HV_MSG_FLOAT: msg_setFloat(o->msg, letIn, msg_getFloat(m, 0)); break; case HV_MSG_SYMBOL: case HV_MSG_HASH: msg_setHash(o->msg, letIn, msg_getHash(m, 0)); break; default: break; } break; } } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlPack.h0000644000000000000000000000244614435670357017603 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_PACK_H_ #define _HEAVY_CONTROL_PACK_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct ControlPack { HvMessage *msg; } ControlPack; hv_size_t cPack_init(ControlPack *o, int nargs, ...); void cPack_free(ControlPack *o); void cPack_onMessage(HeavyContextInterface *_c, ControlPack *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_PACK_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlPrint.c0000644000000000000000000000201314435670357020002 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlPrint.h" void cPrint_onMessage(HeavyContextInterface *_c, const HvMessage *m, const char *name) { if (hv_getPrintHook(_c) != NULL) { char *s = msg_toString(m); hv_getPrintHook(_c)(_c, name, s, m); hv_free(s); } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlPrint.h0000644000000000000000000000210614435670357020012 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_PRINT_H_ #define _HEAVY_CONTROL_PRINT_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif void cPrint_onMessage(HeavyContextInterface *_c, const struct HvMessage *m, const char *name); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_PRINT_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1692673663.8688204 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlRandom.c0000644000000000000000000000324114471023200020105 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlRandom.h" // http://www.firstpr.com.au/dsp/rand31 // http://en.wikipedia.org/wiki/Lehmer_random_number_generator hv_size_t cRandom_init(ControlRandom *o, int seed) { o->state = (seed != 0) ? seed : 1; return 0; } void cRandom_onMessage(HeavyContextInterface *_c, ControlRandom *o, int inletIndex, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { switch (inletIndex) { case 0: { HvMessage *n = HV_MESSAGE_ON_STACK(1); o->state = (hv_uint32_t) ((((unsigned long long) o->state) * 279470273UL) % 4294967291UL); float f = ((float) (o->state >> 9)) * 0.00000011920929f; msg_initWithFloat(n, msg_getTimestamp(m), f); sendMessage(_c, 0, n); break; } case 1: { if (msg_isFloat(m,0)) { o->state = (hv_uint32_t) msg_getFloat(m,0); } break; } default: break; } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlRandom.h0000644000000000000000000000242414435670357020141 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_RANDOM_H_ #define _HEAVY_CONTROL_RANDOM_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct ControlRandom { hv_uint32_t state; } ControlRandom; hv_size_t cRandom_init(ControlRandom *o, int seed); void cRandom_onMessage(HeavyContextInterface *_c, ControlRandom *o, int letIndex, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_RANDOM_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlSlice.c0000644000000000000000000000414714435670357017757 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlSlice.h" hv_size_t cSlice_init(ControlSlice *o, int i, int n) { o->i = i; o->n = n; return 0; } void cSlice_onMessage(HeavyContextInterface *_c, ControlSlice *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { switch (letIn) { case 0: { // if the start point is greater than the number of elements in the source message, do nothing if (o->i < msg_getNumElements(m)) { int x = msg_getNumElements(m) - o->i; // number of elements in the new message if (o->n > 0) x = hv_min_i(x, o->n); HvMessage *n = HV_MESSAGE_ON_STACK(x); msg_init(n, x, msg_getTimestamp(m)); hv_memcpy(&n->elem, &m->elem+o->i, x*sizeof(Element)); sendMessage(_c, 0, n); } else { // if nothing can be sliced, send a bang out of the right outlet HvMessage *n = HV_MESSAGE_ON_STACK(1); msg_initWithBang(n, msg_getTimestamp(m)); sendMessage(_c, 1, n); } break; } case 1: { if (msg_isFloat(m,0)) { o->i = (int) msg_getFloat(m,0); if (msg_isFloat(m,1)) { o->n = (int) msg_getFloat(m,1); } } break; } case 2: { if (msg_isFloat(m,0)) { o->n = (int) msg_getFloat(m,0); } break; } default: break; } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlSlice.h0000644000000000000000000000245514435670357017764 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_SLICE_H_ #define _HEAVY_CONTROL_SLICE_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct ControlSlice { int i; // start index int n; // length of slice } ControlSlice; hv_size_t cSlice_init(ControlSlice *o, int i, int n); void cSlice_onMessage(HeavyContextInterface *_c, ControlSlice *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_SLICE_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlSystem.c0000644000000000000000000000435314435670357020203 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlSystem.h" void cSystem_onMessage(HeavyContextInterface *_c, void *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { HvMessage *n = HV_MESSAGE_ON_STACK(1); if (msg_compareSymbol(m, 0, "samplerate")) { msg_initWithFloat(n, msg_getTimestamp(m), (float) hv_getSampleRate(_c)); } else if (msg_compareSymbol(m, 0, "numInputChannels")) { msg_initWithFloat(n, msg_getTimestamp(m), (float) hv_getNumInputChannels(_c)); } else if (msg_compareSymbol(m, 0, "numOutputChannels")) { msg_initWithFloat(n, msg_getTimestamp(m), (float) hv_getNumOutputChannels(_c)); } else if (msg_compareSymbol(m, 0, "currentTime")) { msg_initWithFloat(n, msg_getTimestamp(m), (float) msg_getTimestamp(m)); } else if (msg_compareSymbol(m, 0, "table")) { // NOTE(mhroth): no need to check message format for symbols as table lookup will fail otherwise HvTable *table = hv_table_get(_c, msg_getHash(m,1)); if (table != NULL) { if (msg_compareSymbol(m, 2, "length")) { msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getLength(table)); } else if (msg_compareSymbol(m, 2, "size")) { msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getSize(table)); } else if (msg_compareSymbol(m, 2, "head")) { msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getHead(table)); } else return; } else return; } else return; sendMessage(_c, 0, n); } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlSystem.h0000644000000000000000000000221714435670357020205 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_SYSTEM_H_ #define _HEAVY_CONTROL_SYSTEM_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif void cSystem_onMessage(HeavyContextInterface *_c, void *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_SYSTEM_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlTabhead.c0000644000000000000000000000305114435670357020241 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlTabhead.h" hv_size_t cTabhead_init(ControlTabhead *o, HvTable *table) { o->table = table; return 0; } void cTabhead_onMessage(HeavyContextInterface *_c, ControlTabhead *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { switch (letIn) { case 0: { if (msg_getType(m,0) == HV_MSG_BANG) { // get current head of table HvMessage *n = HV_MESSAGE_ON_STACK(1); msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getHead(o->table)); sendMessage(_c, 0, n); } break; } case 1: { if (msg_isHashLike(m,0)) { // set a new table o->table = hv_table_get(_c, msg_getHash(m,0)); } break; } default: break; } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlTabhead.h0000644000000000000000000000245514435670357020255 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_TABHEAD_H_ #define _HEAVY_CONTROL_TABHEAD_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct ControlTabhead { struct HvTable *table; } ControlTabhead; hv_size_t cTabhead_init(ControlTabhead *o, struct HvTable *table); void cTabhead_onMessage(HeavyContextInterface *_c, ControlTabhead *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_TABHEAD_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1685549294.7622068 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlTabread.c0000644000000000000000000000321314435670357020253 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlTabread.h" hv_size_t cTabread_init(ControlTabread *o, struct HvTable *table) { o->table = table; return 0; } void cTabread_onMessage(HeavyContextInterface *_c, ControlTabread *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { switch (letIn) { case 0: { if (msg_isFloat(m,0) && msg_getFloat(m,0) >= 0.0f && o->table != NULL) { const hv_uint32_t x = (hv_uint32_t) msg_getFloat(m,0); if (x < hTable_getSize(o->table)) { HvMessage *n = HV_MESSAGE_ON_STACK(1); msg_initWithFloat(n, msg_getTimestamp(m), hTable_getBuffer(o->table)[x]); sendMessage(_c, 0, n); } } break; } case 1: { if (msg_isHashLike(m,0)) { o->table = hv_table_get(_c, msg_getHash(m,0)); } break; } default: return; } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlTabread.h0000644000000000000000000000244614435670357020267 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_TABREAD_H_ #define _HEAVY_CONTROL_TABREAD_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct ControlTabread { HvTable *table; } ControlTabread; hv_size_t cTabread_init(ControlTabread *o, struct HvTable *table); void cTabread_onMessage(HeavyContextInterface *_c, ControlTabread *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_TABREAD_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlTabwrite.c0000644000000000000000000000332614435670357020477 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlTabwrite.h" hv_size_t cTabwrite_init(ControlTabwrite *o, struct HvTable *table) { o->table = table; o->x = 0; return 0; } void cTabwrite_onMessage(HeavyContextInterface *_c, ControlTabwrite *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { switch (letIn) { case 0: { if (msg_isFloat(m,0) && o->table != NULL) { hTable_getBuffer(o->table)[o->x] = msg_getFloat(m,0); // update Y value } break; } case 1: { if (msg_isFloat(m,0) && msg_getFloat(m,0) >= 0.0f && o->table != NULL) { const hv_uint32_t x = (hv_uint32_t) msg_getFloat(m,0); if (x < hTable_getSize(o->table)) { o->x = x; // update X value } } break; } case 2: { if (msg_isHashLike(m,0)) { o->table = hv_table_get(_c,msg_getHash(m,0)); // update table } break; } default: return; } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlTabwrite.h0000644000000000000000000000251214435670357020500 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_TABRWRITE_H_ #define _HEAVY_CONTROL_TABRWRITE_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct ControlTabwrite { struct HvTable *table; hv_uint32_t x; } ControlTabwrite; hv_size_t cTabwrite_init(ControlTabwrite *o, struct HvTable *table); void cTabwrite_onMessage(HeavyContextInterface *_c, ControlTabwrite *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_TABRWRITE_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlUnop.c0000644000000000000000000000447714435670357017647 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlUnop.h" void cUnop_onMessage(HeavyContextInterface *_c, UnopType op, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { if (msg_isFloat(m, 0)) { float f = msg_getFloat(m, 0); switch (op) { case HV_UNOP_SIN: f = hv_sin_f(f); break; case HV_UNOP_SINH: f = hv_sinh_f(f); break; case HV_UNOP_COS: f = hv_cos_f(f); break; case HV_UNOP_COSH: f = hv_cosh_f(f); break; case HV_UNOP_TAN: f = hv_tan_f(f); break; case HV_UNOP_TANH: f = hv_tanh_f(f); break; case HV_UNOP_ASIN: f = hv_asin_f(f); break; case HV_UNOP_ASINH: f = hv_asinh_f(f); break; case HV_UNOP_ACOS: f = hv_acos_f(f); break; case HV_UNOP_ACOSH: f = hv_acosh_f(f); break; case HV_UNOP_ATAN: f = hv_atan_f(f); break; case HV_UNOP_ATANH: f = hv_atanh_f(f); break; case HV_UNOP_EXP: f = hv_exp_f(f); break; case HV_UNOP_ABS: f = hv_abs_f(f); break; case HV_UNOP_SQRT: f = (f > 0.0f) ? hv_sqrt_f(f) : 0.0f; break; case HV_UNOP_LOG: f = (f > 0.0f) ? hv_log_f(f) : 0.0f; break; case HV_UNOP_LOG2: f = (f > 0.0f) ? (1.442695040888963f*hv_log_f(f)) : 0.0f; break; case HV_UNOP_LOG10: f = (f > 0.0f) ? (0.434294481903252f*hv_log_f(f)) : 0.0f; break; case HV_UNOP_CEIL: f = hv_ceil_f(f); break; case HV_UNOP_FLOOR: f = hv_floor_f(f); break; case HV_UNOP_ROUND: f = hv_round_f(f); break; default: return; } HvMessage *n = HV_MESSAGE_ON_STACK(1); msg_initWithFloat(n, m->timestamp, f); sendMessage(_c, 0, n); } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlUnop.h0000644000000000000000000000300214435670357017633 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_UNOP_H_ #define _HEAVY_CONTROL_UNOP_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef enum UnopType { HV_UNOP_ASIN, HV_UNOP_ASINH, HV_UNOP_ACOS, HV_UNOP_ACOSH, HV_UNOP_ATAN, HV_UNOP_ATANH, HV_UNOP_SIN, HV_UNOP_SINH, HV_UNOP_COS, HV_UNOP_COSH, HV_UNOP_TAN, HV_UNOP_TANH, HV_UNOP_EXP, HV_UNOP_ABS, HV_UNOP_SQRT, HV_UNOP_LOG, HV_UNOP_LOG2, HV_UNOP_LOG10, HV_UNOP_CEIL, HV_UNOP_FLOOR, HV_UNOP_ROUND } UnopType; void cUnop_onMessage(HeavyContextInterface *_c, UnopType op, const struct HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const struct HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_UNOP_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlVar.c0000644000000000000000000000473514435670357017453 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvControlVar.h" hv_size_t cVar_init_f(ControlVar *o, float k) { o->e.type = HV_MSG_FLOAT; o->e.data.f = k; return 0; } hv_size_t cVar_init_s(ControlVar *o, const char *s) { o->e.type = HV_MSG_HASH; o->e.data.h = hv_string_to_hash(s); return 0; } void cVar_free(ControlVar *o) { // nothing to do } void cVar_onMessage(HeavyContextInterface *_c, ControlVar *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { switch (letIn) { case 0: { switch (msg_getType(m,0)) { case HV_MSG_BANG: { HvMessage *n = HV_MESSAGE_ON_STACK(1); if (o->e.type == HV_MSG_FLOAT) msg_initWithFloat(n, msg_getTimestamp(m), o->e.data.f); else if (o->e.type == HV_MSG_HASH) msg_initWithHash(n, msg_getTimestamp(m), o->e.data.h); else return; sendMessage(_c, 0, n); break; } case HV_MSG_FLOAT: { o->e.type = HV_MSG_FLOAT; o->e.data.f = msg_getFloat(m,0); sendMessage(_c, 0, m); break; } case HV_MSG_SYMBOL: case HV_MSG_HASH: { o->e.type = HV_MSG_HASH; o->e.data.h = msg_getHash(m,0); sendMessage(_c, 0, m); break; } default: return; } break; } case 1: { switch (msg_getType(m,0)) { case HV_MSG_FLOAT: { o->e.type = HV_MSG_FLOAT; o->e.data.f = msg_getFloat(m,0); break; } case HV_MSG_SYMBOL: case HV_MSG_HASH: { o->e.type = HV_MSG_HASH; o->e.data.h = msg_getHash(m,0); break; } default: break; } } default: return; } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvControlVar.h0000644000000000000000000000257114435670357017454 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_CONTROL_VAR_H_ #define _HEAVY_CONTROL_VAR_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct ControlVar { Element e; // type is only every HV_MSG_FLOAT or HV_MSG_HASH } ControlVar; hv_size_t cVar_init_f(ControlVar *o, float k); hv_size_t cVar_init_s(ControlVar *o, const char *s); void cVar_free(ControlVar *o); void cVar_onMessage(HeavyContextInterface *_c, ControlVar *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_CONTROL_VAR_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5961823 hvcc-0.13.3/hvcc/generators/ir2c/static/HvHeavy.cpp0000644000000000000000000002371014735300037016754 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HeavyContext.hpp" #ifdef __cplusplus extern "C" { #endif #if HV_APPLE #pragma mark - Heavy Table #endif HV_EXPORT bool hv_table_setLength(HeavyContextInterface *c, hv_uint32_t tableHash, hv_uint32_t newSampleLength) { hv_assert(c != nullptr); return c->setLengthForTable(tableHash, newSampleLength); } HV_EXPORT float *hv_table_getBuffer(HeavyContextInterface *c, hv_uint32_t tableHash) { hv_assert(c != nullptr); return c->getBufferForTable(tableHash); } HV_EXPORT hv_uint32_t hv_table_getLength(HeavyContextInterface *c, hv_uint32_t tableHash) { hv_assert(c != nullptr); return c->getLengthForTable(tableHash); } #if HV_APPLE #pragma mark - Heavy Message #endif HV_EXPORT hv_size_t hv_msg_getByteSize(hv_uint32_t numElements) { return msg_getCoreSize(numElements); } HV_EXPORT void hv_msg_init(HvMessage *m, int numElements, hv_uint32_t timestamp) { msg_init(m, numElements, timestamp); } HV_EXPORT hv_size_t hv_msg_getNumElements(const HvMessage *m) { return msg_getNumElements(m); } HV_EXPORT hv_uint32_t hv_msg_getTimestamp(const HvMessage *m) { return msg_getTimestamp(m); } HV_EXPORT void hv_msg_setTimestamp(HvMessage *m, hv_uint32_t timestamp) { msg_setTimestamp(m, timestamp); } HV_EXPORT bool hv_msg_isBang(const HvMessage *const m, int i) { return msg_isBang(m,i); } HV_EXPORT void hv_msg_setBang(HvMessage *m, int i) { msg_setBang(m,i); } HV_EXPORT bool hv_msg_isFloat(const HvMessage *const m, int i) { return msg_isFloat(m, i); } HV_EXPORT float hv_msg_getFloat(const HvMessage *const m, int i) { return msg_getFloat(m,i); } HV_EXPORT void hv_msg_setFloat(HvMessage *m, int i, float f) { msg_setFloat(m,i,f); } HV_EXPORT bool hv_msg_isSymbol(const HvMessage *const m, int i) { return msg_isSymbol(m,i); } HV_EXPORT const char *hv_msg_getSymbol(const HvMessage *const m, int i) { return msg_getSymbol(m,i); } HV_EXPORT void hv_msg_setSymbol(HvMessage *m, int i, const char *s) { msg_setSymbol(m,i,s); } HV_EXPORT bool hv_msg_isHash(const HvMessage *const m, int i) { return msg_isHash(m, i); } HV_EXPORT hv_uint32_t hv_msg_getHash(const HvMessage *const m, int i) { return msg_getHash(m, i); } HV_EXPORT bool hv_msg_hasFormat(const HvMessage *const m, const char *fmt) { return msg_hasFormat(m, fmt); } HV_EXPORT char *hv_msg_toString(const HvMessage *const m) { return msg_toString(m); } HV_EXPORT HvMessage *hv_msg_copy(const HvMessage *const m) { return msg_copy(m); } HV_EXPORT void hv_msg_free(HvMessage *m) { msg_free(m); } #if HV_APPLE #pragma mark - Heavy Common #endif HV_EXPORT int hv_getSize(HeavyContextInterface *c) { hv_assert(c != nullptr); return (int) c->getSize(); } HV_EXPORT double hv_getSampleRate(HeavyContextInterface *c) { hv_assert(c != nullptr); return c->getSampleRate(); } HV_EXPORT int hv_getNumInputChannels(HeavyContextInterface *c) { hv_assert(c != nullptr); return c->getNumInputChannels(); } HV_EXPORT int hv_getNumOutputChannels(HeavyContextInterface *c) { hv_assert(c != nullptr); return c->getNumOutputChannels(); } HV_EXPORT void hv_setPrintHook(HeavyContextInterface *c, HvPrintHook_t *f) { hv_assert(c != nullptr); c->setPrintHook(f); } HV_EXPORT HvPrintHook_t *hv_getPrintHook(HeavyContextInterface *c) { hv_assert(c != nullptr); return c->getPrintHook(); } HV_EXPORT void hv_setSendHook(HeavyContextInterface *c, HvSendHook_t *f) { hv_assert(c != nullptr); c->setSendHook(f); } HV_EXPORT hv_uint32_t hv_stringToHash(const char *s) { return hv_string_to_hash(s); } HV_EXPORT bool hv_sendBangToReceiver(HeavyContextInterface *c, hv_uint32_t receiverHash) { hv_assert(c != nullptr); return c->sendBangToReceiver(receiverHash); } HV_EXPORT bool hv_sendFloatToReceiver(HeavyContextInterface *c, hv_uint32_t receiverHash, float x) { hv_assert(c != nullptr); return c->sendFloatToReceiver(receiverHash, x); } HV_EXPORT bool hv_sendSymbolToReceiver(HeavyContextInterface *c, hv_uint32_t receiverHash, char *s) { hv_assert(c != nullptr); return c->sendSymbolToReceiver(receiverHash, s); } HV_EXPORT bool hv_sendMessageToReceiverV( HeavyContextInterface *c, hv_uint32_t receiverHash, double delayMs, const char *format, ...) { hv_assert(c != nullptr); hv_assert(delayMs >= 0.0); hv_assert(format != nullptr); va_list ap; va_start(ap, format); const int numElem = (int) hv_strlen(format); HvMessage *m = HV_MESSAGE_ON_STACK(numElem); msg_init(m, numElem, c->getCurrentSample() + (hv_uint32_t) (hv_max_d(0.0, delayMs)*c->getSampleRate()/1000.0)); for (int i = 0; i < numElem; i++) { switch (format[i]) { case 'b': msg_setBang(m, i); break; case 'f': msg_setFloat(m, i, (float) va_arg(ap, double)); break; case 'h': msg_setHash(m, i, (int) va_arg(ap, int)); break; case 's': msg_setSymbol(m, i, (char *) va_arg(ap, char *)); break; default: break; } } va_end(ap); return c->sendMessageToReceiver(receiverHash, delayMs, m); } HV_EXPORT bool hv_sendMessageToReceiverFF( HeavyContextInterface *c, hv_uint32_t receiverHash, double delayMs, double data1, double data2) { hv_assert(c != nullptr); hv_assert(delayMs >= 0.0); const int numElem = (int) 2; HvMessage *m = HV_MESSAGE_ON_STACK(numElem); msg_init(m, numElem, c->getCurrentSample() + (hv_uint32_t) (hv_max_d(0.0, delayMs)*c->getSampleRate()/1000.0)); msg_setFloat(m, 0, (float) data1); msg_setFloat(m, 1, (float) data2); return c->sendMessageToReceiver(receiverHash, delayMs, m); } HV_EXPORT bool hv_sendMessageToReceiverFFF( HeavyContextInterface *c, hv_uint32_t receiverHash, double delayMs, double data1, double data2, double data3) { hv_assert(c != nullptr); hv_assert(delayMs >= 0.0); const int numElem = (int) 3; HvMessage *m = HV_MESSAGE_ON_STACK(numElem); msg_init(m, numElem, c->getCurrentSample() + (hv_uint32_t) (hv_max_d(0.0, delayMs)*c->getSampleRate()/1000.0)); msg_setFloat(m, 0, (float) data1); msg_setFloat(m, 1, (float) data2); msg_setFloat(m, 2, (float) data3); return c->sendMessageToReceiver(receiverHash, delayMs, m); } HV_EXPORT bool hv_sendMessageToReceiver( HeavyContextInterface *c, hv_uint32_t receiverHash, double delayMs, HvMessage *m) { hv_assert(c != nullptr); return c->sendMessageToReceiver(receiverHash, delayMs, m); } HV_EXPORT void hv_cancelMessage(HeavyContextInterface *c, HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { hv_assert(c != nullptr); c->cancelMessage(m, sendMessage); } HV_EXPORT const char *hv_getName(HeavyContextInterface *c) { hv_assert(c != nullptr); return c->getName(); } HV_EXPORT void hv_setUserData(HeavyContextInterface *c, void *userData) { hv_assert(c != nullptr); c->setUserData(userData); } HV_EXPORT void *hv_getUserData(HeavyContextInterface *c) { hv_assert(c != nullptr); return c->getUserData(); } HV_EXPORT double hv_getCurrentTime(HeavyContextInterface *c) { hv_assert(c != nullptr); return (double) c->samplesToMilliseconds(c->getCurrentSample()); } HV_EXPORT hv_uint32_t hv_getCurrentSample(HeavyContextInterface *c) { hv_assert(c != nullptr); return c->getCurrentSample(); } HV_EXPORT float hv_samplesToMilliseconds(HeavyContextInterface *c, hv_uint32_t numSamples) { hv_assert(c != nullptr); return c->samplesToMilliseconds(numSamples); } HV_EXPORT hv_uint32_t hv_millisecondsToSamples(HeavyContextInterface *c, float ms) { hv_assert(c != nullptr); return c->millisecondsToSamples(ms); } HV_EXPORT int hv_getParameterInfo(HeavyContextInterface *c, int index, HvParameterInfo *info) { hv_assert(c != nullptr); return c->getParameterInfo(index, info); } HV_EXPORT void hv_lock_acquire(HeavyContextInterface *c) { hv_assert(c != nullptr); c->lockAcquire(); } HV_EXPORT bool hv_lock_try(HeavyContextInterface *c) { hv_assert(c != nullptr); return c->lockTry(); } HV_EXPORT void hv_lock_release(HeavyContextInterface *c) { hv_assert(c != nullptr); c->lockRelease(); } HV_EXPORT void hv_setInputMessageQueueSize(HeavyContextInterface *c, hv_uint32_t inQueueKb) { hv_assert(c != nullptr); c->setInputMessageQueueSize(inQueueKb); } HV_EXPORT void hv_setOutputMessageQueueSize(HeavyContextInterface *c, hv_uint32_t outQueueKb) { hv_assert(c != nullptr); c->setOutputMessageQueueSize(outQueueKb); } HV_EXPORT bool hv_getNextSentMessage(HeavyContextInterface *c, hv_uint32_t *destinationHash, HvMessage *outMsg, hv_uint32_t msgLength) { hv_assert(c != nullptr); hv_assert(destinationHash != nullptr); hv_assert(outMsg != nullptr); return c->getNextSentMessage(destinationHash, outMsg, msgLength); } #if HV_APPLE #pragma mark - Heavy Common #endif HV_EXPORT int hv_process(HeavyContextInterface *c, float **inputBuffers, float **outputBuffers, int n) { hv_assert(c != nullptr); return c->process(inputBuffers, outputBuffers, n); } HV_EXPORT int hv_processInline(HeavyContextInterface *c, float *inputBuffers, float *outputBuffers, int n) { hv_assert(c != nullptr); return c->processInline(inputBuffers, outputBuffers, n); } HV_EXPORT int hv_processInlineInterleaved(HeavyContextInterface *c, float *inputBuffers, float *outputBuffers, int n) { hv_assert(c != nullptr); return c->processInlineInterleaved(inputBuffers, outputBuffers, n); } HV_EXPORT void hv_delete(HeavyContextInterface *c) { delete c; } #ifdef __cplusplus } #endif ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5971823 hvcc-0.13.3/hvcc/generators/ir2c/static/HvHeavy.h0000644000000000000000000004015214735300037016420 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_H_ #define _HEAVY_H_ #include "HvUtils.h" #ifdef __cplusplus extern "C" { #endif #ifndef _HEAVY_DECLARATIONS_ #define _HEAVY_DECLARATIONS_ #ifdef __cplusplus class HeavyContextInterface; #else typedef struct HeavyContextInterface HeavyContextInterface; #endif typedef struct HvMessage HvMessage; typedef enum { HV_PARAM_TYPE_PARAMETER_IN, HV_PARAM_TYPE_PARAMETER_OUT, HV_PARAM_TYPE_EVENT_IN, HV_PARAM_TYPE_EVENT_OUT } HvParameterType; typedef struct HvParameterInfo { const char *name; // the human readable parameter name hv_uint32_t hash; // an integer identified used by heavy for this parameter HvParameterType type; // type of this parameter float minVal; // the minimum value of this parameter float maxVal; // the maximum value of this parameter float defaultVal; // the default value of this parameter } HvParameterInfo; typedef void (HvSendHook_t) (HeavyContextInterface *context, const char *sendName, hv_uint32_t sendHash, const HvMessage *msg); typedef void (HvPrintHook_t) (HeavyContextInterface *context, const char *printName, const char *str, const HvMessage *msg); #endif // _HEAVY_DECLARATIONS_ #if HV_APPLE #pragma mark - Heavy Context #endif /** Deletes a patch instance. */ void hv_delete(HeavyContextInterface *c); #if HV_APPLE #pragma mark - Heavy Process #endif /** * Processes one block of samples for a patch instance. The buffer format is an array of float channel arrays. * If the context has not input or output channels, the respective argument may be NULL. * The number of samples to to tbe processed should be a multiple of 1, 4, or 8, depending on if * no, SSE or NEON, or AVX optimisation is being used, respectively. * e.g. [[LLLL][RRRR]] * This function support in-place processing. * * @return The number of samples processed. * * This function is NOT thread-safe. It is assumed that only the audio thread will execute this function. */ int hv_process(HeavyContextInterface *c, float **inputBuffers, float **outputBuffers, int n); /** * Processes one block of samples for a patch instance. The buffer format is an uninterleaved float array of channels. * If the context has not input or output channels, the respective argument may be NULL. * The number of samples to to tbe processed should be a multiple of 1, 4, or 8, depending on if * no, SSE or NEON, or AVX optimisation is being used, respectively. * e.g. [LLLLRRRR] * This function support in-place processing. * * @return The number of samples processed. * * This function is NOT thread-safe. It is assumed that only the audio thread will execute this function. */ int hv_processInline(HeavyContextInterface *c, float *inputBuffers, float *outputBuffers, int n); /** * Processes one block of samples for a patch instance. The buffer format is an interleaved float array of channels. * If the context has not input or output channels, the respective argument may be NULL. * The number of samples to to tbe processed should be a multiple of 1, 4, or 8, depending on if * no, SSE or NEON, or AVX optimisation is being used, respectively. * e.g. [LRLRLRLR] * This function support in-place processing. * * @return The number of samples processed. * * This function is NOT thread-safe. It is assumed that only the audio thread will execute this function. */ int hv_processInlineInterleaved(HeavyContextInterface *c, float *inputBuffers, float *outputBuffers, int n); #if HV_APPLE #pragma mark - Heavy Common #endif /** * Returns the total size in bytes of the context. * This value may change if tables are resized. */ int hv_getSize(HeavyContextInterface *c); /** Returns the sample rate with which this context has been configured. */ double hv_getSampleRate(HeavyContextInterface *c); /** Returns the number of input channels with which this context has been configured. */ int hv_getNumInputChannels(HeavyContextInterface *c); /** Returns the number of output channels with which this context has been configured. */ int hv_getNumOutputChannels(HeavyContextInterface *c); /** Set the print hook. The function is called whenever a message is sent to a print object. */ void hv_setPrintHook(HeavyContextInterface *c, HvPrintHook_t *f); /** Returns the print hook, or NULL. */ HvPrintHook_t *hv_getPrintHook(HeavyContextInterface *c); /** * Set the send hook. The function is called whenever a message is sent to any send object. * Messages returned by this function should NEVER be freed. If the message must persist, call * hv_msg_copy() first. */ void hv_setSendHook(HeavyContextInterface *c, HvSendHook_t *f); /** Returns a 32-bit hash of any string. Returns 0 if string is NULL. */ hv_uint32_t hv_stringToHash(const char *s); /** * A convenience function to send a bang to a receiver to be processed immediately. * The receiver is addressed with its hash, which can also be determined using hv_stringToHash(). * This function is thread-safe. * * @return True if the message was accepted. False if the message could not fit onto * the message queue to be processed this block. */ bool hv_sendBangToReceiver(HeavyContextInterface *c, hv_uint32_t receiverHash); /** * A convenience function to send a float to a receiver to be processed immediately. * The receiver is addressed with its hash, which can also be determined using hv_stringToHash(). * This function is thread-safe. * * @return True if the message was accepted. False if the message could not fit onto * the message queue to be processed this block. */ bool hv_sendFloatToReceiver(HeavyContextInterface *c, hv_uint32_t receiverHash, const float x); /** * A convenience function to send a symbol to a receiver to be processed immediately. * The receiver is addressed with its hash, which can also be determined using hv_stringToHash(). * This function is thread-safe. * * @return True if the message was accepted. False if the message could not fit onto * the message queue to be processed this block. */ bool hv_sendSymbolToReceiver(HeavyContextInterface *c, hv_uint32_t receiverHash, char *s); /** * Sends a formatted message to a receiver that can be scheduled for the future. * The receiver is addressed with its hash, which can also be determined using hv_stringToHash(). * This function is thread-safe. * * @return True if the message was accepted. False if the message could not fit onto * the message queue to be processed this block. */ bool hv_sendMessageToReceiverV(HeavyContextInterface *c, hv_uint32_t receiverHash, double delayMs, const char *format, ...); /** * Sends a fixed formatted message of two floats to a receiver that can be scheduled for the future. * The receiver is addressed with its hash, which can also be determined using hv_stringToHash(). * This function is thread-safe. * * @return True if the message was accepted. False if the message could not fit onto * the message queue to be processed this block. */ bool hv_sendMessageToReceiverFF(HeavyContextInterface *c, hv_uint32_t receiverHash, double delayMs, double data1, double data2); /** * Sends a fixed formatted message of three floats to a receiver that can be scheduled for the future. * The receiver is addressed with its hash, which can also be determined using hv_stringToHash(). * This function is thread-safe. * * @return True if the message was accepted. False if the message could not fit onto * the message queue to be processed this block. */ bool hv_sendMessageToReceiverFFF(HeavyContextInterface *c, hv_uint32_t receiverHash, double delayMs, double data1, double data2, double data3); /** * Sends a message to a receiver that can be scheduled for the future. * The receiver is addressed with its hash, which can also be determined using hv_stringToHash(). * This function is thread-safe. * * @return True if the message was accepted. False if the message could not fit onto * the message queue to be processed this block. */ bool hv_sendMessageToReceiver(HeavyContextInterface *c, hv_uint32_t receiverHash, double delayMs, HvMessage *m); /** * Cancels a previously scheduled message. * * @param sendMessage May be NULL. */ void hv_cancelMessage(HeavyContextInterface *c, HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); /** Returns the read-only user-assigned name of this patch. */ const char *hv_getName(HeavyContextInterface *c); /** Sets a user-definable value. This value is never manipulated by Heavy. */ void hv_setUserData(HeavyContextInterface *c, void *userData); /** Returns the user-defined data. */ void *hv_getUserData(HeavyContextInterface *c); /** Returns the current patch time in milliseconds. This value may have rounding errors. */ double hv_getCurrentTime(HeavyContextInterface *c); /** Returns the current patch time in samples. This value is always exact. */ hv_uint32_t hv_getCurrentSample(HeavyContextInterface *c); /** * Returns information about each parameter such as name, hash, and range. * The total number of parameters is always returned. * * @param index The parameter index. * @param info A pointer to a HvParameterInfo struct. May be null. * * @return The total number of parameters. */ int hv_getParameterInfo(HeavyContextInterface *c, int index, HvParameterInfo *info); /** */ float hv_samplesToMilliseconds(HeavyContextInterface *c, hv_uint32_t numSamples); /** Converts milliseconds to samples. Input is limited to non-negative range. */ hv_uint32_t hv_millisecondsToSamples(HeavyContextInterface *c, float ms); /** * Acquire the input message queue lock. * * This function will block until the message lock as been acquired. * Typical applications will not require the use of this function. * * @param c A Heavy context. */ void hv_lock_acquire(HeavyContextInterface *c); /** * Try to acquire the input message queue lock. * * If the lock has been acquired, hv_lock_release() must be called to release it. * Typical applications will not require the use of this function. * * @param c A Heavy context. * * @return Returns true if the lock has been acquired, false otherwise. */ bool hv_lock_try(HeavyContextInterface *c); /** * Release the input message queue lock. * * Typical applications will not require the use of this function. * * @param c A Heavy context. */ void hv_lock_release(HeavyContextInterface *c); /** * Set the size of the input message queue in kilobytes. * * The buffer is reset and all existing contents are lost on resize. * * @param c A Heavy context. * @param inQueueKb Must be positive i.e. at least one. */ void hv_setInputMessageQueueSize(HeavyContextInterface *c, hv_uint32_t inQueueKb); /** * Set the size of the output message queue in kilobytes. * * The buffer is reset and all existing contents are lost on resize. * Only the default sendhook uses the outgoing message queue. If the default * sendhook is not being used, then this function is not useful. * * @param c A Heavy context. * @param outQueueKb Must be postive i.e. at least one. */ void hv_setOutputMessageQueueSize(HeavyContextInterface *c, hv_uint32_t outQueueKb); /** * Get the next message in the outgoing queue, will also consume the message. * Returns false if there are no messages. * * @param c A Heavy context. * @param destinationHash a hash of the name of the receiver the message was sent to. * @param outMsg message pointer that is filled by the next message contents. * @param msgLength length of outMsg in bytes. * * @return True if there is a message in the outgoing queue. */ bool hv_getNextSentMessage(HeavyContextInterface *c, hv_uint32_t *destinationHash, HvMessage *outMsg, hv_uint32_t msgLength); #if HV_APPLE #pragma mark - Heavy Message #endif typedef struct HvMessage HvMessage; /** Returns the total size in bytes of a HvMessage with a number of elements on the heap. */ unsigned long hv_msg_getByteSize(hv_uint32_t numElements); /** Initialise a HvMessage structure with the number of elements and a timestamp (in samples). */ void hv_msg_init(HvMessage *m, int numElements, hv_uint32_t timestamp); /** Returns the number of elements in this message. */ unsigned long hv_msg_getNumElements(const HvMessage *m); /** Returns the time at which this message exists (in samples). */ hv_uint32_t hv_msg_getTimestamp(const HvMessage *m); /** Set the time at which this message should be executed (in samples). */ void hv_msg_setTimestamp(HvMessage *m, hv_uint32_t timestamp); /** Returns true of the indexed element is a bang. False otherwise. Index is not bounds checked. */ bool hv_msg_isBang(const HvMessage *const m, int i); /** Sets the indexed element to a bang. Index is not bounds checked. */ void hv_msg_setBang(HvMessage *m, int i); /** Returns true of the indexed element is a float. False otherwise. Index is not bounds checked. */ bool hv_msg_isFloat(const HvMessage *const m, int i); /** Returns the indexed element as a float value. Index is not bounds checked. */ float hv_msg_getFloat(const HvMessage *const m, int i); /** Sets the indexed element to float value. Index is not bounds checked. */ void hv_msg_setFloat(HvMessage *m, int i, float f); /** Returns true of the indexed element is a symbol. False otherwise. Index is not bounds checked. */ bool hv_msg_isSymbol(const HvMessage *const m, int i); /** Returns the indexed element as a symbol value. Index is not bounds checked. */ const char *hv_msg_getSymbol(const HvMessage *const m, int i); /** Returns true of the indexed element is a hash. False otherwise. Index is not bounds checked. */ bool hv_msg_isHash(const HvMessage *const m, int i); /** Returns the indexed element as a hash value. Index is not bounds checked. */ hv_uint32_t hv_msg_getHash(const HvMessage *const m, int i); /** Sets the indexed element to symbol value. Index is not bounds checked. */ void hv_msg_setSymbol(HvMessage *m, int i, const char *s); /** * Returns true if the message has the given format, in number of elements and type. False otherwise. * Valid element types are: * 'b': bang * 'f': float * 's': symbol * * For example, a message with three floats would have a format of "fff". A single bang is "b". * A message with two symbols is "ss". These types can be mixed and matched in any way. */ bool hv_msg_hasFormat(const HvMessage *const m, const char *fmt); /** * Returns a basic string representation of the message. * The character array MUST be deallocated by the caller. */ char *hv_msg_toString(const HvMessage *const m); /** Copy a message onto the stack. The message persists. */ HvMessage *hv_msg_copy(const HvMessage *const m); /** Free a copied message. */ void hv_msg_free(HvMessage *m); #if HV_APPLE #pragma mark - Heavy Table #endif /** * Resizes the table to the given length. * * Existing contents are copied to the new table. Remaining space is cleared * if the table is longer than the original, truncated otherwise. * * @param tableHash The table identifier. * @param newSampleLength The new length of the table, in samples. Must be positive. * * @return False if the table could not be found. True otherwise. */ bool hv_table_setLength(HeavyContextInterface *c, hv_uint32_t tableHash, hv_uint32_t newSampleLength); /** Returns a pointer to the raw buffer backing this table. DO NOT free it. */ float *hv_table_getBuffer(HeavyContextInterface *c, hv_uint32_t tableHash); /** Returns the length of this table in samples. */ hv_uint32_t hv_table_getLength(HeavyContextInterface *c, hv_uint32_t tableHash); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvHeavyInternal.h0000644000000000000000000000260414435670357020131 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_INTERNAL_H_ #define _HEAVY_INTERNAL_H_ #include "HvHeavy.h" #include "HvUtils.h" #include "HvTable.h" #include "HvMessage.h" #include "HvMath.h" #ifdef __cplusplus extern "C" { #endif /** * */ HvTable *hv_table_get(HeavyContextInterface *c, hv_uint32_t tableHash); /** * */ void hv_scheduleMessageForReceiver(HeavyContextInterface *c, hv_uint32_t receiverHash, HvMessage *m); /** * */ HvMessage *hv_scheduleMessageForObject(HeavyContextInterface *c, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *), int letIndex); #ifdef __cplusplus } #endif #endif ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvLightPipe.c0000644000000000000000000001130314435670357017234 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvLightPipe.h" #if __SSE__ || HV_SIMD_SSE #include #define hv_sfence() _mm_sfence() #elif __arm__ || HV_SIMD_NEON #if __ARM_ACLE #include // https://msdn.microsoft.com/en-us/library/hh875058.aspx#BarrierRestrictions // http://doxygen.reactos.org/d8/d47/armintr_8h_a02be7ec76ca51842bc90d9b466b54752.html #define hv_sfence() __dmb(0xE) /* _ARM_BARRIER_ST */ #elif defined(__GNUC__) #define hv_sfence() __asm__ volatile ("dmb 0xE":::"memory") #else // http://stackoverflow.com/questions/19965076/gcc-memory-barrier-sync-synchronize-vs-asm-volatile-memory #define hv_sfence() __sync_synchronize() #endif #elif HV_WIN // https://msdn.microsoft.com/en-us/library/windows/desktop/ms684208(v=vs.85).aspx #define hv_sfence() _WriteBarrier() #else #define hv_sfence() __asm__ volatile("" : : : "memory") #endif #define HLP_STOP 0 #define HLP_LOOP 0xFFFFFFFF #define HLP_SET_UINT32_AT_BUFFER(a, b) (*((hv_uint32_t *) (a)) = (b)) #define HLP_GET_UINT32_AT_BUFFER(a) (*((hv_uint32_t *) (a))) hv_uint32_t hLp_init(HvLightPipe *q, hv_uint32_t numBytes) { if (numBytes > 0) { q->buffer = (char *) hv_malloc(numBytes); hv_assert(q->buffer != NULL); HLP_SET_UINT32_AT_BUFFER(q->buffer, HLP_STOP); } else { q->buffer = NULL; } q->writeHead = q->buffer; q->readHead = q->buffer; q->len = numBytes; q->remainingBytes = numBytes; return numBytes; } void hLp_free(HvLightPipe *q) { hv_free(q->buffer); } hv_uint32_t hLp_hasData(HvLightPipe *q) { hv_uint32_t x = HLP_GET_UINT32_AT_BUFFER(q->readHead); if (x == HLP_LOOP) { q->readHead = q->buffer; x = HLP_GET_UINT32_AT_BUFFER(q->readHead); } return x; } char *hLp_getWriteBuffer(HvLightPipe *q, hv_uint32_t bytesToWrite) { char *const readHead = q->readHead; char *const oldWriteHead = q->writeHead; const hv_uint32_t totalByteRequirement = bytesToWrite + 2*sizeof(hv_uint32_t); // check if there is enough space to write the data in the remaining // length of the buffer if (totalByteRequirement <= q->remainingBytes) { char *const newWriteHead = oldWriteHead + sizeof(hv_uint32_t) + bytesToWrite; // check if writing would overwrite existing data in the pipe (return NULL if so) if ((oldWriteHead < readHead) && (newWriteHead >= readHead)) return NULL; else return (oldWriteHead + sizeof(hv_uint32_t)); } else { // there isn't enough space, try looping around to the start if (totalByteRequirement <= q->len) { if ((oldWriteHead < readHead) || ((q->buffer + totalByteRequirement) > readHead)) { return NULL; // overwrite condition } else { q->writeHead = q->buffer; q->remainingBytes = q->len; HLP_SET_UINT32_AT_BUFFER(q->buffer, HLP_STOP); hv_sfence(); HLP_SET_UINT32_AT_BUFFER(oldWriteHead, HLP_LOOP); return q->buffer + sizeof(hv_uint32_t); } } else { return NULL; // there isn't enough space to write the data } } } void hLp_produce(HvLightPipe *q, hv_uint32_t numBytes) { hv_assert(q->remainingBytes >= (numBytes + 2*sizeof(hv_uint32_t))); q->remainingBytes -= (sizeof(hv_uint32_t) + numBytes); char *const oldWriteHead = q->writeHead; q->writeHead += (sizeof(hv_uint32_t) + numBytes); HLP_SET_UINT32_AT_BUFFER(q->writeHead, HLP_STOP); // save everything before this point to memory hv_sfence(); // then save this HLP_SET_UINT32_AT_BUFFER(oldWriteHead, numBytes); } char *hLp_getReadBuffer(HvLightPipe *q, hv_uint32_t *numBytes) { *numBytes = HLP_GET_UINT32_AT_BUFFER(q->readHead); char *const readBuffer = q->readHead + sizeof(hv_uint32_t); return readBuffer; } void hLp_consume(HvLightPipe *q) { hv_assert(HLP_GET_UINT32_AT_BUFFER(q->readHead) != HLP_STOP); q->readHead += sizeof(hv_uint32_t) + HLP_GET_UINT32_AT_BUFFER(q->readHead); } void hLp_reset(HvLightPipe *q) { q->writeHead = q->buffer; q->readHead = q->buffer; q->remainingBytes = q->len; memset(q->buffer, 0, q->len); } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvLightPipe.h0000644000000000000000000000631214435670357017245 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_LIGHTPIPE_H_ #define _HEAVY_LIGHTPIPE_H_ #include "HvUtils.h" #ifdef __cplusplus extern "C" { #endif /* * This pipe assumes that there is only one producer thread and one consumer * thread. This data structure does not support any other configuration. */ typedef struct HvLightPipe { char *buffer; char *writeHead; char *readHead; hv_uint32_t len; hv_uint32_t remainingBytes; // total bytes from write head to end } HvLightPipe; /** * Initialise the pipe with a given length, in bytes. * @return Returns the size of the pipe in bytes. */ hv_uint32_t hLp_init(HvLightPipe *q, hv_uint32_t numBytes); /** * Frees the internal buffer. * @param q The light pipe. */ void hLp_free(HvLightPipe *q); /** * Indicates if data is available for reading. * @param q The light pipe. * * @return Returns the number of bytes available for reading. Zero if no bytes * are available. */ hv_uint32_t hLp_hasData(HvLightPipe *q); /** * Returns a pointer to a location in the pipe where numBytes can be written. * * @param numBytes The number of bytes to be written. * @return A pointer to a location where those bytes can be written. Returns * NULL if no more space is available. Successive calls to this * function may eventually return a valid pointer because the readhead * has been advanced on another thread. */ char *hLp_getWriteBuffer(HvLightPipe *q, hv_uint32_t numBytes); /** * Indicates to the pipe how many bytes have been written. * * @param numBytes The number of bytes written. In general this should be the * same value as was passed to the preceeding call to * hLp_getWriteBuffer(). */ void hLp_produce(HvLightPipe *q, hv_uint32_t numBytes); /** * Returns the current read buffer, indicating the number of bytes available * for reading. * @param q The light pipe. * @param numBytes This value will be filled with the number of bytes available * for reading. * * @return A pointer to the read buffer. */ char *hLp_getReadBuffer(HvLightPipe *q, hv_uint32_t *numBytes); /** * Indicates that the next set of bytes have been read and are no longer needed. * @param q The light pipe. */ void hLp_consume(HvLightPipe *q); // resets the queue to it's initialised state // This should be done when only one thread is accessing the pipe. void hLp_reset(HvLightPipe *q); #ifdef __cplusplus } #endif #endif // _HEAVY_LIGHTPIPE_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5971823 hvcc-0.13.3/hvcc/generators/ir2c/static/HvMath.h0000644000000000000000000005253514735300037016245 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_MATH_H_ #define _HEAVY_MATH_H_ #include "HvUtils.h" // https://software.intel.com/sites/landingpage/IntrinsicsGuide/ // https://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/ARM-NEON-Intrinsics.html // http://codesuppository.blogspot.co.uk/2015/02/sse2neonh-porting-guide-and-header-file.html static inline void __hv_zero_f(hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_setzero_ps(); #elif HV_SIMD_SSE *bOut = _mm_setzero_ps(); #elif HV_SIMD_NEON *bOut = vdupq_n_f32(0.0f); #else // HV_SIMD_NONE *bOut = 0.0f; #endif } static inline void __hv_zero_i(hv_bOuti_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_setzero_si256(); #elif HV_SIMD_SSE *bOut = _mm_setzero_si128(); #elif HV_SIMD_NEON *bOut = vdupq_n_s32(0); #else // HV_SIMD_NONE *bOut = 0; #endif } static inline void __hv_load_f(float *bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_load_ps(bIn); #elif HV_SIMD_SSE *bOut = _mm_load_ps(bIn); #elif HV_SIMD_NEON *bOut = vld1q_f32(bIn); #else // HV_SIMD_NONE *bOut = *bIn; #endif } static inline void __hv_store_f(float *bOut, hv_bInf_t bIn) { #if HV_SIMD_AVX _mm256_store_ps(bOut, bIn); #elif HV_SIMD_SSE _mm_store_ps(bOut, bIn); #elif HV_SIMD_NEON vst1q_f32(bOut, bIn); #else // HV_SIMD_NONE *bOut = bIn; #endif } static inline void __hv_log2_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_log2_f() not implemented #elif HV_SIMD_SSE // https://en.wikipedia.org/wiki/Fast_inverse_square_root __m128i a = _mm_castps_si128(bIn); __m128i b = _mm_srli_epi32(a, 23); __m128i c = _mm_sub_epi32(b, _mm_set1_epi32(127)); // exponent (int) __m128 d = _mm_cvtepi32_ps(c); // exponent (float) __m128i e = _mm_or_si128(_mm_andnot_si128(_mm_set1_epi32(0xFF800000), a), _mm_set1_epi32(0x3F800000)); __m128 f = _mm_castsi128_ps(e); // 1+m (float) __m128 g = _mm_add_ps(d, f); // e + 1 + m __m128 h = _mm_add_ps(g, _mm_set1_ps(-0.9569643f)); // e + 1 + m + (sigma-1) *bOut = h; #elif HV_SIMD_NEON int32x4_t a = vreinterpretq_s32_f32(bIn); int32x4_t b = vshrq_n_s32(a, 23); int32x4_t c = vsubq_s32(b, vdupq_n_s32(127)); float32x4_t d = vcvtq_f32_s32(c); int32x4_t e = vorrq_s32(vbicq_s32(a, vdupq_n_s32(0xFF800000)), vdupq_n_s32(0x3F800000)); float32x4_t f = vreinterpretq_f32_s32(e); float32x4_t g = vaddq_f32(d, f); float32x4_t h = vaddq_f32(g, vdupq_n_f32(-0.9569643f)); *bOut = h; #else // HV_SIMD_NONE *bOut = 1.442695040888963f * hv_log_f(bIn); #endif } // NOTE(mhroth): this is a pretty ghetto implementation static inline void __hv_cos_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_set_ps( hv_cos_f(bIn[7]), hv_cos_f(bIn[6]), hv_cos_f(bIn[5]), hv_cos_f(bIn[4]), hv_cos_f(bIn[3]), hv_cos_f(bIn[2]), hv_cos_f(bIn[1]), hv_cos_f(bIn[0])); #elif HV_SIMD_SSE const float *const b = (float *) &bIn; *bOut = _mm_set_ps(hv_cos_f(b[3]), hv_cos_f(b[2]), hv_cos_f(b[1]), hv_cos_f(b[0])); #elif HV_SIMD_NEON *bOut = (float32x4_t) {hv_cos_f(bIn[0]), hv_cos_f(bIn[1]), hv_cos_f(bIn[2]), hv_cos_f(bIn[3])}; #else // HV_SIMD_NONE *bOut = hv_cos_f(bIn); #endif } static inline void __hv_acos_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_acos_f() not implemented #elif HV_SIMD_SSE hv_assert(0); // __hv_acos_f() not implemented #elif HV_SIMD_NEON hv_assert(0); // __hv_acos_f() not implemented #else // HV_SIMD_NONE *bOut = hv_acos_f(bIn); #endif } static inline void __hv_cosh_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_cosh_f() not implemented #elif HV_SIMD_SSE hv_assert(0); // __hv_cosh_f() not implemented #elif HV_SIMD_NEON hv_assert(0); // __hv_cosh_f() not implemented #else // HV_SIMD_NONE *bOut = hv_cosh_f(bIn); #endif } static inline void __hv_acosh_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_acosh_f() not implemented #elif HV_SIMD_SSE hv_assert(0); // __hv_acosh_f() not implemented #elif HV_SIMD_NEON hv_assert(0); // __hv_acosh_f() not implemented #else // HV_SIMD_NONE *bOut = hv_acosh_f(bIn); #endif } static inline void __hv_sin_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_sin_f() not implemented #elif HV_SIMD_SSE hv_assert(0); // __hv_sin_f() not implemented #elif HV_SIMD_NEON hv_assert(0); // __hv_sin_f() not implemented #else // HV_SIMD_NONE *bOut = hv_sin_f(bIn); #endif } static inline void __hv_asin_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_asin_f() not implemented #elif HV_SIMD_SSE hv_assert(0); // __hv_asin_f() not implemented #elif HV_SIMD_NEON hv_assert(0); // __hv_asin_f() not implemented #else // HV_SIMD_NONE *bOut = hv_asin_f(bIn); #endif } static inline void __hv_sinh_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_sinh_f() not implemented #elif HV_SIMD_SSE hv_assert(0); // __hv_sinh_f() not implemented #elif HV_SIMD_NEON hv_assert(0); // __hv_sinh_f() not implemented #else // HV_SIMD_NONE *bOut = hv_sinh_f(bIn); #endif } static inline void __hv_asinh_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_asinh_f() not implemented #elif HV_SIMD_SSE hv_assert(0); // __hv_asinh_f() not implemented #elif HV_SIMD_NEON hv_assert(0); // __hv_asinh_f() not implemented #else // HV_SIMD_NONE *bOut = hv_asinh_f(bIn); #endif } static inline void __hv_tan_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_tan_f() not implemented #elif HV_SIMD_SSE hv_assert(0); // __hv_tan_f() not implemented #elif HV_SIMD_NEON hv_assert(0); // __hv_tan_f() not implemented #else // HV_SIMD_NONE *bOut = hv_tan_f(bIn); #endif } static inline void __hv_atan_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_atan_f() not implemented #elif HV_SIMD_SSE hv_assert(0); // __hv_atan_f() not implemented #elif HV_SIMD_NEON hv_assert(0); // __hv_atan_f() not implemented #else // HV_SIMD_NONE *bOut = hv_atan_f(bIn); #endif } static inline void __hv_atan2_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_atan2_f() not implemented #elif HV_SIMD_SSE hv_assert(0); // __hv_atan2_f() not implemented #elif HV_SIMD_NEON hv_assert(0); // __hv_atan2_f() not implemented #else // HV_SIMD_NONE *bOut = hv_atan2_f(bIn0, bIn1); #endif } static inline void __hv_tanh_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_tanh_f() not implemented #elif HV_SIMD_SSE hv_assert(0); // __hv_tanh_f() not implemented #elif HV_SIMD_NEON hv_assert(0); // __hv_tanh_f() not implemented #else // HV_SIMD_NONE *bOut = hv_tanh_f(bIn); #endif } static inline void __hv_atanh_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_atanh_f() not implemented #elif HV_SIMD_SSE hv_assert(0); // __hv_atanh_f() not implemented #elif HV_SIMD_NEON hv_assert(0); // __hv_atanh_f() not implemented #else // HV_SIMD_NONE *bOut = hv_atanh_f(bIn); #endif } static inline void __hv_sqrt_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_sqrt_ps(bIn); #elif HV_SIMD_SSE *bOut = _mm_sqrt_ps(bIn); #elif HV_SIMD_NEON const float32x4_t y = vrsqrteq_f32(bIn); *bOut = vmulq_f32(bIn, vmulq_f32(vrsqrtsq_f32(vmulq_f32(bIn, y), y), y)); // numerical results may be inexact #else // HV_SIMD_NONE *bOut = hv_sqrt_f(bIn); #endif } static inline void __hv_rsqrt_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_rsqrt_ps(bIn); #elif HV_SIMD_SSE *bOut = _mm_rsqrt_ps(bIn); #elif HV_SIMD_NEON const float32x4_t y = vrsqrteq_f32(bIn); *bOut = vmulq_f32(vrsqrtsq_f32(vmulq_f32(bIn, y), y), y); // numerical results may be inexact #else // HV_SIMD_NONE *bOut = 1.0f/hv_sqrt_f(bIn); #endif } static inline void __hv_abs_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), bIn); #elif HV_SIMD_SSE *bOut = _mm_andnot_ps(_mm_set1_ps(-0.0f), bIn); // == 1 << 31 #elif HV_SIMD_NEON *bOut = vabsq_f32(bIn); #else // HV_SIMD_NONE *bOut = hv_abs_f(bIn); #endif } static inline void __hv_neg_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_xor_ps(bIn, _mm256_set1_ps(-0.0f)); #elif HV_SIMD_SSE *bOut = _mm_xor_ps(bIn, _mm_set1_ps(-0.0f)); #elif HV_SIMD_NEON *bOut = vnegq_f32(bIn); #else // HV_SIMD_NONE *bOut = bIn * -1.0f; #endif } static inline void __hv_exp_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX float *const b = (float *) hv_alloca(HV_N_SIMD*sizeof(float)); _mm256_store_ps(b, bIn); *bOut = _mm256_set_ps( hv_exp_f(b[7]), hv_exp_f(b[6]), hv_exp_f(b[5]), hv_exp_f(b[4]), hv_exp_f(b[3]), hv_exp_f(b[2]), hv_exp_f(b[1]), hv_exp_f(b[0])); #elif HV_SIMD_SSE float *const b = (float *) hv_alloca(HV_N_SIMD*sizeof(float)); _mm_store_ps(b, bIn); *bOut = _mm_set_ps(hv_exp_f(b[3]), hv_exp_f(b[2]), hv_exp_f(b[1]), hv_exp_f(b[0])); #elif HV_SIMD_NEON *bOut = (float32x4_t) { hv_exp_f(bIn[0]), hv_exp_f(bIn[1]), hv_exp_f(bIn[2]), hv_exp_f(bIn[3])}; #else // HV_SIMD_NONE *bOut = hv_exp_f(bIn); #endif } static inline void __hv_ceil_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_ceil_ps(bIn); #elif HV_SIMD_SSE *bOut = _mm_ceil_ps(bIn); #elif HV_SIMD_NEON #if __ARM_ARCH >= 8 *bOut = vrndpq_f32(bIn); #else // A slow NEON implementation of __hv_ceil_f() is being used because // the necessary intrinsic cannot be found. It is only available in ARMv8. *bOut = (float32x4_t) {hv_ceil_f(bIn[0]), hv_ceil_f(bIn[1]), hv_ceil_f(bIn[2]), hv_ceil_f(bIn[3])}; #endif // vrndpq_f32 #else // HV_SIMD_NONE *bOut = hv_ceil_f(bIn); #endif } static inline void __hv_floor_f(hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_floor_ps(bIn); #elif HV_SIMD_SSE *bOut = _mm_floor_ps(bIn); #elif HV_SIMD_NEON #if __ARM_ARCH >= 8 *bOut = vrndmq_f32(bIn); #else // A slow implementation of __hv_floor_f() is being used because // the necessary intrinsic cannot be found. It is only available from ARMv8. *bOut = (float32x4_t) {hv_floor_f(bIn[0]), hv_floor_f(bIn[1]), hv_floor_f(bIn[2]), hv_floor_f(bIn[3])}; #endif // vrndmq_f32 #else // HV_SIMD_NONE *bOut = hv_floor_f(bIn); #endif } // __add~f static inline void __hv_add_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_add_ps(bIn0, bIn1); #elif HV_SIMD_SSE *bOut = _mm_add_ps(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vaddq_f32(bIn0, bIn1); #else // HV_SIMD_NONE *bOut = bIn0 + bIn1; #endif } // __add~i static inline void __hv_add_i(hv_bIni_t bIn0, hv_bIni_t bIn1, hv_bOuti_t bOut) { #if HV_SIMD_AVX __m128i x = _mm_add_epi32(_mm256_castsi256_si128(bIn0), _mm256_castsi256_si128(bIn1)); __m128i y = _mm_add_epi32(_mm256_extractf128_si256(bIn0, 1), _mm256_extractf128_si256(bIn1, 1)); *bOut = _mm256_insertf128_si256(_mm256_castsi128_si256(x), y, 1); #elif HV_SIMD_SSE *bOut = _mm_add_epi32(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vaddq_s32(bIn0, bIn1); #else // HV_SIMD_NONE *bOut = bIn0 + bIn1; #endif } // __sub~f static inline void __hv_sub_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_sub_ps(bIn0, bIn1); #elif HV_SIMD_SSE *bOut = _mm_sub_ps(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vsubq_f32(bIn0, bIn1); #else // HV_SIMD_NONE *bOut = bIn0 - bIn1; #endif } // __mul~f static inline void __hv_mul_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_mul_ps(bIn0, bIn1); #elif HV_SIMD_SSE *bOut = _mm_mul_ps(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vmulq_f32(bIn0, bIn1); #else // HV_SIMD_NONE *bOut = bIn0 * bIn1; #endif } // __*~i static inline void __hv_mul_i(hv_bIni_t bIn0, hv_bIni_t bIn1, hv_bOuti_t bOut) { #if HV_SIMD_AVX __m128i x = _mm_mullo_epi32(_mm256_castsi256_si128(bIn0), _mm256_castsi256_si128(bIn1)); __m128i y = _mm_mullo_epi32(_mm256_extractf128_si256(bIn0, 1), _mm256_extractf128_si256(bIn1, 1)); *bOut = _mm256_insertf128_si256(_mm256_castsi128_si256(x), y, 1); #elif HV_SIMD_SSE *bOut = _mm_mullo_epi32(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vmulq_s32(bIn0, bIn1); #else // HV_SIMD_NONE *bOut = bIn0 * bIn1; #endif } // __cast~if static inline void __hv_cast_if(hv_bIni_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_cvtepi32_ps(bIn); #elif HV_SIMD_SSE *bOut = _mm_cvtepi32_ps(bIn); #elif HV_SIMD_NEON *bOut = vcvtq_f32_s32(bIn); #else // HV_SIMD_NONE *bOut = (float) bIn; #endif } // __cast~fi static inline void __hv_cast_fi(hv_bInf_t bIn, hv_bOuti_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_cvtps_epi32(bIn); #elif HV_SIMD_SSE *bOut = _mm_cvtps_epi32(bIn); #elif HV_SIMD_NEON *bOut = vcvtq_s32_f32(bIn); #else // HV_SIMD_NONE *bOut = (int) bIn; #endif } static inline void __hv_div_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX __m256 a = _mm256_cmp_ps(bIn1, _mm256_setzero_ps(), _CMP_EQ_OQ); __m256 b = _mm256_div_ps(bIn0, bIn1); *bOut = _mm256_andnot_ps(a, b); #elif HV_SIMD_SSE __m128 a = _mm_cmpeq_ps(bIn1, _mm_setzero_ps()); __m128 b = _mm_div_ps(bIn0, bIn1); *bOut = _mm_andnot_ps(a, b); #elif HV_SIMD_NEON uint32x4_t a = vceqq_f32(bIn1, vdupq_n_f32(0.0f)); float32x4_t b = vmulq_f32(bIn0, vrecpeq_f32(bIn1)); // NOTE(mhroth): numerical results may be inexact *bOut = vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(b), a)); #else // HV_SIMD_NONE *bOut = (bIn1 != 0.0f) ? (bIn0 / bIn1) : 0.0f; #endif } static inline void __hv_min_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_min_ps(bIn0, bIn1); #elif HV_SIMD_SSE *bOut = _mm_min_ps(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vminq_f32(bIn0, bIn1); #else // HV_SIMD_NONE *bOut = hv_min_f(bIn0, bIn1); #endif } static inline void __hv_min_i(hv_bIni_t bIn0, hv_bIni_t bIn1, hv_bOuti_t bOut) { #if HV_SIMD_AVX __m128i x = _mm_min_epi32(_mm256_castsi256_si128(bIn0), _mm256_castsi256_si128(bIn1)); __m128i y = _mm_min_epi32(_mm256_extractf128_si256(bIn0, 1), _mm256_extractf128_si256(bIn1, 1)); *bOut = _mm256_insertf128_si256(_mm256_castsi128_si256(x), y, 1); #elif HV_SIMD_SSE *bOut = _mm_min_epi32(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vminq_s32(bIn0, bIn1); #else // HV_SIMD_NONE *bOut = hv_min_i(bIn0, bIn1); #endif } static inline void __hv_max_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_max_ps(bIn0, bIn1); #elif HV_SIMD_SSE *bOut = _mm_max_ps(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vmaxq_f32(bIn0, bIn1); #else // HV_SIMD_NONE *bOut = hv_max_f(bIn0, bIn1); #endif } static inline void __hv_max_i(hv_bIni_t bIn0, hv_bIni_t bIn1, hv_bOuti_t bOut) { #if HV_SIMD_AVX __m128i x = _mm_max_epi32(_mm256_castsi256_si128(bIn0), _mm256_castsi256_si128(bIn1)); __m128i y = _mm_max_epi32(_mm256_extractf128_si256(bIn0, 1), _mm256_extractf128_si256(bIn1, 1)); *bOut = _mm256_insertf128_si256(_mm256_castsi128_si256(x), y, 1); #elif HV_SIMD_SSE *bOut = _mm_max_epi32(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vmaxq_s32(bIn0, bIn1); #else // HV_SIMD_NONE *bOut = hv_max_i(bIn0, bIn1); #endif } static inline void __hv_pow_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX float *b = (float *) hv_alloca(16*sizeof(float)); _mm256_store_ps(b, bIn0); _mm256_store_ps(b+8, bIn1); *bOut = _mm256_set_ps( hv_pow_f(b[7], b[15]), hv_pow_f(b[6], b[14]), hv_pow_f(b[5], b[13]), hv_pow_f(b[4], b[12]), hv_pow_f(b[3], b[11]), hv_pow_f(b[2], b[10]), hv_pow_f(b[1], b[9]), hv_pow_f(b[0], b[8])); #elif HV_SIMD_SSE float *b = (float *) hv_alloca(8*sizeof(float)); _mm_store_ps(b, bIn0); _mm_store_ps(b+4, bIn1); *bOut = _mm_set_ps( hv_pow_f(b[3], b[7]), hv_pow_f(b[2], b[6]), hv_pow_f(b[1], b[5]), hv_pow_f(b[0], b[4])); #elif HV_SIMD_NEON *bOut = (float32x4_t) { hv_pow_f(bIn0[0], bIn1[0]), hv_pow_f(bIn0[1], bIn1[1]), hv_pow_f(bIn0[2], bIn1[2]), hv_pow_f(bIn0[3], bIn1[3])}; #else // HV_SIMD_NONE *bOut = hv_pow_f(bIn0, bIn1); #endif } static inline void __hv_gt_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_GT_OQ); #elif HV_SIMD_SSE *bOut = _mm_cmpgt_ps(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vreinterpretq_f32_u32(vcgtq_f32(bIn0, bIn1)); #else // HV_SIMD_NONE *bOut = (bIn0 > bIn1) ? 1.0f : 0.0f; #endif } static inline void __hv_gte_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_GE_OQ); #elif HV_SIMD_SSE *bOut = _mm_cmpge_ps(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vreinterpretq_f32_u32(vcgeq_f32(bIn0, bIn1)); #else // HV_SIMD_NONE *bOut = (bIn0 >= bIn1) ? 1.0f : 0.0f; #endif } static inline void __hv_lt_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_LT_OQ); #elif HV_SIMD_SSE *bOut = _mm_cmplt_ps(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vreinterpretq_f32_u32(vcltq_f32(bIn0, bIn1)); #else // HV_SIMD_NONE *bOut = (bIn0 < bIn1) ? 1.0f : 0.0f; #endif } static inline void __hv_lte_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_LE_OQ); #elif HV_SIMD_SSE *bOut = _mm_cmple_ps(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vreinterpretq_f32_u32(vcleq_f32(bIn0, bIn1)); #else // HV_SIMD_NONE *bOut = (bIn0 <= bIn1) ? 1.0f : 0.0f; #endif } static inline void __hv_eq_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_EQ_OQ); #elif HV_SIMD_SSE *bOut = _mm_cmpeq_ps(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vreinterpretq_f32_u32(vceqq_f32(bIn0, bIn1)); #else // HV_SIMD_NONE *bOut = (bIn0 == bIn1) ? 1.0f : 0.0f; #endif } static inline void __hv_neq_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_NEQ_OQ); #elif HV_SIMD_SSE *bOut = _mm_cmpneq_ps(bIn0, bIn1); #elif HV_SIMD_NEON *bOut = vreinterpretq_f32_u32(vmvnq_u32(vceqq_f32(bIn0, bIn1))); #else // HV_SIMD_NONE *bOut = (bIn0 != bIn1) ? 1.0f : 0.0f; #endif } static inline void __hv_or_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_or_ps(bIn1, bIn0); #elif HV_SIMD_SSE *bOut = _mm_or_ps(bIn1, bIn0); #elif HV_SIMD_NEON *bOut = vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(bIn1), vreinterpretq_u32_f32(bIn0))); #else // HV_SIMD_NONE if (bIn0 == 0.0f && bIn1 == 0.0f) *bOut = 0.0f; else if (bIn0 == 0.0f) *bOut = bIn1; else if (bIn1 == 0.0f) *bOut = bIn0; else hv_assert(0); #endif } static inline void __hv_and_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_and_ps(bIn1, bIn0); #elif HV_SIMD_SSE *bOut = _mm_and_ps(bIn1, bIn0); #elif HV_SIMD_NEON *bOut = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(bIn1), vreinterpretq_u32_f32(bIn0))); #else // HV_SIMD_NONE if (bIn0 == 0.0f || bIn1 == 0.0f) *bOut = 0.0f; else if (bIn0 == 1.0f) *bOut = bIn1; else if (bIn1 == 1.0f) *bOut = bIn0; else hv_assert(0); #endif } static inline void __hv_andnot_f(hv_bInf_t bIn0_mask, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_andnot_ps(bIn0_mask, bIn1); #elif HV_SIMD_SSE *bOut = _mm_andnot_ps(bIn0_mask, bIn1); #elif HV_SIMD_NEON *bOut = vreinterpretq_f32_s32(vbicq_s32(vreinterpretq_s32_f32(bIn1), vreinterpretq_s32_f32(bIn0_mask))); #else // HV_SIMD_NONE *bOut = (bIn0_mask == 0.0f) ? bIn1 : 0.0f; #endif } // bOut = (bIn0 * bIn1) + bIn2 static inline void __hv_fma_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bInf_t bIn2, hv_bOutf_t bOut) { #if HV_SIMD_AVX #if HV_SIMD_FMA *bOut = _mm256_fmadd_ps(bIn0, bIn1, bIn2); #else *bOut = _mm256_add_ps(_mm256_mul_ps(bIn0, bIn1), bIn2); #endif // HV_SIMD_FMA #elif HV_SIMD_SSE #if HV_SIMD_FMA *bOut = _mm_fmadd_ps(bIn0, bIn1, bIn2); #else *bOut = _mm_add_ps(_mm_mul_ps(bIn0, bIn1), bIn2); #endif // HV_SIMD_FMA #elif HV_SIMD_NEON #if __ARM_ARCH >= 8 *bOut = vfmaq_f32(bIn2, bIn0, bIn1); #else // NOTE(mhroth): it turns out, fma SUUUUCKS on lesser ARM architectures *bOut = vaddq_f32(vmulq_f32(bIn0, bIn1), bIn2); #endif #else // HV_SIMD_NONE *bOut = hv_fma_f(bIn0, bIn1, bIn2); #endif } // bOut = (bIn0 * bIn1) - bIn2 static inline void __hv_fms_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bInf_t bIn2, hv_bOutf_t bOut) { #if HV_SIMD_AVX #if HV_SIMD_FMA *bOut = _mm256_fmsub_ps(bIn0, bIn1, bIn2); #else *bOut = _mm256_sub_ps(_mm256_mul_ps(bIn0, bIn1), bIn2); #endif // HV_SIMD_FMA #elif HV_SIMD_SSE #if HV_SIMD_FMA *bOut = _mm_fmsub_ps(bIn0, bIn1, bIn2); #else *bOut = _mm_sub_ps(_mm_mul_ps(bIn0, bIn1), bIn2); #endif // HV_SIMD_FMA #elif HV_SIMD_NEON #if __ARM_ARCH >= 8 *bOut = vfmsq_f32(bIn2, bIn0, bIn1); #else // NOTE(mhroth): it turns out, fma SUUUUCKS on lesser ARM architectures *bOut = vsubq_f32(vmulq_f32(bIn0, bIn1), bIn2); #endif #else // HV_SIMD_NONE *bOut = (bIn0 * bIn1) - bIn2; #endif } #endif // _HEAVY_MATH_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvMessage.c0000644000000000000000000001622514435670357016743 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvMessage.h" HvMessage *msg_init(HvMessage *m, hv_size_t numElements, hv_uint32_t timestamp) { m->timestamp = timestamp; m->numElements = (hv_uint16_t) numElements; m->numBytes = (hv_uint16_t) msg_getCoreSize(numElements); return m; } HvMessage *msg_initWithFloat(HvMessage *m, hv_uint32_t timestamp, float f) { m->timestamp = timestamp; m->numElements = 1; m->numBytes = sizeof(HvMessage); msg_setFloat(m, 0, f); return m; } HvMessage *msg_initWithBang(HvMessage *m, hv_uint32_t timestamp) { m->timestamp = timestamp; m->numElements = 1; m->numBytes = sizeof(HvMessage); msg_setBang(m, 0); return m; } HvMessage *msg_initWithSymbol(HvMessage *m, hv_uint32_t timestamp, const char *s) { m->timestamp = timestamp; m->numElements = 1; m->numBytes = sizeof(HvMessage) + (hv_uint16_t) hv_strlen(s); msg_setSymbol(m, 0, s); return m; } HvMessage *msg_initWithHash(HvMessage *m, hv_uint32_t timestamp, hv_uint32_t h) { m->timestamp = timestamp; m->numElements = 1; m->numBytes = sizeof(HvMessage); msg_setHash(m, 0, h); return m; } void msg_copyToBuffer(const HvMessage *m, char *buffer, hv_size_t len) { HvMessage *r = (HvMessage *) buffer; hv_size_t len_r = msg_getCoreSize(msg_getNumElements(m)); // assert that the message is not already larger than the length of the buffer hv_assert(len_r <= len); // copy the basic message to the buffer hv_memcpy(r, m, len_r); char *p = buffer + len_r; // points to the end of the base message for (int i = 0; i < msg_getNumElements(m); ++i) { if (msg_isSymbol(m,i)) { const hv_size_t symLen = (hv_size_t) hv_strlen(msg_getSymbol(m,i)) + 1; // include the trailing null char hv_assert(len_r + symLen <= len); // stay safe! hv_strncpy(p, msg_getSymbol(m,i), symLen); msg_setSymbol(r, i, p); p += symLen; len_r += symLen; } } r->numBytes = (hv_uint16_t) len_r; // update the message size in memory } // the message is serialised such that all symbol elements are placed in order at the end of the buffer HvMessage *msg_copy(const HvMessage *m) { const hv_uint32_t heapSize = msg_getSize(m); char *r = (char *) hv_malloc(heapSize); hv_assert(r != NULL); msg_copyToBuffer(m, r, heapSize); return (HvMessage *) r; } void msg_free(HvMessage *m) { hv_free(m); // because heap messages are serialised in memory, a simple call to free releases the message } bool msg_hasFormat(const HvMessage *m, const char *fmt) { hv_assert(fmt != NULL); const int n = msg_getNumElements(m); for (int i = 0; i < n; ++i) { switch (fmt[i]) { case 'b': if (!msg_isBang(m, i)) return false; break; case 'f': if (!msg_isFloat(m, i)) return false; break; case 'h': if (!msg_isHash(m, i)) return false; break; case 's': if (!msg_isSymbol(m, i)) return false; break; default: return false; } } return (fmt[n] == '\0'); } bool msg_compareSymbol(const HvMessage *m, int i, const char *s) { switch (msg_getType(m,i)) { case HV_MSG_SYMBOL: return !hv_strcmp(msg_getSymbol(m, i), s); case HV_MSG_HASH: return (msg_getHash(m,i) == hv_string_to_hash(s)); default: return false; } } bool msg_equalsElement(const HvMessage *m, int i_m, const HvMessage *n, int i_n) { if (i_m < msg_getNumElements(m) && i_n < msg_getNumElements(n)) { if (msg_getType(m, i_m) == msg_getType(n, i_n)) { switch (msg_getType(m, i_m)) { case HV_MSG_BANG: return true; case HV_MSG_FLOAT: return (msg_getFloat(m, i_m) == msg_getFloat(n, i_n)); case HV_MSG_SYMBOL: return msg_compareSymbol(m, i_m, msg_getSymbol(n, i_n)); case HV_MSG_HASH: return msg_getHash(m,i_m) == msg_getHash(n,i_n); default: break; } } } return false; } void msg_setElementToFrom(HvMessage *n, int i_n, const HvMessage *const m, int i_m) { switch (msg_getType(m, i_m)) { case HV_MSG_BANG: msg_setBang(n, i_n); break; case HV_MSG_FLOAT: msg_setFloat(n, i_n, msg_getFloat(m, i_m)); break; case HV_MSG_SYMBOL: msg_setSymbol(n, i_n, msg_getSymbol(m, i_m)); break; case HV_MSG_HASH: msg_setHash(n, i_n, msg_getHash(m, i_m)); default: break; } } hv_uint32_t msg_getHash(const HvMessage *const m, int i) { hv_assert(i < msg_getNumElements(m)); // invalid index switch (msg_getType(m,i)) { case HV_MSG_BANG: return 0xFFFFFFFF; case HV_MSG_FLOAT: { float f = msg_getFloat(m,i); return *((hv_uint32_t *) &f); } case HV_MSG_SYMBOL: return hv_string_to_hash(msg_getSymbol(m,i)); case HV_MSG_HASH: return (&(m->elem)+i)->data.h; default: return 0; } } char *msg_toString(const HvMessage *m) { hv_assert(msg_getNumElements(m) > 0); int *len = (int *) hv_alloca(msg_getNumElements(m)*sizeof(int)); int size = 0; // the total length of our final buffer // loop through every element in our list of atoms // first loop figures out how long our buffer should be for (int i = 0; i < msg_getNumElements(m); i++) { // length of our string is each atom plus a space, or \0 on the end switch (msg_getType(m, i)) { case HV_MSG_BANG: len[i] = hv_snprintf(NULL, 0, "%s", "bang") + 1; break; case HV_MSG_FLOAT: len[i] = hv_snprintf(NULL, 0, "%g", msg_getFloat(m, i)) + 1; break; case HV_MSG_SYMBOL: len[i] = hv_snprintf(NULL, 0, "%s", msg_getSymbol(m, i)) + 1; break; case HV_MSG_HASH: len[i] = hv_snprintf(NULL, 0, "0x%X", msg_getHash(m, i)) + 1; break; default: break; } size += len[i]; } hv_assert(size > 0); // now we do the piecewise concatenation into our final string // the final buffer we will pass back after concatenating all strings - user should free it char *finalString = (char *) hv_malloc(size*sizeof(char)); hv_assert(finalString != NULL); int pos = 0; for (int i = 0; i < msg_getNumElements(m); i++) { // put a string representation of each atom into the final string switch (msg_getType(m, i)) { case HV_MSG_BANG: hv_snprintf(finalString+pos, len[i], "%s", "bang"); break; case HV_MSG_FLOAT: hv_snprintf(finalString+pos, len[i], "%g", msg_getFloat(m, i)); break; case HV_MSG_SYMBOL: hv_snprintf(finalString+pos, len[i], "%s", msg_getSymbol(m, i)); break; case HV_MSG_HASH: hv_snprintf(finalString+pos, len[i], "0x%X", msg_getHash(m, i)); break; default: break; } pos += len[i]; finalString[pos-1] = 32; // ASCII space } finalString[size-1] = '\0'; // ensure that the string is null terminated return finalString; } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvMessage.h0000644000000000000000000001423614435670357016750 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_MESSAGE_H_ #define _HEAVY_MESSAGE_H_ #include "HvUtils.h" #ifdef __cplusplus extern "C" { #endif typedef enum ElementType { HV_MSG_BANG = 0, HV_MSG_FLOAT = 1, HV_MSG_SYMBOL = 2, HV_MSG_HASH = 3 } ElementType; typedef struct Element { ElementType type; union { float f; // float const char *s; // symbol hv_uint32_t h; // hash } data; } Element; typedef struct HvMessage { hv_uint32_t timestamp; // the sample at which this message should be processed hv_uint16_t numElements; hv_uint16_t numBytes; // the total number of bytes that this message occupies in memory, including strings Element elem; } HvMessage; typedef struct ReceiverMessagePair { hv_uint32_t receiverHash; HvMessage msg; } ReceiverMessagePair; #define HV_MESSAGE_ON_STACK(_x) (HvMessage *) hv_alloca(msg_getCoreSize(_x)) /** Returns the number of bytes that this message consumes in memory, not including strings. */ static inline hv_size_t msg_getCoreSize(hv_size_t numElements) { hv_assert(numElements > 0); return sizeof(HvMessage) + ((numElements-1) * sizeof(Element)); } HvMessage *msg_copy(const HvMessage *m); /** Copies the message into the given buffer. The buffer must be at least as large as msg_getNumHeapBytes(). */ void msg_copyToBuffer(const HvMessage *m, char *buffer, hv_size_t len); void msg_setElementToFrom(HvMessage *n, int indexN, const HvMessage *const m, int indexM); /** Frees a message on the heap. Does nothing if argument is NULL. */ void msg_free(HvMessage *m); HvMessage *msg_init(HvMessage *m, hv_size_t numElements, hv_uint32_t timestamp); HvMessage *msg_initWithFloat(HvMessage *m, hv_uint32_t timestamp, float f); HvMessage *msg_initWithBang(HvMessage *m, hv_uint32_t timestamp); HvMessage *msg_initWithSymbol(HvMessage *m, hv_uint32_t timestamp, const char *s); HvMessage *msg_initWithHash(HvMessage *m, hv_uint32_t timestamp, hv_uint32_t h); static inline hv_uint32_t msg_getTimestamp(const HvMessage *m) { return m->timestamp; } static inline void msg_setTimestamp(HvMessage *m, hv_uint32_t timestamp) { m->timestamp = timestamp; } static inline int msg_getNumElements(const HvMessage *m) { return (int) m->numElements; } /** Returns the total number of bytes this message consumes in memory. */ static inline hv_uint32_t msg_getSize(const HvMessage *m) { return m->numBytes; } static inline ElementType msg_getType(const HvMessage *m, int index) { hv_assert(index < msg_getNumElements(m)); // invalid index return (&(m->elem)+index)->type; } static inline void msg_setBang(HvMessage *m, int index) { hv_assert(index < msg_getNumElements(m)); // invalid index (&(m->elem)+index)->type = HV_MSG_BANG; (&(m->elem)+index)->data.s = NULL; } static inline bool msg_isBang(const HvMessage *m, int index) { return (index < msg_getNumElements(m)) ? (msg_getType(m,index) == HV_MSG_BANG) : false; } static inline void msg_setFloat(HvMessage *m, int index, float f) { hv_assert(index < msg_getNumElements(m)); // invalid index (&(m->elem)+index)->type = HV_MSG_FLOAT; (&(m->elem)+index)->data.f = f; } static inline float msg_getFloat(const HvMessage *const m, int index) { hv_assert(index < msg_getNumElements(m)); // invalid index return (&(m->elem)+index)->data.f; } static inline bool msg_isFloat(const HvMessage *const m, int index) { return (index < msg_getNumElements(m)) ? (msg_getType(m,index) == HV_MSG_FLOAT) : false; } static inline void msg_setHash(HvMessage *m, int index, hv_uint32_t h) { hv_assert(index < msg_getNumElements(m)); // invalid index (&(m->elem)+index)->type = HV_MSG_HASH; (&(m->elem)+index)->data.h = h; } static inline bool msg_isHash(const HvMessage *m, int index) { return (index < msg_getNumElements(m)) ? (msg_getType(m, index) == HV_MSG_HASH) : false; } /** Returns true if the element is a hash or symbol. False otherwise. */ static inline bool msg_isHashLike(const HvMessage *m, int index) { return (index < msg_getNumElements(m)) ? ((msg_getType(m, index) == HV_MSG_HASH) || (msg_getType(m, index) == HV_MSG_SYMBOL)) : false; } /** Returns a 32-bit hash of the given element. */ hv_uint32_t msg_getHash(const HvMessage *const m, int i); static inline void msg_setSymbol(HvMessage *m, int index, const char *s) { hv_assert(index < msg_getNumElements(m)); // invalid index hv_assert(s != NULL); (&(m->elem)+index)->type = HV_MSG_SYMBOL; (&(m->elem)+index)->data.s = s; // NOTE(mhroth): if the same message container is reused and string reset, // then the message size will be overcounted m->numBytes += (hv_uint16_t) (hv_strlen(s) + 1); // also count '\0' } static inline const char *msg_getSymbol(const HvMessage *m, int index) { hv_assert(index < msg_getNumElements(m)); // invalid index return (&(m->elem)+index)->data.s; } static inline bool msg_isSymbol(const HvMessage *m, int index) { return (index < msg_getNumElements(m)) ? (msg_getType(m, index) == HV_MSG_SYMBOL) : false; } bool msg_compareSymbol(const HvMessage *m, int i, const char *s); /** Returns 1 if the element i_m of message m is equal to element i_n of message n. */ bool msg_equalsElement(const HvMessage *m, int i_m, const HvMessage *n, int i_n); bool msg_hasFormat(const HvMessage *m, const char *fmt); /** * Create a string representation of the message. Suitable for use by the print object. * The resulting string must be freed by the caller. */ char *msg_toString(const HvMessage *msg); #ifdef __cplusplus } #endif #endif // _HEAVY_MESSAGE_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.763207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvMessagePool.c0000644000000000000000000001111014435670357017561 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvMessagePool.h" #include "HvMessage.h" // the number of bytes reserved at a time from the pool #define MP_BLOCK_SIZE_BYTES 512 #if HV_APPLE #pragma mark - MessageList #endif typedef struct MessageListNode { char *p; struct MessageListNode *next; } MessageListNode; static inline bool ml_hasAvailable(HvMessagePoolList *ml) { return (ml->head != NULL); } static char *ml_pop(HvMessagePoolList *ml) { MessageListNode *n = ml->head; ml->head = n->next; n->next = ml->pool; ml->pool = n; char *const p = n->p; n->p = NULL; // set to NULL to make it clear that this node does not have a valid buffer return p; } /** Push a MessageListNode with the given pointer onto the head of the queue. */ static void ml_push(HvMessagePoolList *ml, void *p) { MessageListNode *n = NULL; if (ml->pool != NULL) { // take an empty MessageListNode from the pool n = ml->pool; ml->pool = n->next; } else { // a MessageListNode is not available, allocate one n = (MessageListNode *) hv_malloc(sizeof(MessageListNode)); hv_assert(n != NULL); } n->p = (char *) p; n->next = ml->head; ml->head = n; // push to the front of the queue } static void ml_free(HvMessagePoolList *ml) { if (ml != NULL) { while (ml_hasAvailable(ml)) { ml_pop(ml); } while (ml->pool != NULL) { MessageListNode *n = ml->pool; ml->pool = n->next; hv_free(n); } } } #if HV_APPLE #pragma mark - HvMessagePool #endif static hv_size_t mp_messagelistIndexForSize(hv_size_t byteSize) { return (hv_size_t) hv_max_i((hv_min_max_log2((hv_uint32_t) byteSize) - 5), 0); } hv_size_t mp_init(HvMessagePool *mp, hv_size_t numKB) { mp->bufferSize = numKB * 1024; mp->buffer = (char *) hv_malloc(mp->bufferSize); hv_assert(mp->buffer != NULL); mp->bufferIndex = 0; // initialise all message lists for (int i = 0; i < MP_NUM_MESSAGE_LISTS; i++) { mp->lists[i].head = NULL; mp->lists[i].pool = NULL; } return mp->bufferSize; } void mp_free(HvMessagePool *mp) { hv_free(mp->buffer); for (int i = 0; i < MP_NUM_MESSAGE_LISTS; i++) { ml_free(&mp->lists[i]); } } void mp_freeMessage(HvMessagePool *mp, HvMessage *m) { const hv_size_t b = msg_getSize(m); // the number of bytes that a message occupies in memory const hv_size_t i = mp_messagelistIndexForSize(b); // the HvMessagePoolList index in the pool HvMessagePoolList *ml = &mp->lists[i]; const hv_size_t chunkSize = 32 << i; hv_memclear(m, chunkSize); // clear the chunk, just in case ml_push(ml, m); } HvMessage *mp_addMessage(HvMessagePool *mp, const HvMessage *m) { const hv_size_t b = msg_getSize(m); // determine the message list index to allocate data from based on the msg size // smallest chunk size is 32 bytes const hv_size_t i = mp_messagelistIndexForSize(b); hv_assert(i < MP_NUM_MESSAGE_LISTS); // how many chunk sizes do we want to support? 32, 64, 128, 256 at the moment HvMessagePoolList *ml = &mp->lists[i]; const hv_size_t chunkSize = 32 << i; if (ml_hasAvailable(ml)) { char *buf = ml_pop(ml); msg_copyToBuffer(m, buf, chunkSize); return (HvMessage *) buf; } else { // if no appropriately sized buffer is immediately available, increase the size of the used buffer const hv_size_t newIndex = mp->bufferIndex + MP_BLOCK_SIZE_BYTES; hv_assert((newIndex <= mp->bufferSize) && "The message pool buffer size has been exceeded. The context cannot store more messages. " "Try using the new_with_options() initialiser with a larger pool size (default is 10KB)."); for (hv_size_t j = mp->bufferIndex; j < newIndex; j += chunkSize) { ml_push(ml, mp->buffer + j); // push new nodes onto the list with chunk pointers } mp->bufferIndex = newIndex; char *buf = ml_pop(ml); msg_copyToBuffer(m, buf, chunkSize); return (HvMessage *) buf; } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2755518 hvcc-0.13.3/hvcc/generators/ir2c/static/HvMessagePool.h0000644000000000000000000000507714677551203017601 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _MESSAGE_POOL_H_ #define _MESSAGE_POOL_H_ #include "HvUtils.h" #ifdef HV_MP_NUM_MESSAGE_LISTS #define MP_NUM_MESSAGE_LISTS HV_MP_NUM_MESSAGE_LISTS #else // HV_MP_NUM_MESSAGE_LISTS #define MP_NUM_MESSAGE_LISTS 4 #endif // HV_MP_NUM_MESSAGE_LISTS #ifdef __cplusplus extern "C" { #endif typedef struct HvMessagePoolList { struct MessageListNode *head; // list of currently available blocks struct MessageListNode *pool; // list of currently used blocks } HvMessagePoolList; typedef struct HvMessagePool { char *buffer; // the buffer of all messages hv_size_t bufferSize; // in bytes hv_size_t bufferIndex; // the number of total reserved bytes HvMessagePoolList lists[MP_NUM_MESSAGE_LISTS]; } HvMessagePool; /** * The HvMessagePool is a basic memory management system. It reserves a large block of memory at initialisation * and proceeds to divide this block into smaller chunks (usually 512 bytes) as they are needed. These chunks are * further divided into 32, 64, 128, or 256 sections. Each of these sections is managed by a HvMessagePoolList (MPL). * An MPL is a linked-list data structure which is initialised such that its own pool of listnodes is filled with nodes * that point at each subblock (e.g. each 32-byte block of a 512-block chunk). * * HvMessagePool is loosely inspired by TCMalloc. http://goog-perftools.sourceforge.net/doc/tcmalloc.html */ hv_size_t mp_init(struct HvMessagePool *mp, hv_size_t numKB); void mp_free(struct HvMessagePool *mp); /** * Adds a message to the pool and returns a pointer to the copy. Returns NULL * if no space was available in the pool. */ struct HvMessage *mp_addMessage(struct HvMessagePool *mp, const struct HvMessage *m); void mp_freeMessage(struct HvMessagePool *mp, struct HvMessage *m); #ifdef __cplusplus } #endif #endif // _MESSAGE_POOL_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvMessageQueue.c0000644000000000000000000001366714435670357017757 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvMessageQueue.h" hv_size_t mq_initWithPoolSize(HvMessageQueue *q, hv_size_t poolSizeKB) { hv_assert(poolSizeKB > 0); q->head = NULL; q->tail = NULL; q->pool = NULL; return mp_init(&q->mp, poolSizeKB); } void mq_free(HvMessageQueue *q) { mq_clear(q); while (q->pool != NULL) { MessageNode *n = q->pool; q->pool = q->pool->next; hv_free(n); } mp_free(&q->mp); } static MessageNode *mq_getOrCreateNodeFromPool(HvMessageQueue *q) { if (q->pool == NULL) { // if necessary, create a new empty node q->pool = (MessageNode *) hv_malloc(sizeof(MessageNode)); hv_assert(q->pool != NULL); q->pool->next = NULL; } MessageNode *node = q->pool; q->pool = q->pool->next; return node; } int mq_size(HvMessageQueue *q) { int size = 0; MessageNode *n = q->head; while (n != NULL) { ++size; n = n->next; } return size; } HvMessage *mq_addMessage(HvMessageQueue *q, const HvMessage *m, int let, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { MessageNode *node = mq_getOrCreateNodeFromPool(q); node->m = mp_addMessage(&q->mp, m); node->let = let; node->sendMessage = sendMessage; node->prev = NULL; node->next = NULL; if (q->tail != NULL) { // the list already contains elements q->tail->next = node; node->prev = q->tail; q->tail = node; } else { // the list is empty node->prev = NULL; q->head = node; q->tail = node; } return mq_node_getMessage(node); } HvMessage *mq_addMessageByTimestamp(HvMessageQueue *q, const HvMessage *m, int let, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { if (mq_hasMessage(q)) { MessageNode *n = mq_getOrCreateNodeFromPool(q); n->m = mp_addMessage(&q->mp, m); n->let = let; n->sendMessage = sendMessage; if (msg_getTimestamp(m) < msg_getTimestamp(q->head->m)) { // the message occurs before the current head n->next = q->head; q->head->prev = n; n->prev = NULL; q->head = n; } else if (msg_getTimestamp(m) >= msg_getTimestamp(q->tail->m)) { // the message occurs after the current tail n->next = NULL; n->prev = q->tail; q->tail->next = n; q->tail = n; } else { // the message occurs somewhere between the head and tail MessageNode *node = q->head; while (node != NULL) { if (msg_getTimestamp(m) < msg_getTimestamp(node->next->m)) { MessageNode *r = node->next; node->next = n; n->next = r; n->prev = node; r->prev = n; break; } node = node->next; } } return n->m; } else { // add a message to the head return mq_addMessage(q, m, let, sendMessage); } } void mq_pop(HvMessageQueue *q) { if (mq_hasMessage(q)) { MessageNode *n = q->head; mp_freeMessage(&q->mp, n->m); n->m = NULL; n->let = 0; n->sendMessage = NULL; q->head = n->next; if (q->head == NULL) { q->tail = NULL; } else { q->head->prev = NULL; } n->next = q->pool; n->prev = NULL; q->pool = n; } } bool mq_removeMessage(HvMessageQueue *q, HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { if (mq_hasMessage(q)) { if (mq_node_getMessage(q->head) == m) { // msg in head node // only remove the message if sendMessage is the same as the stored one, // if the sendMessage argument is NULL, it is not checked and will remove any matching message pointer if (sendMessage == NULL || q->head->sendMessage == sendMessage) { mq_pop(q); return true; } } else { MessageNode *prevNode = q->head; MessageNode *currNode = q->head->next; while ((currNode != NULL) && (currNode->m != m)) { prevNode = currNode; currNode = currNode->next; } if (currNode != NULL) { if (sendMessage == NULL || currNode->sendMessage == sendMessage) { mp_freeMessage(&q->mp, m); currNode->m = NULL; currNode->let = 0; currNode->sendMessage = NULL; if (currNode == q->tail) { // msg in tail node prevNode->next = NULL; q->tail = prevNode; } else { // msg in middle node prevNode->next = currNode->next; currNode->next->prev = prevNode; } currNode->next = (q->pool == NULL) ? NULL : q->pool; currNode->prev = NULL; q->pool = currNode; return true; } } } } return false; } void mq_clear(HvMessageQueue *q) { while (mq_hasMessage(q)) { mq_pop(q); } } void mq_clearAfter(HvMessageQueue *q, const hv_uint32_t timestamp) { MessageNode *n = q->tail; while (n != NULL && timestamp <= msg_getTimestamp(n->m)) { // free the node's message mp_freeMessage(&q->mp, n->m); n->m = NULL; n->let = 0; n->sendMessage = NULL; // the tail points at the previous node q->tail = n->prev; // put the node back in the pool n->next = q->pool; n->prev = NULL; if (q->pool != NULL) q->pool->prev = n; q->pool = n; // update the tail node n = q->tail; } if (q->tail == NULL) q->head = NULL; } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvMessageQueue.h0000644000000000000000000000630614435670357017754 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _MESSAGE_QUEUE_H_ #define _MESSAGE_QUEUE_H_ #include "HvMessage.h" #include "HvMessagePool.h" #ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus class HeavyContextInterface; #else typedef struct HeavyContextInterface HeavyContextInterface; #endif typedef struct MessageNode { struct MessageNode *prev; // doubly linked list struct MessageNode *next; HvMessage *m; void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *); int let; } MessageNode; /** A doubly linked list containing scheduled messages. */ typedef struct HvMessageQueue { MessageNode *head; // the head of the queue MessageNode *tail; // the tail of the queue MessageNode *pool; // the head of the reserve pool HvMessagePool mp; } HvMessageQueue; hv_size_t mq_initWithPoolSize(HvMessageQueue *q, hv_size_t poolSizeKB); void mq_free(HvMessageQueue *q); int mq_size(HvMessageQueue *q); static inline HvMessage *mq_node_getMessage(MessageNode *n) { return n->m; } static inline int mq_node_getLet(MessageNode *n) { return n->let; } static inline bool mq_hasMessage(HvMessageQueue *q) { return (q->head != NULL); } // true if there is a message and it occurs before (<) timestamp static inline bool mq_hasMessageBefore(HvMessageQueue *const q, const hv_uint32_t timestamp) { return mq_hasMessage(q) && (msg_getTimestamp(mq_node_getMessage(q->head)) < timestamp); } static inline MessageNode *mq_peek(HvMessageQueue *q) { return q->head; } /** Appends the message to the end of the queue. */ HvMessage *mq_addMessage(HvMessageQueue *q, const HvMessage *m, int let, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); /** Insert in ascending order the message acccording to its timestamp. */ HvMessage *mq_addMessageByTimestamp(HvMessageQueue *q, const HvMessage *m, int let, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); /** Pop the message at the head of the queue (and free its memory). */ void mq_pop(HvMessageQueue *q); /** Remove a message from the queue (and free its memory) */ bool mq_removeMessage(HvMessageQueue *q, HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); /** Clears (and frees) all messages in the queue. */ void mq_clear(HvMessageQueue *q); /** Removes all messages occuring at or after the given timestamp. */ void mq_clearAfter(HvMessageQueue *q, const hv_uint32_t timestamp); #ifdef __cplusplus } #endif #endif // _MESSAGE_QUEUE_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753709.3467236 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalBiquad.c0000644000000000000000000002212714735277755017730 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalBiquad.h" // http://reanimator-web.appspot.com/articles/simdiir // https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html hv_size_t sBiquad_init(SignalBiquad *o) { #if HV_SIMD_AVX o->x = _mm256_setzero_ps(); #elif HV_SIMD_SSE o->x = _mm_setzero_ps(); #elif HV_SIMD_NEON o->x = vdupq_n_f32(0.0f); #else // HV_SIMD_NONE o->xm1 = 0.0f; o->xm2 = 0.0f; #endif o->ym1 = 0.0f; o->ym2 = 0.0f; return 0; } #if _WIN32 && !_WIN64 void __hv_biquad_f_win32(SignalBiquad *o, hv_bInf_t *_bIn, hv_bInf_t *_bX0, hv_bInf_t *_bX1, hv_bInf_t *_bX2, hv_bInf_t *_bY1, hv_bInf_t *_bY2, hv_bOutf_t bOut) { hv_bInf_t bIn = *_bIn; hv_bInf_t bX0 = *_bX0; hv_bInf_t bX1 = *_bX1; hv_bInf_t bX2 = *_bX2; hv_bInf_t bY1 = *_bY1; hv_bInf_t bY2 = *_bY2; #else void __hv_biquad_f(SignalBiquad *o, hv_bInf_t bIn, hv_bInf_t bX0, hv_bInf_t bX1, hv_bInf_t bX2, hv_bInf_t bY1, hv_bInf_t bY2, hv_bOutf_t bOut) { #endif #if HV_SIMD_AVX __m256 x = _mm256_permute_ps(bIn, _MM_SHUFFLE(2,1,0,3)); // [3 0 1 2 7 4 5 6] __m256 y = _mm256_permute_ps(o->x, _MM_SHUFFLE(2,1,0,3)); // [d a b c h e f g] __m256 n = _mm256_permute2f128_ps(y,x,0x21); // [h e f g 3 0 1 2] __m256 xm1 = _mm256_blend_ps(x, n, 0x11); // [h 0 1 2 3 4 5 6] x = _mm256_permute_ps(bIn, _MM_SHUFFLE(1,0,3,2)); // [2 3 0 1 6 7 4 5] y = _mm256_permute_ps(o->x, _MM_SHUFFLE(1,0,3,2)); // [c d a b g h e f] n = _mm256_permute2f128_ps(y,x,0x21); // [g h e f 2 3 0 1] __m256 xm2 = _mm256_blend_ps(x, n, 0x33); // [g h 0 1 2 3 4 5] __m256 a = _mm256_mul_ps(bIn, bX0); __m256 b = _mm256_mul_ps(xm1, bX1); __m256 c = _mm256_mul_ps(xm2, bX2); __m256 d = _mm256_add_ps(a, b); __m256 e = _mm256_add_ps(c, d); // bIn*bX0 + o->x1*bX1 + o->x2*bX2 float y0 = e[0] - o->ym1*bY1[0] - o->ym2*bY2[0]; float y1 = e[1] - y0*bY1[1] - o->ym1*bY2[1]; float y2 = e[2] - y1*bY1[2] - y0*bY2[2]; float y3 = e[3] - y2*bY1[3] - y1*bY2[3]; float y4 = e[4] - y3*bY1[4] - y2*bY2[4]; float y5 = e[5] - y4*bY1[5] - y3*bY2[5]; float y6 = e[6] - y5*bY1[6] - y4*bY2[6]; float y7 = e[7] - y6*bY1[7] - y5*bY2[7]; o->x = bIn; o->ym1 = y7; o->ym2 = y6; *bOut = _mm256_set_ps(y7, y6, y5, y4, y3, y2, y1, y0); #elif HV_SIMD_SSE __m128 n = _mm_blend_ps(o->x, bIn, 0x7); // [a b c d] [e f g h] = [e f g d] __m128 xm1 = _mm_shuffle_ps(n, n, _MM_SHUFFLE(2,1,0,3)); // [d e f g] __m128 xm2 = _mm_shuffle_ps(o->x, bIn, _MM_SHUFFLE(1,0,3,2)); // [c d e f] __m128 a = _mm_mul_ps(bIn, bX0); __m128 b = _mm_mul_ps(xm1, bX1); __m128 c = _mm_mul_ps(xm2, bX2); __m128 d = _mm_add_ps(a, b); __m128 e = _mm_add_ps(c, d); const float *const bbe = (float *) &e; const float *const bbY1 = (float *) &bY1; const float *const bbY2 = (float *) &bY2; float y0 = bbe[0] - o->ym1*bbY1[0] - o->ym2*bbY2[0]; float y1 = bbe[1] - y0*bbY1[1] - o->ym1*bbY2[1]; float y2 = bbe[2] - y1*bbY1[2] - y0*bbY2[2]; float y3 = bbe[3] - y2*bbY1[3] - y1*bbY2[3]; o->x = bIn; o->ym1 = y3; o->ym2 = y2; *bOut = _mm_set_ps(y3, y2, y1, y0); #elif HV_SIMD_NEON float32x4_t xm1 = vextq_f32(o->x, bIn, 3); float32x4_t xm2 = vextq_f32(o->x, bIn, 2); float32x4_t a = vmulq_f32(bIn, bX0); float32x4_t b = vmulq_f32(xm1, bX1); float32x4_t c = vmulq_f32(xm2, bX2); float32x4_t d = vaddq_f32(a, b); float32x4_t e = vaddq_f32(c, d); float y0 = e[0] - o->ym1*bY1[0] - o->ym2*bY2[0]; float y1 = e[1] - y0*bY1[1] - o->ym1*bY2[1]; float y2 = e[2] - y1*bY1[2] - y0*bY2[2]; float y3 = e[3] - y2*bY1[3] - y1*bY2[3]; o->x = bIn; o->ym1 = y3; o->ym2 = y2; *bOut = (float32x4_t) {y0, y1, y2, y3}; #else const float y = bIn*bX0 + o->xm1*bX1 + o->xm2*bX2 - o->ym1*bY1 - o->ym2*bY2; o->xm2 = o->xm1; o->xm1 = bIn; o->ym2 = o->ym1; o->ym1 = y; *bOut = y; #endif } static void sBiquad_k_updateCoefficients(SignalBiquad_k *const o) { #if DEBUG // inspect the filter coefficients to ensure that the filter is stable // 1/((1-a*z^-1) * (1-b*z^-1)) float k = (o->a1*o->a1) - (4.0f*o->a2); float l = hv_sqrt_f(hv_abs_f(k)); float m_alpha = 0.0f; float m_beta = 0.0f; if (k < 0.0f) { // alpha is complex float r_alpha = o->a1 * 0.5f; float i_alpha = l * 0.5f; m_alpha = (r_alpha*r_alpha + i_alpha*i_alpha); // |alpha|^2 float r_beta = (o->a2 * r_alpha) / m_alpha; float i_beta = (o->a2 * -i_alpha) / m_alpha; m_alpha = hv_sqrt_f(m_alpha); m_beta = hv_sqrt_f(r_beta*r_beta + i_beta*i_beta); } else { // alpha is real float alpha = (o->a1 + l) * 0.5f; float beta = o->a2 / alpha; m_alpha = hv_abs_f(alpha); m_beta = hv_abs_f(beta); } hv_assert(m_alpha < 1.0f); hv_assert(m_beta < 1.0f); #endif // calculate all filter coefficients in the double domain #if HV_SIMD_AVX || HV_SIMD_SSE || HV_SIMD_NEON double b0 = (double) o->b0; double b1 = (double) o->b1; double b2 = (double) o->b2; double a1 = (double) -o->a1; double a2 = (double) -o->a2; double coeffs[4][8] = { { 0, 0, 0, b0, b1, b2, a1, a2 }, { 0, 0, b0, b1, b2, 0, a2, 0 }, { 0, b0, b1, b2, 0, 0, 0, 0 }, { b0, b1, b2, 0, 0, 0, 0, 0 }, }; for (int i = 0; i < 8; i++) { coeffs[1][i] += a1*coeffs[0][i]; coeffs[2][i] += a1*coeffs[1][i] + a2*coeffs[0][i]; coeffs[3][i] += a1*coeffs[2][i] + a2*coeffs[1][i]; } #if HV_SIMD_AVX || HV_SIMD_SSE o->coeff_xp3 = _mm_set_ps((float) coeffs[3][0], (float) coeffs[2][0], (float) coeffs[1][0], (float) coeffs[0][0]); o->coeff_xp2 = _mm_set_ps((float) coeffs[3][1], (float) coeffs[2][1], (float) coeffs[1][1], (float) coeffs[0][1]); o->coeff_xp1 = _mm_set_ps((float) coeffs[3][2], (float) coeffs[2][2], (float) coeffs[1][2], (float) coeffs[0][2]); o->coeff_x0 = _mm_set_ps((float) coeffs[3][3], (float) coeffs[2][3], (float) coeffs[1][3], (float) coeffs[0][3]); o->coeff_xm1 = _mm_set_ps((float) coeffs[3][4], (float) coeffs[2][4], (float) coeffs[1][4], (float) coeffs[0][4]); o->coeff_xm2 = _mm_set_ps((float) coeffs[3][5], (float) coeffs[2][5], (float) coeffs[1][5], (float) coeffs[0][5]); o->coeff_ym1 = _mm_set_ps((float) coeffs[3][6], (float) coeffs[2][6], (float) coeffs[1][6], (float) coeffs[0][6]); o->coeff_ym2 = _mm_set_ps((float) coeffs[3][7], (float) coeffs[2][7], (float) coeffs[1][7], (float) coeffs[0][7]); #else // HV_SIMD_NEON o->coeff_xp3 = (float32x4_t) {(float) coeffs[0][0], (float) coeffs[1][0], (float) coeffs[2][0], (float) coeffs[3][0]}; o->coeff_xp2 = (float32x4_t) {(float) coeffs[0][1], (float) coeffs[1][1], (float) coeffs[2][1], (float) coeffs[3][1]}; o->coeff_xp1 = (float32x4_t) {(float) coeffs[0][2], (float) coeffs[1][2], (float) coeffs[2][2], (float) coeffs[3][2]}; o->coeff_x0 = (float32x4_t) {(float) coeffs[0][3], (float) coeffs[1][3], (float) coeffs[2][3], (float) coeffs[3][3]}; o->coeff_xm1 = (float32x4_t) {(float) coeffs[0][4], (float) coeffs[1][4], (float) coeffs[2][4], (float) coeffs[3][4]}; o->coeff_xm2 = (float32x4_t) {(float) coeffs[0][5], (float) coeffs[1][5], (float) coeffs[2][5], (float) coeffs[3][5]}; o->coeff_ym1 = (float32x4_t) {(float) coeffs[0][6], (float) coeffs[1][6], (float) coeffs[2][6], (float) coeffs[3][6]}; o->coeff_ym2 = (float32x4_t) {(float) coeffs[0][7], (float) coeffs[1][7], (float) coeffs[2][7], (float) coeffs[3][7]}; #endif #endif // NOTE(mhroth): not necessary to calculate any coefficients for HV_SIMD_NONE case } hv_size_t sBiquad_k_init(SignalBiquad_k *o, float b0, float b1, float b2, float a1, float a2) { // initialise filter coefficients o->b0 = b0; o->b1 = b1; o->b2 = b2; o->a1 = a1; o->a2 = a2; sBiquad_k_updateCoefficients(o); // clear filter state #if HV_SIMD_AVX || HV_SIMD_SSE o->xm1 = _mm_setzero_ps(); o->xm2 = _mm_setzero_ps(); o->ym1 = _mm_setzero_ps(); o->ym2 = _mm_setzero_ps(); #elif HV_SIMD_NEON o->xm1 = vdupq_n_f32(0.0f); o->xm2 = vdupq_n_f32(0.0f); o->ym1 = vdupq_n_f32(0.0f); o->ym2 = vdupq_n_f32(0.0f); #else // HV_SIMD_NONE o->xm1 = 0.0f; o->xm2 = 0.0f; o->ym1 = 0.0f; o->ym2 = 0.0f; #endif return 0; } void sBiquad_k_onMessage(SignalBiquad_k *o, int letIn, const HvMessage *m) { if (msg_isFloat(m,0)) { switch (letIn) { case 1: o->b0 = msg_getFloat(m,0); break; case 2: o->b1 = msg_getFloat(m,0); break; case 3: o->b2 = msg_getFloat(m,0); break; case 4: o->a1 = msg_getFloat(m,0); break; case 5: o->a2 = msg_getFloat(m,0); break; default: return; } sBiquad_k_updateCoefficients(o); } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalBiquad.h0000644000000000000000000001565514435670357017735 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_SIGNAL_BIQUAD_H_ #define _HEAVY_SIGNAL_BIQUAD_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif // http://en.wikipedia.org/wiki/Digital_biquad_filter typedef struct SignalBiquad { #if HV_SIMD_NONE hv_bufferf_t xm1; hv_bufferf_t xm2; #else hv_bufferf_t x; #endif float ym1; float ym2; } SignalBiquad; hv_size_t sBiquad_init(SignalBiquad *o); #if _WIN32 && !_WIN64 // NOTE(mhroth): unfortunately this specific definition of __hv_biquad_f for Win32 is necessary due to // the limited stack and alignment capabilities of the VS compiler in this mode #define __hv_biquad_f(o, bIn, bX0, bX1, bX2, bY1, bY2, bOut) __hv_biquad_f_win32(o, &bIn, &bX0, &bX1, &bX2, &bY1, &bY2, bOut) void __hv_biquad_f_win32(SignalBiquad *o, hv_bInf_t *bIn, hv_bInf_t *bX0, hv_bInf_t *bX1, hv_bInf_t *bX2, hv_bInf_t *bY1, hv_bInf_t *bY2, hv_bOutf_t bOut); #else void __hv_biquad_f(SignalBiquad *o, hv_bInf_t bIn, hv_bInf_t bX0, hv_bInf_t bX1, hv_bInf_t bX2, hv_bInf_t bY1, hv_bInf_t bY2, hv_bOutf_t bOut); #endif typedef struct SignalBiquad_k { #if HV_SIMD_AVX || HV_SIMD_SSE // preprocessed filter coefficients __m128 coeff_xp3; __m128 coeff_xp2; __m128 coeff_xp1; __m128 coeff_x0; __m128 coeff_xm1; __m128 coeff_xm2; __m128 coeff_ym1; __m128 coeff_ym2; // filter state __m128 xm1; __m128 xm2; __m128 ym1; __m128 ym2; #elif HV_SIMD_NEON float32x4_t coeff_xp3; float32x4_t coeff_xp2; float32x4_t coeff_xp1; float32x4_t coeff_x0; float32x4_t coeff_xm1; float32x4_t coeff_xm2; float32x4_t coeff_ym1; float32x4_t coeff_ym2; float32x4_t xm1; float32x4_t xm2; float32x4_t ym1; float32x4_t ym2; #else // HV_SIMD_NONE float xm1; float xm2; float ym1; float ym2; #endif // original filter coefficients float b0; // x[0] float b1; // x[-1] float b2; // x[-2] float a1; // y[-1] float a2; // y[-2] } SignalBiquad_k; hv_size_t sBiquad_k_init(SignalBiquad_k *o, float x0, float x1, float x2, float y1, float y2); void sBiquad_k_onMessage(SignalBiquad_k *o, int letIn, const HvMessage *m); static inline void __hv_biquad_k_f(SignalBiquad_k *o, hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX const __m128 c_xp3 = o->coeff_xp3; const __m128 c_xp2 = o->coeff_xp2; const __m128 c_xp1 = o->coeff_xp1; const __m128 c_x0 = o->coeff_x0; const __m128 c_xm1 = o->coeff_xm1; const __m128 c_xm2 = o->coeff_xm2; const __m128 c_ym1 = o->coeff_ym1; const __m128 c_ym2 = o->coeff_ym2; // lower half __m128 x3 = _mm_set1_ps(bIn[3]); __m128 x2 = _mm_set1_ps(bIn[2]); __m128 x1 = _mm_set1_ps(bIn[1]); __m128 x0 = _mm_set1_ps(bIn[0]); __m128 xm1 = o->xm1; __m128 xm2 = o->xm2; __m128 ym1 = o->ym1; __m128 ym2 = o->ym2; __m128 a = _mm_mul_ps(c_xp3, x3); __m128 b = _mm_mul_ps(c_xp2, x2); __m128 c = _mm_mul_ps(c_xp1, x1); __m128 d = _mm_mul_ps(c_x0, x0); __m128 e = _mm_mul_ps(c_xm1, xm1); __m128 f = _mm_mul_ps(c_xm2, xm2); __m128 g = _mm_mul_ps(c_ym1, ym1); __m128 h = _mm_mul_ps(c_ym2, ym2); __m128 i = _mm_add_ps(a, b); __m128 j = _mm_add_ps(c, d); __m128 k = _mm_add_ps(e, f); __m128 l = _mm_add_ps(g, h); __m128 m = _mm_add_ps(i, j); __m128 n = _mm_add_ps(k, l); __m128 lo_y = _mm_add_ps(m, n); // lower part of output buffer // upper half xm1 = x3; xm2 = x2; x3 = _mm_set1_ps(bIn[7]); x2 = _mm_set1_ps(bIn[6]); x1 = _mm_set1_ps(bIn[5]); x0 = _mm_set1_ps(bIn[4]); ym1 = _mm_set1_ps(lo_y[3]); ym2 = _mm_set1_ps(lo_y[2]); a = _mm_mul_ps(c_xp3, x3); b = _mm_mul_ps(c_xp2, x2); c = _mm_mul_ps(c_xp1, x1); d = _mm_mul_ps(c_x0, x0); e = _mm_mul_ps(c_xm1, xm1); f = _mm_mul_ps(c_xm2, xm2); g = _mm_mul_ps(c_ym1, ym1); h = _mm_mul_ps(c_ym2, ym2); i = _mm_add_ps(a, b); j = _mm_add_ps(c, d); k = _mm_add_ps(e, f); l = _mm_add_ps(g, h); m = _mm_add_ps(i, j); n = _mm_add_ps(k, l); __m128 up_y = _mm_add_ps(m, n); // upper part of output buffer o->xm1 = x3; o->xm2 = x2; o->ym1 = _mm_set1_ps(up_y[3]); o->ym2 = _mm_set1_ps(up_y[2]); *bOut = _mm256_insertf128_ps(_mm256_castps128_ps256(lo_y), up_y, 1); #elif HV_SIMD_SSE __m128 x3 = _mm_shuffle_ps(bIn, bIn, _MM_SHUFFLE(3,3,3,3)); __m128 x2 = _mm_shuffle_ps(bIn, bIn, _MM_SHUFFLE(2,2,2,2)); __m128 x1 = _mm_shuffle_ps(bIn, bIn, _MM_SHUFFLE(1,1,1,1)); __m128 x0 = _mm_shuffle_ps(bIn, bIn, _MM_SHUFFLE(0,0,0,0)); __m128 a = _mm_mul_ps(o->coeff_xp3, x3); __m128 b = _mm_mul_ps(o->coeff_xp2, x2); __m128 c = _mm_mul_ps(o->coeff_xp1, x1); __m128 d = _mm_mul_ps(o->coeff_x0, x0); __m128 e = _mm_mul_ps(o->coeff_xm1, o->xm1); __m128 f = _mm_mul_ps(o->coeff_xm2, o->xm2); __m128 g = _mm_mul_ps(o->coeff_ym1, o->ym1); __m128 h = _mm_mul_ps(o->coeff_ym2, o->ym2); __m128 i = _mm_add_ps(a, b); __m128 j = _mm_add_ps(c, d); __m128 k = _mm_add_ps(e, f); __m128 l = _mm_add_ps(g, h); __m128 m = _mm_add_ps(i, j); __m128 n = _mm_add_ps(k, l); __m128 y = _mm_add_ps(m, n); o->xm1 = x3; o->xm2 = x2; o->ym1 = _mm_shuffle_ps(y, y, _MM_SHUFFLE(3,3,3,3)); o->ym2 = _mm_shuffle_ps(y, y, _MM_SHUFFLE(2,2,2,2)); *bOut = y; #elif HV_SIMD_NEON float32x4_t x3 = vdupq_n_f32(bIn[3]); float32x4_t x2 = vdupq_n_f32(bIn[2]); float32x4_t x1 = vdupq_n_f32(bIn[1]); float32x4_t x0 = vdupq_n_f32(bIn[0]); float32x4_t a = vmulq_f32(o->coeff_xp3, x3); float32x4_t b = vmulq_f32(o->coeff_xp2, x2); float32x4_t c = vmulq_f32(o->coeff_xp1, x1); float32x4_t d = vmulq_f32(o->coeff_x0, x0); float32x4_t e = vmulq_f32(o->coeff_xm1, o->xm1); float32x4_t f = vmulq_f32(o->coeff_xm2, o->xm2); float32x4_t g = vmulq_f32(o->coeff_ym1, o->ym1); float32x4_t h = vmulq_f32(o->coeff_ym2, o->ym2); float32x4_t i = vaddq_f32(a, b); float32x4_t j = vaddq_f32(c, d); float32x4_t k = vaddq_f32(e, f); float32x4_t l = vaddq_f32(g, h); float32x4_t m = vaddq_f32(i, j); float32x4_t n = vaddq_f32(k, l); float32x4_t y = vaddq_f32(m, n); o->xm1 = x3; o->xm2 = x2; o->ym1 = vdupq_n_f32(y[3]); o->ym2 = vdupq_n_f32(y[2]); *bOut = y; #else // HV_SIMD_NONE float y = o->b0*bIn + o->b1*o->xm1 + o->b2*o->xm2 - o->a1*o->ym1 - o->a2*o->ym2; o->xm2 = o->xm1; o->xm1 = bIn; o->ym2 = o->ym1; o->ym1 = y; *bOut = y; #endif } #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_SIGNAL_BIQUAD_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalCPole.c0000644000000000000000000000455414435670357017521 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalCPole.h" hv_size_t sCPole_init(SignalCPole *o) { #if HV_SIMD_AVX sDel1_init(&o->sDel1_8kZ3w); sDel1_init(&o->sDel1_sy3YC); sDel1_init(&o->sDel1_GjjjE); sDel1_init(&o->sDel1_52HYk); sDel1_init(&o->sDel1_lXpu3); sDel1_init(&o->sDel1_orza7); sDel1_init(&o->sDel1_K7tpr); sDel1_init(&o->sDel1_yfNee); sDel1_init(&o->sDel1_hl63z); sDel1_init(&o->sDel1_etJkN); sDel1_init(&o->sDel1_BW4zg); sDel1_init(&o->sDel1_0z8gy); sDel1_init(&o->sDel1_0F5sm); sDel1_init(&o->sDel1_i4rAW); sDel1_init(&o->sDel1_ux1Jv); sDel1_init(&o->sDel1_FVaak); sDel1_init(&o->sDel1_oEc0p); sDel1_init(&o->sDel1_1AVVz); sDel1_init(&o->sDel1_qp6ty); sDel1_init(&o->sDel1_bkttO); sDel1_init(&o->sDel1_60VsH); sDel1_init(&o->sDel1_TbY4f); sDel1_init(&o->sDel1_bNHHm); sDel1_init(&o->sDel1_mijYH); sDel1_init(&o->sDel1_anxSw); sDel1_init(&o->sDel1_YiP2h); sDel1_init(&o->sDel1_anyeH); sDel1_init(&o->sDel1_Vtq0Y); __hv_zero_f(&o->ymr); __hv_zero_f(&o->ymi); #elif HV_SIMD_SSE || HV_SIMD_NEON sDel1_init(&o->sDel1_j0EQa); sDel1_init(&o->sDel1_4REN6); sDel1_init(&o->sDel1_5z88r); sDel1_init(&o->sDel1_CxDdp); sDel1_init(&o->sDel1_8zCWF); sDel1_init(&o->sDel1_1A4op); sDel1_init(&o->sDel1_ldSdM); sDel1_init(&o->sDel1_sOZ64); sDel1_init(&o->sDel1_mpbqn); sDel1_init(&o->sDel1_sBC7F); sDel1_init(&o->sDel1_bZG8k); sDel1_init(&o->sDel1_Wtjof); __hv_zero_f(&o->ymr); __hv_zero_f(&o->ymi); #else o->ymr = 0.0f; o->ymi = 0.0f; #endif return 0; } void sCPole_onMessage(HeavyContextInterface *_c, SignalCPole *o, int letIn, const HvMessage *m) { // TODO } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalCPole.h0000644000000000000000000002673414435670357017532 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SIGNAL_CPOLE_H_ #define _SIGNAL_CPOLE_H_ #include "HvHeavyInternal.h" #include "HvSignalDel1.h" #ifdef __cplusplus extern "C" { #endif // implements y[n] = x[n] - a*y[n-1] // H(z) = 1/(1+a*z^-1) typedef struct SignalCPole { #if HV_SIMD_AVX SignalDel1 sDel1_8kZ3w; SignalDel1 sDel1_sy3YC; SignalDel1 sDel1_GjjjE; SignalDel1 sDel1_52HYk; SignalDel1 sDel1_lXpu3; SignalDel1 sDel1_orza7; SignalDel1 sDel1_K7tpr; SignalDel1 sDel1_yfNee; SignalDel1 sDel1_hl63z; SignalDel1 sDel1_etJkN; SignalDel1 sDel1_BW4zg; SignalDel1 sDel1_0z8gy; SignalDel1 sDel1_0F5sm; SignalDel1 sDel1_i4rAW; SignalDel1 sDel1_ux1Jv; SignalDel1 sDel1_FVaak; SignalDel1 sDel1_oEc0p; SignalDel1 sDel1_1AVVz; SignalDel1 sDel1_qp6ty; SignalDel1 sDel1_bkttO; SignalDel1 sDel1_60VsH; SignalDel1 sDel1_TbY4f; SignalDel1 sDel1_bNHHm; SignalDel1 sDel1_mijYH; SignalDel1 sDel1_anxSw; SignalDel1 sDel1_YiP2h; SignalDel1 sDel1_anyeH; SignalDel1 sDel1_Vtq0Y; hv_bufferf_t ymr; hv_bufferf_t ymi; #elif HV_SIMD_SSE || HV_SIMD_NEON SignalDel1 sDel1_j0EQa; SignalDel1 sDel1_4REN6; SignalDel1 sDel1_5z88r; SignalDel1 sDel1_CxDdp; SignalDel1 sDel1_8zCWF; SignalDel1 sDel1_1A4op; SignalDel1 sDel1_ldSdM; SignalDel1 sDel1_sOZ64; SignalDel1 sDel1_mpbqn; SignalDel1 sDel1_sBC7F; SignalDel1 sDel1_bZG8k; SignalDel1 sDel1_Wtjof; hv_bufferf_t ymr; hv_bufferf_t ymi; #else hv_bufferf_t ymr; hv_bufferf_t ymi; #endif } SignalCPole; hv_size_t sCPole_init(SignalCPole *o); void sCPole_onMessage(HeavyContextInterface *_c, SignalCPole *o, int letIn, const HvMessage *m); #if _WIN32 && !_WIN64 #define __hv_cpole_f(o, bIn0, bIn1, bIn2, bIn3, bOut0, bOut1) __hv_cpole_f_win32(o, &bIn0, &bIn1, &bIn2, &bIn3, bOut0, bOut1) static inline void __hv_cpole_f_win32(SignalCPole *o, hv_bInf_t *_bIn0, hv_bInf_t *_bIn1, hv_bInf_t *_bIn2, hv_bInf_t *_bIn3, hv_bOutf_t bOut0, hv_bOutf_t bOut1) { hv_bInf_t bIn0 = *_bIn0; hv_bInf_t bIn1 = *_bIn1; hv_bInf_t bIn2 = *_bIn2; hv_bInf_t bIn3 = *_bIn3; #else static inline void __hv_cpole_f(SignalCPole *o, hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bInf_t bIn2, hv_bInf_t bIn3, hv_bOutf_t bOut0, hv_bOutf_t bOut1) { #endif #if HV_SIMD_AVX hv_bufferf_t Bf0, Bf1, Bf2, Bf3, Bf4, Bf5, Bf6, Bf7, Bf8, Bf9, Bf10, Bf11, Bf12, Bf13, Bf14; __hv_del1_f(&o->sDel1_8kZ3w, bIn0, VOf(Bf0)); __hv_del1_f(&o->sDel1_sy3YC, bIn1, VOf(Bf1)); __hv_mul_f(VIf(Bf1), bIn2, VOf(Bf2)); __hv_fma_f(VIf(Bf0), bIn3, VIf(Bf2), VOf(Bf2)); __hv_mul_f(VIf(Bf0), bIn2, VOf(Bf3)); __hv_mul_f(VIf(Bf1), bIn3, VOf(Bf4)); __hv_sub_f(VIf(Bf3), VIf(Bf4), VOf(Bf4)); __hv_sub_f(bIn1, VIf(Bf2), VOf(Bf2)); __hv_del1_f(&o->sDel1_GjjjE, VIf(Bf0), VOf(Bf0)); __hv_del1_f(&o->sDel1_52HYk, VIf(Bf1), VOf(Bf1)); __hv_del1_f(&o->sDel1_lXpu3, bIn2, VOf(Bf3)); __hv_del1_f(&o->sDel1_orza7, bIn3, VOf(Bf5)); __hv_mul_f(bIn2, VIf(Bf3), VOf(Bf6)); __hv_mul_f(bIn3, VIf(Bf5), VOf(Bf7)); __hv_sub_f(VIf(Bf6), VIf(Bf7), VOf(Bf7)); __hv_mul_f(bIn3, VIf(Bf3), VOf(Bf6)); __hv_fma_f(bIn2, VIf(Bf5), VIf(Bf6), VOf(Bf6)); __hv_mul_f(VIf(Bf0), VIf(Bf6), VOf(Bf8)); __hv_fma_f(VIf(Bf1), VIf(Bf7), VIf(Bf8), VOf(Bf8)); __hv_mul_f(VIf(Bf0), VIf(Bf7), VOf(Bf9)); __hv_mul_f(VIf(Bf1), VIf(Bf6), VOf(Bf10)); __hv_sub_f(VIf(Bf9), VIf(Bf10), VOf(Bf10)); __hv_add_f(VIf(Bf2), VIf(Bf8), VOf(Bf8)); __hv_del1_f(&o->sDel1_K7tpr, VIf(Bf0), VOf(Bf0)); __hv_del1_f(&o->sDel1_yfNee, VIf(Bf1), VOf(Bf1)); __hv_del1_f(&o->sDel1_hl63z, VIf(Bf3), VOf(Bf3)); __hv_del1_f(&o->sDel1_etJkN, VIf(Bf5), VOf(Bf5)); __hv_mul_f(VIf(Bf7), VIf(Bf3), VOf(Bf2)); __hv_mul_f(VIf(Bf6), VIf(Bf5), VOf(Bf9)); __hv_sub_f(VIf(Bf2), VIf(Bf9), VOf(Bf9)); __hv_mul_f(VIf(Bf7), VIf(Bf5), VOf(Bf7)); __hv_fma_f(VIf(Bf6), VIf(Bf3), VIf(Bf7), VOf(Bf7)); __hv_mul_f(VIf(Bf1), VIf(Bf9), VOf(Bf6)); __hv_fma_f(VIf(Bf0), VIf(Bf7), VIf(Bf6), VOf(Bf6)); __hv_mul_f(VIf(Bf0), VIf(Bf9), VOf(Bf2)); __hv_mul_f(VIf(Bf1), VIf(Bf7), VOf(Bf11)); __hv_sub_f(VIf(Bf2), VIf(Bf11), VOf(Bf11)); __hv_sub_f(VIf(Bf8), VIf(Bf6), VOf(Bf6)); __hv_del1_f(&o->sDel1_BW4zg, VIf(Bf0), VOf(Bf0)); __hv_del1_f(&o->sDel1_0z8gy, VIf(Bf1), VOf(Bf1)); __hv_del1_f(&o->sDel1_0F5sm, VIf(Bf3), VOf(Bf3)); __hv_del1_f(&o->sDel1_i4rAW, VIf(Bf5), VOf(Bf5)); __hv_mul_f(VIf(Bf7), VIf(Bf3), VOf(Bf8)); __hv_fma_f(VIf(Bf9), VIf(Bf5), VIf(Bf8), VOf(Bf8)); __hv_mul_f(VIf(Bf9), VIf(Bf3), VOf(Bf9)); __hv_mul_f(VIf(Bf7), VIf(Bf5), VOf(Bf7)); __hv_sub_f(VIf(Bf9), VIf(Bf7), VOf(Bf7)); __hv_mul_f(VIf(Bf0), VIf(Bf7), VOf(Bf9)); __hv_mul_f(VIf(Bf1), VIf(Bf8), VOf(Bf2)); __hv_sub_f(VIf(Bf9), VIf(Bf2), VOf(Bf2)); __hv_mul_f(VIf(Bf0), VIf(Bf8), VOf(Bf9)); __hv_fma_f(VIf(Bf1), VIf(Bf7), VIf(Bf9), VOf(Bf9)); __hv_add_f(VIf(Bf6), VIf(Bf9), VOf(Bf9)); __hv_del1_f(&o->sDel1_ux1Jv, VIf(Bf0), VOf(Bf0)); __hv_del1_f(&o->sDel1_FVaak, VIf(Bf1), VOf(Bf1)); __hv_del1_f(&o->sDel1_oEc0p, VIf(Bf3), VOf(Bf3)); __hv_del1_f(&o->sDel1_1AVVz, VIf(Bf5), VOf(Bf5)); __hv_mul_f(VIf(Bf8), VIf(Bf3), VOf(Bf6)); __hv_fma_f(VIf(Bf7), VIf(Bf5), VIf(Bf6), VOf(Bf6)); __hv_mul_f(VIf(Bf7), VIf(Bf3), VOf(Bf7)); __hv_mul_f(VIf(Bf8), VIf(Bf5), VOf(Bf8)); __hv_sub_f(VIf(Bf7), VIf(Bf8), VOf(Bf8)); __hv_mul_f(VIf(Bf0), VIf(Bf8), VOf(Bf7)); __hv_mul_f(VIf(Bf1), VIf(Bf6), VOf(Bf12)); __hv_sub_f(VIf(Bf7), VIf(Bf12), VOf(Bf12)); __hv_mul_f(VIf(Bf1), VIf(Bf8), VOf(Bf7)); __hv_fma_f(VIf(Bf0), VIf(Bf6), VIf(Bf7), VOf(Bf7)); __hv_sub_f(VIf(Bf9), VIf(Bf7), VOf(Bf7)); __hv_del1_f(&o->sDel1_qp6ty, VIf(Bf0), VOf(Bf0)); __hv_del1_f(&o->sDel1_bkttO, VIf(Bf1), VOf(Bf1)); __hv_del1_f(&o->sDel1_60VsH, VIf(Bf3), VOf(Bf3)); __hv_del1_f(&o->sDel1_TbY4f, VIf(Bf5), VOf(Bf5)); __hv_mul_f(VIf(Bf6), VIf(Bf3), VOf(Bf9)); __hv_fma_f(VIf(Bf8), VIf(Bf5), VIf(Bf9), VOf(Bf9)); __hv_mul_f(VIf(Bf8), VIf(Bf3), VOf(Bf8)); __hv_mul_f(VIf(Bf6), VIf(Bf5), VOf(Bf6)); __hv_sub_f(VIf(Bf8), VIf(Bf6), VOf(Bf6)); __hv_mul_f(VIf(Bf0), VIf(Bf9), VOf(Bf8)); __hv_fma_f(VIf(Bf1), VIf(Bf6), VIf(Bf8), VOf(Bf8)); __hv_mul_f(VIf(Bf0), VIf(Bf6), VOf(Bf13)); __hv_mul_f(VIf(Bf1), VIf(Bf9), VOf(Bf14)); __hv_sub_f(VIf(Bf13), VIf(Bf14), VOf(Bf14)); __hv_add_f(VIf(Bf7), VIf(Bf8), VOf(Bf8)); __hv_del1_f(&o->sDel1_bNHHm, VIf(Bf0), VOf(Bf0)); __hv_del1_f(&o->sDel1_mijYH, VIf(Bf1), VOf(Bf1)); __hv_del1_f(&o->sDel1_anxSw, VIf(Bf3), VOf(Bf3)); __hv_del1_f(&o->sDel1_YiP2h, VIf(Bf5), VOf(Bf5)); __hv_mul_f(VIf(Bf6), VIf(Bf5), VOf(Bf7)); __hv_fma_f(VIf(Bf9), VIf(Bf3), VIf(Bf7), VOf(Bf7)); __hv_mul_f(VIf(Bf6), VIf(Bf3), VOf(Bf6)); __hv_mul_f(VIf(Bf9), VIf(Bf5), VOf(Bf9)); __hv_sub_f(VIf(Bf6), VIf(Bf9), VOf(Bf9)); __hv_mul_f(VIf(Bf0), VIf(Bf9), VOf(Bf6)); __hv_mul_f(VIf(Bf1), VIf(Bf7), VOf(Bf13)); __hv_sub_f(VIf(Bf6), VIf(Bf13), VOf(Bf13)); __hv_mul_f(VIf(Bf0), VIf(Bf7), VOf(Bf0)); __hv_fma_f(VIf(Bf1), VIf(Bf9), VIf(Bf0), VOf(Bf0)); __hv_sub_f(VIf(Bf8), VIf(Bf0), VOf(Bf0)); __hv_del1_f(&o->sDel1_anyeH, VIf(Bf3), VOf(Bf3)); __hv_del1_f(&o->sDel1_Vtq0Y, VIf(Bf5), VOf(Bf5)); __hv_mul_f(VIf(Bf9), VIf(Bf3), VOf(Bf8)); __hv_mul_f(VIf(Bf7), VIf(Bf5), VOf(Bf1)); __hv_sub_f(VIf(Bf8), VIf(Bf1), VOf(Bf1)); __hv_mul_f(VIf(Bf9), VIf(Bf5), VOf(Bf5)); __hv_fma_f(VIf(Bf7), VIf(Bf3), VIf(Bf5), VOf(Bf5)); Bf3 = o->ymr; Bf4 = o->ymi; __hv_mul_f(VIf(Bf1), VIf(Bf3), VOf(Bf9)); __hv_mul_f(VIf(Bf5), VIf(Bf7), VOf(Bf8)); __hv_sub_f(VIf(Bf9), VIf(Bf8), VOf(Bf8)); __hv_mul_f(VIf(Bf1), VIf(Bf7), VOf(Bf7)); __hv_fma_f(VIf(Bf5), VIf(Bf3), VIf(Bf7), VOf(Bf7)); __hv_add_f(VIf(Bf0), VIf(Bf7), VOf(Bf7)); o->ymi = Bf7; __hv_sub_f(bIn0, VIf(Bf4), VOf(Bf4)); __hv_add_f(VIf(Bf4), VIf(Bf10), VOf(Bf10)); __hv_sub_f(VIf(Bf10), VIf(Bf11), VOf(Bf11)); __hv_add_f(VIf(Bf11), VIf(Bf2), VOf(Bf2)); __hv_sub_f(VIf(Bf2), VIf(Bf12), VOf(Bf12)); __hv_add_f(VIf(Bf12), VIf(Bf14), VOf(Bf14)); __hv_sub_f(VIf(Bf14), VIf(Bf13), VOf(Bf13)); __hv_add_f(VIf(Bf13), VIf(Bf8), VOf(Bf8)); *bOut0 = Bf8; *bOut0 = Bf7; o->ymr = Bf8; #elif HV_SIMD_SSE || HV_SIMD_NEON hv_bufferf_t Bf0, Bf1, Bf2, Bf3, Bf4, Bf5, Bf6, Bf7, Bf8, Bf9, Bf10; __hv_del1_f(&o->sDel1_j0EQa, bIn0, VOf(Bf0)); __hv_del1_f(&o->sDel1_4REN6, bIn1, VOf(Bf1)); __hv_mul_f(VIf(Bf0), bIn3, VOf(Bf2)); __hv_fma_f(VIf(Bf1), bIn2, VIf(Bf2), VOf(Bf2)); __hv_mul_f(VIf(Bf0), bIn2, VOf(Bf3)); __hv_mul_f(VIf(Bf1), bIn3, VOf(Bf4)); __hv_sub_f(VIf(Bf3), VIf(Bf4), VOf(Bf4)); __hv_sub_f(bIn1, VIf(Bf2), VOf(Bf2)); __hv_del1_f(&o->sDel1_5z88r, VIf(Bf0), VOf(Bf0)); __hv_del1_f(&o->sDel1_CxDdp, VIf(Bf1), VOf(Bf1)); __hv_del1_f(&o->sDel1_8zCWF, bIn2, VOf(Bf3)); __hv_del1_f(&o->sDel1_1A4op, bIn3, VOf(Bf5)); __hv_mul_f(bIn3, VIf(Bf3), VOf(Bf6)); __hv_fma_f(bIn2, VIf(Bf5), VIf(Bf6), VOf(Bf6)); __hv_mul_f(bIn2, VIf(Bf3), VOf(Bf7)); __hv_mul_f(bIn3, VIf(Bf5), VOf(Bf8)); __hv_sub_f(VIf(Bf7), VIf(Bf8), VOf(Bf8)); __hv_mul_f(VIf(Bf0), VIf(Bf8), VOf(Bf7)); __hv_mul_f(VIf(Bf1), VIf(Bf6), VOf(Bf9)); __hv_sub_f(VIf(Bf7), VIf(Bf9), VOf(Bf9)); __hv_mul_f(VIf(Bf0), VIf(Bf6), VOf(Bf7)); __hv_fma_f(VIf(Bf1), VIf(Bf8), VIf(Bf7), VOf(Bf7)); __hv_add_f(VIf(Bf2), VIf(Bf7), VOf(Bf7)); __hv_del1_f(&o->sDel1_ldSdM, VIf(Bf0), VOf(Bf0)); __hv_del1_f(&o->sDel1_sOZ64, VIf(Bf1), VOf(Bf1)); __hv_del1_f(&o->sDel1_mpbqn, VIf(Bf3), VOf(Bf3)); __hv_del1_f(&o->sDel1_sBC7F, VIf(Bf5), VOf(Bf5)); __hv_mul_f(VIf(Bf6), VIf(Bf3), VOf(Bf2)); __hv_fma_f(VIf(Bf8), VIf(Bf5), VIf(Bf2), VOf(Bf2)); __hv_mul_f(VIf(Bf8), VIf(Bf3), VOf(Bf8)); __hv_mul_f(VIf(Bf6), VIf(Bf5), VOf(Bf6)); __hv_sub_f(VIf(Bf8), VIf(Bf6), VOf(Bf6)); __hv_mul_f(VIf(Bf0), VIf(Bf6), VOf(Bf8)); __hv_mul_f(VIf(Bf1), VIf(Bf2), VOf(Bf10)); __hv_sub_f(VIf(Bf8), VIf(Bf10), VOf(Bf10)); __hv_mul_f(VIf(Bf1), VIf(Bf6), VOf(Bf1)); __hv_fma_f(VIf(Bf0), VIf(Bf2), VIf(Bf1), VOf(Bf1)); __hv_sub_f(VIf(Bf7), VIf(Bf1), VOf(Bf1)); __hv_del1_f(&o->sDel1_bZG8k, VIf(Bf3), VOf(Bf3)); __hv_del1_f(&o->sDel1_Wtjof, VIf(Bf5), VOf(Bf5)); __hv_mul_f(VIf(Bf6), VIf(Bf3), VOf(Bf7)); __hv_mul_f(VIf(Bf2), VIf(Bf5), VOf(Bf0)); __hv_sub_f(VIf(Bf7), VIf(Bf0), VOf(Bf0)); __hv_mul_f(VIf(Bf2), VIf(Bf3), VOf(Bf3)); __hv_fma_f(VIf(Bf6), VIf(Bf5), VIf(Bf3), VOf(Bf3)); Bf5 = o->ymr; Bf6 = o->ymi; __hv_mul_f(VIf(Bf3), VIf(Bf5), VOf(Bf2)); __hv_fma_f(VIf(Bf0), VIf(Bf6), VIf(Bf2), VOf(Bf2)); __hv_mul_f(VIf(Bf0), VIf(Bf5), VOf(Bf5)); __hv_mul_f(VIf(Bf3), VIf(Bf6), VOf(Bf6)); __hv_sub_f(VIf(Bf5), VIf(Bf6), VOf(Bf6)); __hv_add_f(VIf(Bf1), VIf(Bf2), VOf(Bf2)); *bOut1 = Bf2; __hv_sub_f(bIn0, VIf(Bf4), VOf(Bf4)); __hv_add_f(VIf(Bf4), VIf(Bf9), VOf(Bf9)); __hv_sub_f(VIf(Bf9), VIf(Bf10), VOf(Bf10)); __hv_add_f(VIf(Bf10), VIf(Bf6), VOf(Bf6)); *bOut0 = Bf6; o->ymr = Bf6; o->ymi = Bf2; #else *bOut0 = bIn0 - (bIn2*o->ymr - bIn3*o->ymi); *bOut1 = bIn1 - (bIn2*o->ymi + bIn3*o->ymr); o->ymr = *bOut0; o->ymi = *bOut1; #endif } #ifdef __cplusplus } // extern "C" #endif #endif // _SIGNAL_CPOLE_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1690125089.643077 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalConvolution.c0000644000000000000000000001132514457241442021021 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalConvolution.h" hv_size_t sConv_init(SignalConvolution *o, struct HvTable *table, const int size) { o->table = table; hv_size_t numBytes = hTable_init(&o->inputs, size); return numBytes; } void sConv_free(SignalConvolution *o) { o->table = NULL; hTable_free(&o->inputs); } void sConv_onMessage(HeavyContextInterface *_c, SignalConvolution *o, int letIndex, const HvMessage *m, void *sendMessage) { switch (letIndex) { case 1: { if (msg_isHashLike(m,0)) { HvTable *table = hv_table_get(_c, msg_getHash(m,0)); if (table != NULL) { o->table = table; if (hTable_getSize(&o->inputs) != hTable_getSize(table)) { hTable_resize(&o->inputs, (hv_uint32_t) hv_min_ui(hTable_getSize(&o->inputs), hTable_getSize(table))); } } } break; } case 2: { if (msg_isFloat(m,0)) { // convolution size should never exceed the coefficient table size hTable_resize(&o->inputs, (hv_uint32_t) msg_getFloat(m,0)); } break; } default: return; } } static hv_bInf_t sConv_kernel(hv_bInf_t bIn, hv_bInf_t bInPrev, hv_bInf_t bInCoeff) { #if HV_SIMD_AVX hv_assert(false & "There is no AVX implementation of __hv_conv_f"); hv_bufferf_t d = _mm256_setzero_ps(); #elif HV_SIMD_SSE __m128 c0 = _mm_shuffle_ps(bInCoeff, bInCoeff, _MM_SHUFFLE(0,0,0,0)); __m128 c1 = _mm_shuffle_ps(bInCoeff, bInCoeff, _MM_SHUFFLE(1,1,1,1)); __m128 c2 = _mm_shuffle_ps(bInCoeff, bInCoeff, _MM_SHUFFLE(2,2,2,2)); __m128 c3 = _mm_shuffle_ps(bInCoeff, bInCoeff, _MM_SHUFFLE(3,3,3,3)); __m128 m0 = bIn; __m128 m2 = _mm_shuffle_ps(bInPrev, bIn, _MM_SHUFFLE(1,0,3,2)); __m128 m1 = _mm_shuffle_ps(m2, bIn, _MM_SHUFFLE(2,1,2,1)); __m128 m3 = _mm_shuffle_ps(bInPrev, m2, _MM_SHUFFLE(2,1,2,1)); hv_bufferf_t a, b, c, d; __hv_mul_f(c0, m0, &a); __hv_fma_f(c1, m1, a, &b); __hv_fma_f(c2, m2, b, &c); __hv_fma_f(c3, m3, c, &d); #elif HV_SIMD_NEON float32x4_t c0 = vdupq_lane_f32(vget_low_f32(bInCoeff), 0); float32x4_t c1 = vdupq_lane_f32(vget_low_f32(bInCoeff), 1); float32x4_t c2 = vdupq_lane_f32(vget_high_f32(bInCoeff), 0); float32x4_t c3 = vdupq_lane_f32(vget_high_f32(bInCoeff), 1); float32x4_t m0 = bIn; float32x4_t m1 = vextq_f32(bInPrev, bIn, 0x3); float32x4_t m2 = vextq_f32(bInPrev, bIn, 0x2); float32x4_t m3 = vextq_f32(bInPrev, bIn, 0x1); hv_bufferf_t a, b, c, d; __hv_mul_f(c0, m0, &a); __hv_fma_f(c1, m1, a, &b); __hv_fma_f(c2, m2, b, &c); __hv_fma_f(c3, m3, c, &d); #else // HV_SIMD_NONE hv_bufferf_t d = bIn * bInCoeff; #endif return d; } static inline int wrap(const int i, const int n) { if (i < 0) return (i+n); if (i >= n) return (i-n); return i; } void __hv_conv_f(SignalConvolution *o, hv_bInf_t bIn, hv_bOutf_t bOut) { hv_assert(o->table != NULL); float *const coeffs = hTable_getBuffer(o->table); hv_assert(coeffs != NULL); const int n = hTable_getSize(o->table); // length fir filter hv_assert((n&HV_N_SIMD_MASK) == 0); // n is a multiple of HV_N_SIMD float *const inputs = hTable_getBuffer(&o->inputs); hv_assert(inputs != NULL); const int m = hTable_getSize(&o->inputs); // length of input buffer. hv_assert(m >= n); const int h_orig = hTable_getHead(&o->inputs); hv_bufferf_t x0, out; x0 = bIn; __hv_zero_f(&out); int i = 0; int h = wrap(h_orig-HV_N_SIMD, m); for (; h >= 0; i+=HV_N_SIMD, h-=HV_N_SIMD) { hv_bufferf_t x1, c, o; __hv_load_f(inputs+h, &x1); __hv_load_f(coeffs+i, &c); o = sConv_kernel(x0, x1, c); __hv_add_f(o, out, &out); x0 = x1; } h += m; // h = m-HV_N_SIMD; for (; i < n; i+=HV_N_SIMD, h-=HV_N_SIMD) { hv_bufferf_t x1, c, o; __hv_load_f(inputs+h, &x1); __hv_load_f(coeffs+i, &c); o = sConv_kernel(x0, x1, c); __hv_add_f(o, out, &out); x0 = x1; } *bOut = out; __hv_store_f(inputs+h_orig, bIn); // store the new input to the inputs buffer hTable_setHead(&o->inputs, wrap(h_orig+HV_N_SIMD, m)); } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalConvolution.h0000644000000000000000000000262514435670357021040 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SIGNAL_CONVOLUTION_H_ #define _SIGNAL_CONVOLUTION_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct SignalConvolution { struct HvTable *table; struct HvTable inputs; } SignalConvolution; hv_size_t sConv_init(SignalConvolution *o, struct HvTable *coeffs, const int size); void sConv_free(SignalConvolution *o); void sConv_onMessage(HeavyContextInterface *_c, SignalConvolution *o, int letIndex, const HvMessage *m, void *sendMessage); void __hv_conv_f(SignalConvolution *o, hv_bInf_t bIn, hv_bOutf_t bOut); #ifdef __cplusplus } // extern "C" #endif #endif // _SIGNAL_CONVOLUTION_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalDel1.c0000644000000000000000000000255214435670357017300 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalDel1.h" hv_size_t sDel1_init(SignalDel1 *o) { #if HV_SIMD_AVX o->x = _mm256_setzero_ps(); #elif HV_SIMD_SSE o->x = _mm_setzero_ps(); #elif HV_SIMD_NEON o->x = vdupq_n_f32(0.0f); #else o->x = 0.0f; #endif return 0; } void sDel1_onMessage(HeavyContextInterface *_c, SignalDel1 *o, int letIn, const HvMessage *m) { if (letIn == 2) { if (msg_compareSymbol(m, 0, "clear")) { #if HV_SIMD_AVX o->x = _mm256_setzero_ps(); #elif HV_SIMD_SSE o->x = _mm_setzero_ps(); #elif HV_SIMD_NEON o->x = vdupq_n_f32(0.0f); #else o->x = 0.0f; #endif } } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalDel1.h0000644000000000000000000000335114435670357017303 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SIGNAL_DEL1_H_ #define _SIGNAL_DEL1_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct SignalDel1 { hv_bufferf_t x; } SignalDel1; hv_size_t sDel1_init(SignalDel1 *o); void sDel1_onMessage(HeavyContextInterface *_c, SignalDel1 *o, int letIn, const HvMessage *m); static inline void __hv_del1_f(SignalDel1 *o, hv_bInf_t bIn0, hv_bOutf_t bOut) { #if HV_SIMD_AVX __m256 x = _mm256_permute_ps(bIn0, _MM_SHUFFLE(2,1,0,3)); // [3 0 1 2 7 4 5 6] __m256 n = _mm256_permute2f128_ps(o->x,x,0x1); // [h e f g 3 0 1 2] *bOut = _mm256_blend_ps(x, n, 0x11); // [h 0 1 2 3 4 5 6] o->x = x; #elif HV_SIMD_SSE __m128 n = _mm_blend_ps(o->x, bIn0, 0x7); *bOut = _mm_shuffle_ps(n, n, _MM_SHUFFLE(2,1,0,3)); o->x = bIn0; #elif HV_SIMD_NEON *bOut = vextq_f32(o->x, bIn0, 3); o->x = bIn0; #else *bOut = o->x; o->x = bIn0; #endif } #ifdef __cplusplus } // extern "C" #endif #endif // _SIGNAL_DEL1_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalEnvelope.c0000644000000000000000000001333414435670357020270 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalEnvelope.h" #ifndef M_PI #define M_PI 3.14159265358979323846 // in case math.h doesn't include this defintion #endif static int ceilToNearestBlock(int x, int n) { return (int) (ceilf(((float) x) / ((float) n)) * n); } hv_size_t sEnv_init(SignalEnvelope *o, int windowSize, int period) { // 0 < BLOCK_SIZE <= period <= windowSize // NOTE(mhroth): this is an artificial limit, but it greatly simplifies development o->windowSize = (windowSize <= HV_N_SIMD) ? HV_N_SIMD : ceilToNearestBlock(windowSize, HV_N_SIMD); o->period = (period <= HV_N_SIMD) ? HV_N_SIMD : (period > o->windowSize) ? o->windowSize : ceilToNearestBlock(period, HV_N_SIMD); o->numSamplesInBuffer = 0; hv_size_t numBytes = 0; // allocate the signal buffer // the buffer is overdimensioned in this way (up to double), but not by much and so what const int bufferLength = 2 * o->windowSize; o->buffer = (float *) hv_malloc(bufferLength*sizeof(float)); hv_assert(o->buffer != NULL); numBytes += bufferLength*sizeof(float); // allocate and calculate the hanning weights o->hanningWeights = (float *) hv_malloc(o->windowSize*sizeof(float)); hv_assert(o->hanningWeights != NULL); numBytes += o->windowSize*sizeof(float); float hanningSum = 0.0f; for (int i = 0; i < o->windowSize; i++) { const float w = 0.5f * (1.0f - cosf(((float) (2.0 * M_PI * i)) / ((float) (o->windowSize - 1)))); o->hanningWeights[i] = w; hanningSum += w; } for (int i = 0; i < o->windowSize; i++) { // normalise the hanning coefficients such that they represent a normalised weighted averaging o->hanningWeights[i] /= hanningSum; } return numBytes; } void sEnv_free(SignalEnvelope *o) { hv_free(o->hanningWeights); hv_free(o->buffer); } static void sEnv_sendMessage(HeavyContextInterface *_c, SignalEnvelope *o, float rms, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { // finish RMS calculation. sqrt is removed as it can be combined with the log operation. // result is normalised such that 1 RMS == 100 dB rms = (4.342944819032518f * hv_log_f(rms)) + 100.0f; // prepare the outgoing message. Schedule it at the beginning of the next block. HvMessage *const m = HV_MESSAGE_ON_STACK(1); msg_initWithFloat(m, hv_getCurrentSample(_c) + HV_N_SIMD, (rms < 0.0f) ? 0.0f : rms); hv_scheduleMessageForObject(_c, m, sendMessage, 0); hv_memcpy(o->buffer, o->buffer+o->period, sizeof(float)*(o->numSamplesInBuffer - o->period)); o->numSamplesInBuffer -= o->period; } void sEnv_process(HeavyContextInterface *_c, SignalEnvelope *o, hv_bInf_t bIn, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { #if HV_SIMD_AVX _mm256_stream_ps(o->buffer+o->numSamplesInBuffer, _mm256_mul_ps(bIn,bIn)); // store bIn^2, no need to cache block o->numSamplesInBuffer += HV_N_SIMD; if (o->numSamplesInBuffer >= o->windowSize) { int n4 = o->windowSize & ~HV_N_SIMD_MASK; __m256 sum = _mm256_setzero_ps(); while (n4) { __m256 x = _mm256_load_ps(o->buffer + n4 - HV_N_SIMD); __m256 h = _mm256_load_ps(o->hanningWeights + n4 - HV_N_SIMD); x = _mm256_mul_ps(x, h); sum = _mm256_add_ps(sum, x); n4 -= HV_N_SIMD; } sum = _mm256_hadd_ps(sum,sum); // horizontal sum sum = _mm256_hadd_ps(sum,sum); sEnv_sendMessage(_c, o, sum[0]+sum[4], sendMessage); // updates numSamplesInBuffer } #elif HV_SIMD_SSE _mm_stream_ps(o->buffer+o->numSamplesInBuffer, _mm_mul_ps(bIn,bIn)); // store bIn^2, no need to cache block o->numSamplesInBuffer += HV_N_SIMD; if (o->numSamplesInBuffer >= o->windowSize) { int n4 = o->windowSize & ~HV_N_SIMD_MASK; __m128 sum = _mm_setzero_ps(); while (n4) { __m128 x = _mm_load_ps(o->buffer + n4 - HV_N_SIMD); __m128 h = _mm_load_ps(o->hanningWeights + n4 - HV_N_SIMD); x = _mm_mul_ps(x, h); sum = _mm_add_ps(sum, x); n4 -= HV_N_SIMD; } sum = _mm_hadd_ps(sum,sum); // horizontal sum sum = _mm_hadd_ps(sum,sum); float f; _mm_store_ss(&f, sum); sEnv_sendMessage(_c, o, f, sendMessage); } #elif HV_SIMD_NEON vst1q_f32(o->buffer+o->numSamplesInBuffer, vmulq_f32(bIn,bIn)); // store bIn^2, no need to cache block o->numSamplesInBuffer += HV_N_SIMD; if (o->numSamplesInBuffer >= o->windowSize) { int n4 = o->windowSize & ~HV_N_SIMD_MASK; float32x4_t sum = vdupq_n_f32(0.0f); while (n4) { float32x4_t x = vld1q_f32(o->buffer + n4 - HV_N_SIMD); float32x4_t h = vld1q_f32(o->hanningWeights + n4 - HV_N_SIMD); x = vmulq_f32(x, h); sum = vaddq_f32(sum, x); n4 -= HV_N_SIMD; } sEnv_sendMessage(_c, o, sum[0]+sum[1]+sum[2]+sum[3], sendMessage); } #else // HV_SIMD_NONE o->buffer[o->numSamplesInBuffer] = (bIn*bIn); o->numSamplesInBuffer += HV_N_SIMD; if (o->numSamplesInBuffer >= o->windowSize) { float sum = 0.0f; for (int i = 0; i < o->windowSize; ++i) { sum += (o->hanningWeights[i] * o->buffer[i]); } sEnv_sendMessage(_c, o, sum, sendMessage); } #endif } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalEnvelope.h0000644000000000000000000000256014435670357020274 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SIGNAL_ENVELOPE_H_ #define _SIGNAL_ENVELOPE_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct SignalEnvelope { int windowSize; int period; int numSamplesInBuffer; float *hanningWeights; float *buffer; } SignalEnvelope; hv_size_t sEnv_init(SignalEnvelope *o, int windowSize, int period); void sEnv_free(SignalEnvelope *o); void sEnv_process(HeavyContextInterface *_c, SignalEnvelope *o, hv_bInf_t bIn, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #ifdef __cplusplus } // extern "C" #endif #endif // _SIGNAL_ENVELOPE_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalLine.c0000644000000000000000000001155614435670357017406 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalLine.h" hv_size_t sLine_init(SignalLine *o) { #if HV_SIMD_AVX o->n = _mm_setzero_si128(); o->x = _mm256_setzero_ps(); o->m = _mm256_setzero_ps(); o->t = _mm256_setzero_ps(); #elif HV_SIMD_SSE o->n = _mm_setzero_si128(); o->x = _mm_setzero_ps(); o->m = _mm_setzero_ps(); o->t = _mm_setzero_ps(); #elif HV_SIMD_NEON o->n = vdupq_n_s32(0); o->x = vdupq_n_f32(0.0f); o->m = vdupq_n_f32(0.0f); o->t = vdupq_n_f32(0.0f); #else // HV_SIMD_NONE o->n = 0; o->x = 0.0f; o->m = 0.0f; o->t = 0.0f; #endif return 0; } void sLine_onMessage(HeavyContextInterface *_c, SignalLine *o, int letIn, const HvMessage *m, void *sendMessage) { if (msg_isFloat(m,0)) { if (msg_isFloat(m,1)) { // new ramp int n = (int) hv_millisecondsToSamples(_c, msg_getFloat(m,1)); #if HV_SIMD_AVX float x = (o->n[1] > 0) ? (o->x[7] + (o->m[7]/8.0f)) : o->t[7]; // current output value float s = (msg_getFloat(m,0) - x) / ((float) n); // slope per sample o->n = _mm_set_epi32(n-3, n-2, n-1, n); o->x = _mm256_set_ps(x+7.0f*s, x+6.0f*s, x+5.0f*s, x+4.0f*s, x+3.0f*s, x+2.0f*s, x+s, x); o->m = _mm256_set1_ps(8.0f*s); o->t = _mm256_set1_ps(msg_getFloat(m,0)); #elif HV_SIMD_SSE const hv_int32_t *const on = (hv_int32_t *) &o->n; const float *const ox = (float *) &o->x; const float *const om = (float *) &o->m; const float *const ot = (float *) &o->t; float x = (on[3] > 0) ? (ox[3] + (om[3]/4.0f)) : ot[3]; float s = (msg_getFloat(m,0) - x) / ((float) n); // slope per sample o->n = _mm_set_epi32(n-3, n-2, n-1, n); o->x = _mm_set_ps(x+3.0f*s, x+2.0f*s, x+s, x); o->m = _mm_set1_ps(4.0f*s); o->t = _mm_set1_ps(msg_getFloat(m,0)); #elif HV_SIMD_NEON float x = (o->n[3] > 0) ? (o->x[3] + (o->m[3]/4.0f)) : o->t[3]; float s = (msg_getFloat(m,0) - x) / ((float) n); o->n = (int32x4_t) {n, n-1, n-2, n-3}; o->x = (float32x4_t) {x, x+s, x+2.0f*s, x+3.0f*s}; o->m = vdupq_n_f32(4.0f*s); o->t = vdupq_n_f32(msg_getFloat(m,0)); #else // HV_SIMD_NONE o->x = (o->n > 0) ? (o->x + o->m) : o->t; // new current value o->n = n; // new distance to target o->m = (msg_getFloat(m,0) - o->x) / ((float) n); // slope per sample o->t = msg_getFloat(m,0); #endif } else { // Jump to value #if HV_SIMD_AVX o->n = _mm_setzero_si128(); o->x = _mm256_set1_ps(msg_getFloat(m,0)); o->m = _mm256_setzero_ps(); o->t = _mm256_set1_ps(msg_getFloat(m,0)); #elif HV_SIMD_SSE o->n = _mm_setzero_si128(); o->x = _mm_set1_ps(msg_getFloat(m,0)); o->m = _mm_setzero_ps(); o->t = _mm_set1_ps(msg_getFloat(m,0)); #elif HV_SIMD_NEON o->n = vdupq_n_s32(0); o->x = vdupq_n_f32(msg_getFloat(m,0)); o->m = vdupq_n_f32(0.0f); o->t = vdupq_n_f32(msg_getFloat(m,0)); #else // HV_SIMD_NONE o->n = 0; o->x = msg_getFloat(m,0); o->m = 0.0f; o->t = msg_getFloat(m,0); #endif } } else if (msg_compareSymbol(m,0,"stop")) { // Stop line at current position #if HV_SIMD_AVX // note o->n[1] is a 64-bit integer; two packed 32-bit ints. We only want to know if the high int is positive, // which can be done simply by testing the long int for positiveness. float x = (o->n[1] > 0) ? (o->x[7] + (o->m[7]/8.0f)) : o->t[7]; o->n = _mm_setzero_si128(); o->x = _mm256_set1_ps(x); o->m = _mm256_setzero_ps(); o->t = _mm256_set1_ps(x); #elif HV_SIMD_SSE const hv_int32_t *const on = (hv_int32_t *) &o->n; const float *const ox = (float *) &o->x; const float *const om = (float *) &o->m; const float *const ot = (float *) &o->t; float x = (on[3] > 0) ? (ox[3] + (om[3]/4.0f)) : ot[3]; o->n = _mm_setzero_si128(); o->x = _mm_set1_ps(x); o->m = _mm_setzero_ps(); o->t = _mm_set1_ps(x); #elif HV_SIMD_NEON float x = (o->n[3] > 0) ? (o->x[3] + (o->m[3]/4.0f)) : o->t[3]; o->n = vdupq_n_s32(0); o->x = vdupq_n_f32(x); o->m = vdupq_n_f32(0.0f); o->t = vdupq_n_f32(x); #else // HV_SIMD_NONE o->n = 0; o->x += o->m; o->m = 0.0f; o->t = o->x; #endif } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalLine.h0000644000000000000000000000551314435670357017407 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SIGNAL_LINE_H_ #define _SIGNAL_LINE_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct SignalLine { #if HV_SIMD_AVX __m128i n; // remaining samples to target #else hv_bufferi_t n; // remaining samples to target #endif hv_bufferf_t x; // current output hv_bufferf_t m; // increment hv_bufferf_t t; // target value } SignalLine; hv_size_t sLine_init(SignalLine *o); static inline void __hv_line_f(SignalLine *o, hv_bOutf_t bOut) { #if HV_SIMD_AVX __m128i n = o->n; __m128i masklo = _mm_cmplt_epi32(n, _mm_setzero_si128()); // n < 0 n = _mm_sub_epi32(n, _mm_set1_epi32(4)); // subtract HV_N_SIMD from remaining samples __m128i maskhi = _mm_cmplt_epi32(n, _mm_setzero_si128()); o->n = _mm_sub_epi32(n, _mm_set1_epi32(4)); __m256 mask = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_castsi128_ps(masklo)), _mm_castsi128_ps(maskhi), 1); __m256 x = o->x; *bOut = _mm256_or_ps(_mm256_and_ps(mask, o->t), _mm256_andnot_ps(mask, x)); // add slope from sloped samples o->x = _mm256_add_ps(x, o->m); #elif HV_SIMD_SSE __m128i n = o->n; __m128 mask = _mm_castsi128_ps(_mm_cmplt_epi32(n, _mm_setzero_si128())); // n < 0 __m128 x = o->x; *bOut = _mm_or_ps(_mm_and_ps(mask, o->t), _mm_andnot_ps(mask, x)); // subtract HV_N_SIMD from remaining samples o->n = _mm_sub_epi32(n, _mm_set1_epi32(HV_N_SIMD)); // add slope from sloped samples o->x = _mm_add_ps(x, o->m); #elif HV_SIMD_NEON int32x4_t n = o->n; int32x4_t mask = vreinterpretq_s32_u32(vcltq_s32(n, vdupq_n_s32(0))); float32x4_t x = o->x; *bOut = vreinterpretq_f32_s32(vorrq_s32( vandq_s32(mask, vreinterpretq_s32_f32(o->t)), vbicq_s32(vreinterpretq_s32_f32(x), mask))); o->n = vsubq_s32(n, vdupq_n_s32(HV_N_SIMD)); o->x = vaddq_f32(x, o->m); #else // HV_SIMD_NONE *bOut = (o->n < 0) ? o->t : o->x; o->n -= HV_N_SIMD; o->x += o->m; #endif } void sLine_onMessage(HeavyContextInterface *_c, SignalLine *o, int letIndex, const HvMessage *m, void *sendMessage); #ifdef __cplusplus } // extern "C" #endif #endif // _SIGNAL_LINE_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalLorenz.c0000644000000000000000000000224514435670357017763 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalLorenz.h" hv_size_t sLorenz_init(SignalLorenz *o, float x, float y, float z) { o->xm1 = x; o->ym1 = y; o->zm1 = z; return 0; } void sLorenz_onMessage(HeavyContextInterface *_c, SignalLorenz *o, int letIndex, const HvMessage *const m) { if (msg_hasFormat(m, "fff")) { o->xm1 = msg_getFloat(m,0); o->ym1 = msg_getFloat(m,1); o->zm1 = msg_getFloat(m,2); } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalLorenz.h0000644000000000000000000001156014435670357017770 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SIGNAL_LORENZ_H_ #define _SIGNAL_LORENZ_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct SignalLorenz { float xm1; float ym1; float zm1; } SignalLorenz; hv_size_t sLorenz_init(SignalLorenz *o, float x, float y, float z); // https://en.wikipedia.org/wiki/Lorenz_system#Overview // x = x'+hstep*s*(y'-x') // y = y'+hstep*(-x'*z'+r*x'-y') // z = z'+hstep*(x'*y'-b*z') static inline void __hv_lorenz_scalar_f( float xm1, float ym1, float zm1, float bInStep, float bInS, float bInR, float bInB, float *bOutX, float *bOutY, float *bOutZ) { *bOutX = hv_max_f(-100.0f, hv_min_f(xm1 + bInStep * bInS * (ym1 - xm1), 100.0f)); *bOutY = hv_max_f(-100.0f, hv_min_f(ym1 + bInStep * (-xm1 * zm1 + (bInR * xm1) - ym1), 100.0f)); *bOutZ = hv_max_f(-100.0f, hv_min_f(zm1 + bInStep * (xm1 * ym1 - bInB * zm1), 100.0f)); } static inline void __hv_lorenz_f(SignalLorenz *o, hv_bInf_t bInStep, hv_bInf_t bInS, hv_bInf_t bInR, hv_bInf_t bInB, hv_bOutf_t bOutX, hv_bOutf_t bOutY, hv_bOutf_t bOutZ) { #if HV_SIMD_AVX const float *const h = (float *) &bInStep; const float *const s = (float *) &bInS; const float *const r = (float *) &bInR; const float *const b = (float *) &bInB; float *const x = (float *) hv_alloca(3 * 8 * sizeof(float)); float *const y = x + 8; float *const z = x + 16; __hv_lorenz_scalar_f(o->xm1, o->ym1, o->zm1, h[0], s[0], r[0], b[0], x, y, z); __hv_lorenz_scalar_f(x[0], y[0], z[0], h[1], s[1], r[1], b[1], x+1, y+1, z+1); __hv_lorenz_scalar_f(x[1], y[1], z[1], h[2], s[2], r[2], b[2], x+2, y+2, z+2); __hv_lorenz_scalar_f(x[2], y[2], z[2], h[3], s[3], r[3], b[3], x+3, y+3, z+3); __hv_lorenz_scalar_f(x[3], y[3], z[3], h[4], s[4], r[4], b[4], x+4, y+4, z+4); __hv_lorenz_scalar_f(x[4], y[4], z[4], h[5], s[5], r[5], b[5], x+5, y+5, z+5); __hv_lorenz_scalar_f(x[5], y[5], z[5], h[6], s[6], r[6], b[6], x+6, y+6, z+6); __hv_lorenz_scalar_f(x[6], y[6], z[6], h[7], s[7], r[7], b[7], x+7, y+7, z+7); o->xm1 = x[7]; o->ym1 = y[7]; o->zm1 = z[7]; __hv_load_f(x, bOutX); __hv_load_f(y, bOutY); __hv_load_f(z, bOutZ); #elif HV_SIMD_SSE const float *const h = (float *) &bInStep; const float *const s = (float *) &bInS; const float *const r = (float *) &bInR; const float *const b = (float *) &bInB; float *const x = (float *) hv_alloca(3 * 4 * sizeof(float)); float *const y = x + 4; float *const z = x + 8; __hv_lorenz_scalar_f(o->xm1, o->ym1, o->zm1, h[0], s[0], r[0], b[0], x, y, z); __hv_lorenz_scalar_f(x[0], y[0], z[0], h[1], s[1], r[1], b[1], x+1, y+1, z+1); __hv_lorenz_scalar_f(x[1], y[1], z[1], h[2], s[2], r[2], b[2], x+2, y+2, z+2); __hv_lorenz_scalar_f(x[2], y[2], z[2], h[3], s[3], r[3], b[3], x+3, y+3, z+3); o->xm1 = x[3]; o->ym1 = y[3]; o->zm1 = z[3]; __hv_load_f(x, bOutX); __hv_load_f(y, bOutY); __hv_load_f(z, bOutZ); #elif HV_SIMD_NEON float *const x = (float *) hv_alloca(3 * 4 * sizeof(float)); float *const y = x + 4; float *const z = x + 8; __hv_lorenz_scalar_f(o->xm1, o->ym1, o->zm1, vgetq_lane_f32(bInStep,0), vgetq_lane_f32(bInS,0), vgetq_lane_f32(bInR,0), vgetq_lane_f32(bInB,0), x, y, z); __hv_lorenz_scalar_f(x[0], y[0], z[0], vgetq_lane_f32(bInStep,1), vgetq_lane_f32(bInS,1), vgetq_lane_f32(bInR,1), vgetq_lane_f32(bInB,1), x+1, y+1, z+1); __hv_lorenz_scalar_f(x[1], y[1], z[1], vgetq_lane_f32(bInStep,2), vgetq_lane_f32(bInS,2), vgetq_lane_f32(bInR,2), vgetq_lane_f32(bInB,2), x+2, y+2, z+2); __hv_lorenz_scalar_f(x[2], y[2], z[2], vgetq_lane_f32(bInStep,3), vgetq_lane_f32(bInS,3), vgetq_lane_f32(bInR,3), vgetq_lane_f32(bInB,3), x+3, y+3, z+3); o->xm1 = x[3]; o->ym1 = y[3]; o->zm1 = z[3]; __hv_load_f(x, bOutX); __hv_load_f(y, bOutY); __hv_load_f(z, bOutZ); #else // HV_SIMD_NONE __hv_lorenz_scalar_f(o->xm1, o->ym1, o->zm1, bInStep, bInS, bInR, bInB, bOutX, bOutY, bOutZ); o->xm1 = *bOutX; o->ym1 = *bOutY; o->zm1 = *bOutZ; #endif } void sLorenz_onMessage(HeavyContextInterface *_c, SignalLorenz *o, int letIndex, const HvMessage *m); #ifdef __cplusplus } // extern "C" #endif #endif // _SIGNAL_LORENZ_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.764207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalPhasor.c0000644000000000000000000001146514435670357017752 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalPhasor.h" #define HV_PHASOR_2_32 4294967296.0 #if HV_SIMD_AVX static void sPhasor_updatePhase(SignalPhasor *o, float p) { o->phase = _mm256_set1_ps(p+1.0f); // o->phase is in range [1,2] #elif HV_SIMD_SSE static void sPhasor_updatePhase(SignalPhasor *o, hv_uint32_t p) { o->phase = _mm_set1_epi32(p); #elif HV_SIMD_NEON static void sPhasor_updatePhase(SignalPhasor *o, hv_uint32_t p) { o->phase = vdupq_n_u32(p); #else // HV_SIMD_NONE static void sPhasor_updatePhase(SignalPhasor *o, hv_uint32_t p) { o->phase = p; #endif } // input phase is in the range of [0,1]. It is independent of o->phase. #if HV_SIMD_AVX static void sPhasor_k_updatePhase(SignalPhasor *o, float p) { o->phase = _mm256_set_ps( p+1.0f+7.0f*o->step.f2sc, p+1.0f+6.0f*o->step.f2sc, p+1.0f+5.0f*o->step.f2sc, p+1.0f+4.0f*o->step.f2sc, p+1.0f+3.0f*o->step.f2sc, p+1.0f+2.0f*o->step.f2sc, p+1.0f+o->step.f2sc, p+1.0f); // ensure that o->phase is still in range [1,2] o->phase = _mm256_or_ps(_mm256_andnot_ps( _mm256_set1_ps(-INFINITY), o->phase), _mm256_set1_ps(1.0f)); #elif HV_SIMD_SSE static void sPhasor_k_updatePhase(SignalPhasor *o, hv_uint32_t p) { o->phase = _mm_set_epi32(3*o->step.s+p, 2*o->step.s+p, o->step.s+p, p); #elif HV_SIMD_NEON static void sPhasor_k_updatePhase(SignalPhasor *o, hv_uint32_t p) { o->phase = (uint32x4_t) {p, o->step.s+p, 2*o->step.s+p, 3*o->step.s+p}; #else // HV_SIMD_NONE static void sPhasor_k_updatePhase(SignalPhasor *o, hv_uint32_t p) { o->phase = p; #endif } static void sPhasor_k_updateFrequency(SignalPhasor *o, float f, double r) { #if HV_SIMD_AVX o->step.f2sc = (float) (f/r); o->inc = _mm256_set1_ps((float) (8.0f*f/r)); sPhasor_k_updatePhase(o, o->phase[0]); #elif HV_SIMD_SSE o->step.s = (hv_int32_t) (f*(HV_PHASOR_2_32/r)); o->inc = _mm_set1_epi32(4*o->step.s); const hv_uint32_t *const p = (hv_uint32_t *) &o->phase; sPhasor_k_updatePhase(o, p[0]); #elif HV_SIMD_NEON o->step.s = (hv_int32_t) (f*(HV_PHASOR_2_32/r)); o->inc = vdupq_n_s32(4*o->step.s); sPhasor_k_updatePhase(o, vgetq_lane_u32(o->phase, 0)); #else // HV_SIMD_NONE o->step.s = (hv_int32_t) (f*(HV_PHASOR_2_32/r)); o->inc = o->step.s; // no need to update phase #endif } hv_size_t sPhasor_init(SignalPhasor *o, double samplerate) { #if HV_SIMD_AVX o->phase = _mm256_set1_ps(1.0f); o->inc = _mm256_setzero_ps(); o->step.f2sc = (float) (1.0/samplerate); #elif HV_SIMD_SSE o->phase = _mm_setzero_si128(); o->inc = _mm_setzero_si128(); o->step.f2sc = (float) (HV_PHASOR_2_32/samplerate); #elif HV_SIMD_NEON o->phase = vdupq_n_u32(0); o->inc = vdupq_n_s32(0); o->step.f2sc = (float) (HV_PHASOR_2_32/samplerate); #else // HV_SIMD_NONE o->phase = 0; o->inc = 0; o->step.f2sc = (float) (HV_PHASOR_2_32/samplerate); #endif return 0; } void sPhasor_onMessage(HeavyContextInterface *_c, SignalPhasor *o, int letIn, const HvMessage *m) { if (letIn == 1) { if (msg_isFloat(m,0)) { float p = msg_getFloat(m,0); while (p < 0.0f) p += 1.0f; // wrap phase to [0,1] while (p > 1.0f) p -= 1.0f; #if HV_SIMD_AVX sPhasor_updatePhase(o, p); #else // HV_SIMD_SSE || HV_SIMD_NEON || HV_SIMD_NONE sPhasor_updatePhase(o, (hv_uint32_t) (p * HV_PHASOR_2_32)); #endif } } } hv_size_t sPhasor_k_init(SignalPhasor *o, float frequency, double samplerate) { __hv_zero_i((hv_bOuti_t) &o->phase); sPhasor_k_updateFrequency(o, frequency, samplerate); return 0; } void sPhasor_k_onMessage(HeavyContextInterface *_c, SignalPhasor *o, int letIn, const HvMessage *m) { if (msg_isFloat(m,0)) { switch (letIn) { case 0: sPhasor_k_updateFrequency(o, msg_getFloat(m,0), hv_getSampleRate(_c)); break; case 1: { float p = msg_getFloat(m,0); while (p < 0.0f) p += 1.0f; // wrap phase to [0,1] while (p > 1.0f) p -= 1.0f; #if HV_SIMD_AVX sPhasor_k_updatePhase(o, p); #else // HV_SIMD_SSE || HV_SIMD_NEON || HV_SIMD_NONE sPhasor_k_updatePhase(o, (hv_uint32_t) (p * HV_PHASOR_2_32)); #endif break; } default: break; } } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalPhasor.h0000644000000000000000000001305714435670357017756 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_SIGNAL_PHASOR_H_ #define _HEAVY_SIGNAL_PHASOR_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct SignalPhasor { #if HV_SIMD_AVX __m256 phase; // current phase __m256 inc; // phase increment #elif HV_SIMD_SSE __m128i phase; __m128i inc; #elif HV_SIMD_NEON uint32x4_t phase; int32x4_t inc; #else // HV_SIMD_NONE hv_uint32_t phase; hv_int32_t inc; #endif union { float f2sc; // float to step conversion (used for __phasor~f) hv_int32_t s; // step value (used for __phasor_k~f) } step; } SignalPhasor; hv_size_t sPhasor_init(SignalPhasor *o, double samplerate); hv_size_t sPhasor_k_init(SignalPhasor *o, float frequency, double samplerate); void sPhasor_k_onMessage(HeavyContextInterface *_c, SignalPhasor *o, int letIn, const HvMessage *m); void sPhasor_onMessage(HeavyContextInterface *_c, SignalPhasor *o, int letIn, const HvMessage *m); static inline void __hv_phasor_f(SignalPhasor *o, hv_bInf_t bIn, hv_bOutf_t bOut) { #if HV_SIMD_AVX __m256 p = _mm256_mul_ps(bIn, _mm256_set1_ps(o->step.f2sc)); // a b c d e f g h __m256 z = _mm256_setzero_ps(); // http://stackoverflow.com/questions/11906814/how-to-rotate-an-sse-avx-vector __m256 a = _mm256_permute_ps(p, _MM_SHUFFLE(2,1,0,3)); // d a b c h e f g __m256 b = _mm256_permute2f128_ps(a, a, 0x01); // h e f g d a b c __m256 c = _mm256_blend_ps(a, b, 0x10); // d a b c d e f g __m256 d = _mm256_blend_ps(c, z, 0x01); // 0 a b c d e f g __m256 e = _mm256_add_ps(p, d); // a (a+b) (b+c) (c+d) (d+e) (e+f) (f+g) (g+h) __m256 f = _mm256_permute_ps(e, _MM_SHUFFLE(1,0,3,2)); // (b+c) (c+d) a (a+b) (f+g) (g+h) (d+e) (e+f) __m256 g = _mm256_permute2f128_ps(f, f, 0x01); // (f+g) (g+h) (d+e) (e+f) (b+c) (c+d) a (a+b) __m256 h = _mm256_blend_ps(f, g, 0x33); // (b+c) (c+d) a (a+b) (b+c) (c+d) (d+e) (e+f) __m256 i = _mm256_blend_ps(h, z, 0x03); // 0 0 a (a+b) (b+c) (c+d) (d+e) (e+f) __m256 j = _mm256_add_ps(e, i); // a (a+b) (a+b+c) (a+b+c+d) (b+c+d+e) (c+d+e+f) (d+e+f+g) (e+f+g+h) __m256 k = _mm256_permute2f128_ps(j, z, 0x02); // 0 0 0 0 a (a+b) (a+b+c) (a+b+c+d) (b+c+d+e) __m256 m = _mm256_add_ps(j, k); // a (a+b) (a+b+c) (a+b+c+d) (a+b+c+d+e) (a+b+c+d+e+f) (a+b+c+d+e+f+g) (a+b+c+d+e+f+g+h) __m256 n = _mm256_or_ps(_mm256_andnot_ps( _mm256_set1_ps(-INFINITY), _mm256_add_ps(o->phase, m)), _mm256_set1_ps(1.0f)); *bOut = _mm256_sub_ps(n, _mm256_set1_ps(1.0f)); __m256 x = _mm256_permute_ps(n, _MM_SHUFFLE(3,3,3,3)); o->phase = _mm256_permute2f128_ps(x, x, 0x11); #elif HV_SIMD_SSE __m128i p = _mm_cvtps_epi32(_mm_mul_ps(bIn, _mm_set1_ps(o->step.f2sc))); // convert frequency to step p = _mm_add_epi32(p, _mm_slli_si128(p, 4)); // add incremental steps to phase (prefix sum) p = _mm_add_epi32(p, _mm_slli_si128(p, 8)); // http://stackoverflow.com/questions/10587598/simd-prefix-sum-on-intel-cpu?rq=1 p = _mm_add_epi32(o->phase, p); *bOut = _mm_sub_ps(_mm_castsi128_ps( _mm_or_si128(_mm_srli_epi32(p, 9), _mm_set_epi32(0x3F800000, 0x3F800000, 0x3F800000, 0x3F800000))), _mm_set1_ps(1.0f)); o->phase = _mm_shuffle_epi32(p, _MM_SHUFFLE(3,3,3,3)); #elif HV_SIMD_NEON int32x4_t p = vcvtq_s32_f32(vmulq_n_f32(bIn, o->step.f2sc)); p = vaddq_s32(p, vextq_s32(vdupq_n_s32(0), p, 3)); // http://stackoverflow.com/questions/11259596/arm-neon-intrinsics-rotation p = vaddq_s32(p, vextq_s32(vdupq_n_s32(0), p, 2)); uint32x4_t pp = vaddq_u32(o->phase, vreinterpretq_u32_s32(p)); *bOut = vsubq_f32(vreinterpretq_f32_u32(vorrq_u32(vshrq_n_u32(pp, 9), vdupq_n_u32(0x3F800000))), vdupq_n_f32(1.0f)); o->phase = vdupq_n_u32(pp[3]); #else // HV_SIMD_NONE const hv_uint32_t p = (o->phase >> 9) | 0x3F800000; *bOut = *((float *) (&p)) - 1.0f; o->phase += ((int) (bIn * o->step.f2sc)); #endif } static inline void __hv_phasor_k_f(SignalPhasor *o, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_sub_ps(o->phase, _mm256_set1_ps(1.0f)); o->phase = _mm256_or_ps(_mm256_andnot_ps( _mm256_set1_ps(-INFINITY), _mm256_add_ps(o->phase, o->inc)), _mm256_set1_ps(1.0f)); #elif HV_SIMD_SSE *bOut = _mm_sub_ps(_mm_castsi128_ps( _mm_or_si128(_mm_srli_epi32(o->phase, 9), _mm_set_epi32(0x3F800000, 0x3F800000, 0x3F800000, 0x3F800000))), _mm_set1_ps(1.0f)); o->phase = _mm_add_epi32(o->phase, o->inc); #elif HV_SIMD_NEON *bOut = vsubq_f32(vreinterpretq_f32_u32( vorrq_u32(vshrq_n_u32(o->phase, 9), vdupq_n_u32(0x3F800000))), vdupq_n_f32(1.0f)); o->phase = vaddq_u32(o->phase, vreinterpretq_u32_s32(o->inc)); #else // HV_SIMD_NONE const hv_uint32_t p = (o->phase >> 9) | 0x3F800000; *bOut = *((float *) (&p)) - 1.0f; o->phase += o->inc; #endif } #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_SIGNAL_PHASOR_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalRPole.c0000644000000000000000000000327414435670357017536 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalRPole.h" hv_size_t sRPole_init(SignalRPole *o) { #if HV_SIMD_AVX sDel1_init(&o->sDel1_fxiLN); sDel1_init(&o->sDel1_kjkpV); sDel1_init(&o->sDel1_dkIWc); sDel1_init(&o->sDel1_bVeoW); sDel1_init(&o->sDel1_PulZn); sDel1_init(&o->sDel1_yTFig); sDel1_init(&o->sDel1_Is9Qf); sDel1_init(&o->sDel1_LIyNt); sDel1_init(&o->sDel1_VqpU3); sDel1_init(&o->sDel1_ZVYeg); sDel1_init(&o->sDel1_IVAZh); sDel1_init(&o->sDel1_F8WrY); sDel1_init(&o->sDel1_rkFMy); sDel1_init(&o->sDel1_BeqSK); __hv_zero_f(&o->ym); #elif HV_SIMD_SSE || HV_SIMD_NEON sDel1_init(&o->sDel1_i8Twk); sDel1_init(&o->sDel1_KYibU); sDel1_init(&o->sDel1_spa5V); sDel1_init(&o->sDel1_3HXdb); sDel1_init(&o->sDel1_Aj1oK); sDel1_init(&o->sDel1_jNX1g); __hv_zero_f(&o->ym); #else o->ym = 0.0f; #endif return 0; } void sRPole_onMessage(HeavyContextInterface *_c, SignalRPole *o, int letIn, const HvMessage *m) { // TODO } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalRPole.h0000644000000000000000000000723714435670357017546 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SIGNAL_RPOLE_H_ #define _SIGNAL_RPOLE_H_ #include "HvHeavyInternal.h" #include "HvSignalDel1.h" #ifdef __cplusplus extern "C" { #endif // implements y[n] = x[n] - a*y[n-1] // H(z) = 1/(1+a*z^-1) typedef struct SignalRPole { #if HV_SIMD_AVX SignalDel1 sDel1_fxiLN; SignalDel1 sDel1_kjkpV; SignalDel1 sDel1_dkIWc; SignalDel1 sDel1_bVeoW; SignalDel1 sDel1_PulZn; SignalDel1 sDel1_yTFig; SignalDel1 sDel1_Is9Qf; SignalDel1 sDel1_LIyNt; SignalDel1 sDel1_VqpU3; SignalDel1 sDel1_ZVYeg; SignalDel1 sDel1_IVAZh; SignalDel1 sDel1_F8WrY; SignalDel1 sDel1_rkFMy; SignalDel1 sDel1_BeqSK; hv_bufferf_t ym; #elif HV_SIMD_SSE || HV_SIMD_NEON SignalDel1 sDel1_i8Twk; SignalDel1 sDel1_KYibU; SignalDel1 sDel1_spa5V; SignalDel1 sDel1_3HXdb; SignalDel1 sDel1_Aj1oK; SignalDel1 sDel1_jNX1g; hv_bufferf_t ym; #else hv_bufferf_t ym; #endif } SignalRPole; hv_size_t sRPole_init(SignalRPole *o); void sRPole_onMessage(HeavyContextInterface *_c, SignalRPole *o, int letIn, const HvMessage *m); static inline void __hv_rpole_f(SignalRPole *o, hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_bufferf_t a, b, c, d, e, f, g, i, j, k, l, m, n; __hv_del1_f(&o->sDel1_fxiLN, bIn1, &a); __hv_mul_f(bIn1, a, &b); __hv_del1_f(&o->sDel1_kjkpV, a, &a); __hv_mul_f(b, a, &c); __hv_del1_f(&o->sDel1_dkIWc, a, &a); __hv_mul_f(c, a, &d); __hv_del1_f(&o->sDel1_bVeoW, a, &a); __hv_mul_f(d, a, &e); __hv_del1_f(&o->sDel1_PulZn, a, &a); __hv_mul_f(e, a, &f); __hv_del1_f(&o->sDel1_yTFig, a, &a); __hv_mul_f(f, a, &g); __hv_del1_f(&o->sDel1_Is9Qf, a, &a); __hv_mul_f(g, a, &a); __hv_del1_f(&o->sDel1_LIyNt, bIn0, &i); __hv_del1_f(&o->sDel1_VqpU3, i, &j); __hv_del1_f(&o->sDel1_ZVYeg, j, &k); __hv_del1_f(&o->sDel1_IVAZh, k, &l); __hv_del1_f(&o->sDel1_F8WrY, l, &m); __hv_del1_f(&o->sDel1_rkFMy, m, &n); __hv_mul_f(i, bIn1, &i); __hv_sub_f(bIn0, i, &i); __hv_fma_f(j, b, i, &i); __hv_mul_f(k, c, &c); __hv_sub_f(i, c, &c); __hv_fma_f(l, d, c, &c); __hv_mul_f(m, e, &e); __hv_sub_f(c, e, &e); __hv_fma_f(n, f, e, &e); __hv_del1_f(&o->sDel1_BeqSK, n, &n); __hv_mul_f(n, g, &g); __hv_sub_f(e, g, &g); __hv_fma_f(a, o->ym, g, &g); o->ym = g; *bOut = g; #elif HV_SIMD_SSE || HV_SIMD_NEON hv_bufferf_t a, b, c, e, f; __hv_del1_f(&o->sDel1_i8Twk, bIn1, &a); __hv_mul_f(bIn1, a, &b); __hv_del1_f(&o->sDel1_KYibU, a, &a); __hv_mul_f(b, a, &c); __hv_del1_f(&o->sDel1_spa5V, a, &a); __hv_mul_f(c, a, &a); __hv_del1_f(&o->sDel1_3HXdb, bIn0, &e); __hv_del1_f(&o->sDel1_Aj1oK, e, &f); __hv_mul_f(e, bIn1, &e); __hv_sub_f(bIn0, e, &e); __hv_fma_f(f, b, e, &e); __hv_del1_f(&o->sDel1_jNX1g, f, &f); __hv_mul_f(f, c, &c); __hv_sub_f(e, c, &c); __hv_fma_f(a, o->ym, c, &c); o->ym = c; *bOut = c; #else *bOut = bIn0 - bIn1 * o->ym; o->ym = *bOut; #endif } #ifdef __cplusplus } // extern "C" #endif #endif // _SIGNAL_RPOLE_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalSamphold.c0000644000000000000000000000300114435670357020250 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalSamphold.h" hv_size_t sSamphold_init(SignalSamphold *o) { #if HV_SIMD_AVX o->s = _mm256_setzero_ps(); #elif HV_SIMD_SSE o->s = _mm_setzero_ps(); #elif HV_SIMD_NEON o->s = vdupq_n_f32(0.0f); #else o->s = 0.0f; #endif return 0; } void sSamphold_onMessage(HeavyContextInterface *_c, SignalSamphold *o, int letIndex, const HvMessage *m, void *sendMessage) { switch (letIndex) { case 2: { if (msg_isFloat(m,0)) { #if HV_SIMD_AVX o->s = _mm256_set1_ps(msg_getFloat(m,0)); #elif HV_SIMD_SSE o->s = _mm_set1_ps(msg_getFloat(m,0)); #elif HV_SIMD_NEON o->s = vdupq_n_f32(msg_getFloat(m,0)); #else o->s = msg_getFloat(m,0); #endif } break; } default: break; } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalSamphold.h0000644000000000000000000002242414435670357020267 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SIGNAL_SAMPHOLD_H_ #define _SIGNAL_SAMPHOLD_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct SignalSamphold { hv_bufferf_t s; } SignalSamphold; hv_size_t sSamphold_init(SignalSamphold *o); static inline void __hv_samphold_f(SignalSamphold *o, hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) { #if HV_SIMD_AVX hv_assert(0); // __hv_samphold_f() not implemented #elif HV_SIMD_SSE switch (_mm_movemask_ps(bIn1)) { default: case 0x0: *bOut = o->s; break; case 0x1: { *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(0,0,0,0)); o->s = *bOut; break; } case 0x2: { const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(1,1,1,1)); *bOut = _mm_blend_ps(o->s, x, 0xE); o->s = x; break; } case 0x3: { const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(1,1,1,1)); *bOut = _mm_blend_ps(bIn0, x, 0xC); o->s = x; break; } case 0x4: { const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,2,2)); *bOut = _mm_blend_ps(o->s, x, 0xC); o->s = x; break; } case 0x5: { *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,0,0)); o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,2,2)); break; } case 0x6: { const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,1,0)); *bOut = _mm_blend_ps(o->s, x, 0xE); o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,2,2)); break; } case 0x7: { const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,2,2)); *bOut = _mm_blend_ps(bIn0, x, 0x8); o->s = x; break; } case 0x8: { const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3)); *bOut = _mm_blend_ps(o->s, x, 0x8); o->s = x; break; } case 0x9: { *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,0,0,0)); o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3)); break; } case 0xA: { const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,1,1,0)); *bOut = _mm_blend_ps(o->s, x, 0xE); o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3)); break; } case 0xB: { *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,1,1,0)); o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3)); break; } case 0xC: { *bOut = _mm_blend_ps(o->s, bIn0, 0xC); o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3)); break; } case 0xD: { *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,2,0,0)); o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3)); break; } case 0xE: { *bOut = _mm_blend_ps(o->s, bIn0, 0xE); o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3)); break; } case 0xF: { *bOut = bIn0; o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3)); break; } } #elif HV_SIMD_NEON uint32x4_t mmA = vandq_u32( vreinterpretq_u32_f32(bIn1), (uint32x4_t) {0x1, 0x2, 0x4, 0x8}); // [0 1 2 3] uint32x4_t mmB = vextq_u32(mmA, mmA, 2); // [2 3 0 1] uint32x4_t mmC = vorrq_u32(mmA, mmB); // [0+2 1+3 0+2 1+3] uint32x4_t mmD = vextq_u32(mmC, mmC, 3); // [1+3 0+2 1+3 0+2] uint32x4_t mmE = vorrq_u32(mmC, mmD); // [0+1+2+3 ...] uint32_t movemask = vgetq_lane_u32(mmE, 0); switch (movemask) { default: case 0x0: *bOut = o->s; break; case 0x1: { *bOut = vdupq_n_f32(vgetq_lane_f32(bIn0,0)); o->s = *bOut; break; } case 0x2: { const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,1)); *bOut = vextq_f32(o->s, x, 3); o->s = x; break; } case 0x3: { const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,1)); *bOut = vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0xFFFFFFFF, 0x0, 0x0, 0x0}), vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}))); o->s = x; break; } case 0x4: { const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,2)); *bOut = vextq_f32(o->s, x, 2); o->s = x; break; } case 0x5: { const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,0)); const float32x4_t y = vdupq_n_f32(vgetq_lane_f32(bIn0,2)); *bOut = vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0}), vandq_u32(vreinterpretq_u32_f32(y), (uint32x4_t) {0x0, 0x0, 0xFFFFFFFF, 0xFFFFFFFF}))); o->s = y; } case 0x6: { const float32x4_t y = vdupq_n_f32(vgetq_lane_f32(bIn0,3)); float32x4_t z = vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(o->s), (uint32x4_t) {0xFFFFFFFF, 0x0, 0x0, 0x0}), vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0x0, 0xFFFFFFFF, 0xFFFFFFFF, 0x0}))); *bOut = vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(z), (uint32x4_t) {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0}), vandq_u32(vreinterpretq_u32_f32(y), (uint32x4_t) {0x0, 0x0, 0x0, 0xFFFFFFFF}))); o->s = y; } case 0x7: { const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,2)); *bOut = vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0}), vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, 0x0, 0xFFFFFFFF, 0xFFFFFFFF}))); o->s = x; break; } case 0x8: { const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,3)); *bOut = vextq_f32(o->s, x, 1); o->s = x; break; } case 0x9: { const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,0)); *bOut = vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0}), vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0x0, 0x0, 0x0, 0xFFFFFFFF}))); o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3)); } case 0xA: { const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,1)); const float32x4_t y = vdupq_n_f32(vgetq_lane_f32(bIn0,3)); float32x4_t z = vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(o->s), (uint32x4_t) {0xFFFFFFFF, 0x0, 0x0, 0x0}), vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, 0xFFFFFFFF, 0xFFFFFFFF, 0x0}))); *bOut = vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(z), (uint32x4_t) {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0}), vandq_u32(vreinterpretq_u32_f32(y), (uint32x4_t) {0x0, 0x0, 0x0, 0xFFFFFFFF}))); o->s = y; } case 0xB: { const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,1)); *bOut = vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0xFFFFFFFF}), vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, 0x0, 0xFFFFFFFF, 0x0}))); o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3)); break; } case 0xC: { *bOut = vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(o->s), (uint32x4_t) {0xFFFFFFFF, 0xFFFFFFFF, 0x0, 0x0}), vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0x0, 0x0, 0xFFFFFFFF, 0xFFFFFFFF}))); o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3)); break; } case 0xD: { const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,0)); *bOut = vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0xFFFFFFFF, 0x0, 0xFFFFFFFF, 0xFFFFFFFF}), vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, 0xFFFFFFFF, 0x0, 0x0}))); o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3)); } case 0xE: { *bOut = vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(o->s), (uint32x4_t) {0xFFFFFFFF, 0x0, 0x0, 0x0}), vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0x0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}))); o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3)); break; } case 0xF: { *bOut = bIn0; o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3)); break; } } #else // HV_SIMD_NONE if (bIn1 != 0.0f) o->s = bIn0; *bOut = o->s; #endif } void sSamphold_onMessage(HeavyContextInterface *_c, SignalSamphold *o, int letIndex, const HvMessage *m, void *sendMessage); #ifdef __cplusplus } // extern "C" #endif #endif // _SIGNAL_SAMPHOLD_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalSample.c0000644000000000000000000000333114435670357017730 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalSample.h" #define __HV_SAMPLE_NULL -1 hv_size_t sSample_init(SignalSample *o) { o->i = __HV_SAMPLE_NULL; return 0; } void sSample_onMessage(HeavyContextInterface *_c, SignalSample *o, int letIndex, const HvMessage *m) { o->i = msg_getTimestamp(m); } void __hv_sample_f(HeavyContextInterface *_c, SignalSample *o, hv_bInf_t bIn, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { if (o->i != __HV_SAMPLE_NULL) { #if HV_SIMD_AVX || HV_SIMD_SSE const float *const b = (float *) &bIn; float out = b[o->i & HV_N_SIMD_MASK]; #elif HV_SIMD_NEON float out = bIn[o->i & HV_N_SIMD_MASK]; #else // HV_SIMD_NONE float out = bIn; #endif HvMessage *n = HV_MESSAGE_ON_STACK(1); hv_uint32_t ts = (o->i + HV_N_SIMD) & ~HV_N_SIMD_MASK; // start of next block msg_initWithFloat(n, ts, out); hv_scheduleMessageForObject(_c, n, sendMessage, 0); o->i = __HV_SAMPLE_NULL; // reset the index } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalSample.h0000644000000000000000000000254314435670357017741 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SIGNAL_SAMPLE_H_ #define _SIGNAL_SAMPLE_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct SignalSample { hv_uint32_t i; // timestamp at which to get sample } SignalSample; hv_size_t sSample_init(SignalSample *o); void __hv_sample_f(HeavyContextInterface *_c, SignalSample *o, hv_bInf_t bIn, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); void sSample_onMessage(HeavyContextInterface *_c, SignalSample *o, int letIndex, const HvMessage *m); #ifdef __cplusplus } // extern "C" #endif #endif // _SIGNAL_SAMPLE_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5971823 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalTabread.c0000644000000000000000000000617014735300037020041 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalTabread.h" hv_size_t sTabread_init(SignalTabread *o, HvTable *table, bool forceAlignedLoads) { o->table = table; o->head = 0; o->end = hTable_getSize(o->table); o->forceAlignedLoads = forceAlignedLoads; o->playing = false; return 0; } void sTabread_onMessage(HeavyContextInterface *_c, SignalTabread *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { switch (letIn) { case 0: { if (o->table != NULL) { o->end = hTable_getSize(o->table); switch (msg_getType(m,0)) { case HV_MSG_BANG: { o->head = 0; o->playing = true; break; } case HV_MSG_FLOAT: { hv_uint32_t h = (hv_uint32_t) hv_abs_f(msg_getFloat(m,0)); if (msg_getFloat(m,0) < 0.0f) { // if input is negative, wrap around the end of the table h = hTable_getSize(o->table) - h; } o->head = o->forceAlignedLoads ? (h & ~HV_N_SIMD_MASK) : h; o->playing = true; // output new head HvMessage *n = HV_MESSAGE_ON_STACK(1); msg_initWithFloat(n, msg_getTimestamp(m), (float) o->head); sendMessage(_c, 1, n); break; } case HV_MSG_SYMBOL: { if (msg_compareSymbol(m, 0, "stop")) { o->head = 0; o->playing = false; } break; } default: break; } } break; } case 1: { if (msg_isHashLike(m,0)) { o->table = hv_table_get(_c, msg_getHash(m,0)); o->head = 0; o->end = hTable_getSize(o->table); } break; } case 2: { if (o->table != NULL) { switch (msg_getType(m,0)) { case HV_MSG_FLOAT: { hv_uint32_t e = (hv_uint32_t) hv_abs_f(msg_getFloat(m,0)); o->end = o->head + e; break; } default: break; } } break; } default: break; } } #if HV_APPLE #pragma mark - Tabhead #endif void sTabhead_onMessage(HeavyContextInterface *_c, SignalTabhead *o, const HvMessage *m) { if (msg_isHashLike(m,0)) { o->table = hv_table_get(_c, msg_getHash(m,0)); } } hv_size_t sTabhead_init(SignalTabhead *o, HvTable *table) { o->table = table; return 0; } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5971823 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalTabread.h0000644000000000000000000001510114735300037020040 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_SIGNAL_TABREAD_H_ #define _HEAVY_SIGNAL_TABREAD_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif typedef struct SignalTabread { HvTable *table; // the table to read hv_uint32_t head; hv_uint32_t end; bool forceAlignedLoads; // false by default, true if using __hv_tabread_f bool playing; // false by default, only __hv_tabread_stoppable_f may respond to it } SignalTabread; // random access to a table hv_size_t sTabread_init(SignalTabread *o, HvTable *table, bool forceAlignedLoads); #if HV_APPLE #pragma mark - Tabread - Random Access #endif static inline void __hv_tabread_if(SignalTabread *o, hv_bIni_t bIn, hv_bOutf_t bOut) { const float *const b = hTable_getBuffer(o->table); #if HV_SIMD_AVX const hv_int32_t *const i = (hv_int32_t *) &bIn; hv_assert(i[0] >= 0 && (hv_uint32_t) i[0] < hTable_getAllocated(o->table)); hv_assert(i[1] >= 0 && (hv_uint32_t) i[1] < hTable_getAllocated(o->table)); hv_assert(i[2] >= 0 && (hv_uint32_t) i[2] < hTable_getAllocated(o->table)); hv_assert(i[3] >= 0 && (hv_uint32_t) i[3] < hTable_getAllocated(o->table)); hv_assert(i[4] >= 0 && (hv_uint32_t) i[4] < hTable_getAllocated(o->table)); hv_assert(i[5] >= 0 && (hv_uint32_t) i[5] < hTable_getAllocated(o->table)); hv_assert(i[6] >= 0 && (hv_uint32_t) i[6] < hTable_getAllocated(o->table)); hv_assert(i[7] >= 0 && (hv_uint32_t) i[7] < hTable_getAllocated(o->table)); *bOut = _mm256_set_ps(b[i[7]], b[i[6]], b[i[5]], b[i[4]], b[i[3]], b[i[2]], b[i[1]], b[i[0]]); #elif HV_SIMD_SSE const hv_int32_t *const i = (hv_int32_t *) &bIn; hv_assert(i[0] >= 0 && (hv_uint32_t) i[0] < hTable_getAllocated(o->table)); hv_assert(i[1] >= 0 && (hv_uint32_t) i[1] < hTable_getAllocated(o->table)); hv_assert(i[2] >= 0 && (hv_uint32_t) i[2] < hTable_getAllocated(o->table)); hv_assert(i[3] >= 0 && (hv_uint32_t) i[3] < hTable_getAllocated(o->table)); *bOut = _mm_set_ps(b[i[3]], b[i[2]], b[i[1]], b[i[0]]); #elif HV_SIMD_NEON hv_assert((bIn[0] >= 0) && (hv_uint32_t) bIn[0] < hTable_getAllocated(o->table)); hv_assert((bIn[1] >= 0) && (hv_uint32_t) bIn[1] < hTable_getAllocated(o->table)); hv_assert((bIn[2] >= 0) && (hv_uint32_t) bIn[2] < hTable_getAllocated(o->table)); hv_assert((bIn[3] >= 0) && (hv_uint32_t) bIn[3] < hTable_getAllocated(o->table)); *bOut = (float32x4_t) {b[bIn[0]], b[bIn[1]], b[bIn[2]], b[bIn[3]]}; #else // HV_SIMD_NONE hv_assert(bIn >= 0 && ((hv_uint32_t) bIn < hTable_getAllocated(o->table))); *bOut = b[bIn]; #endif } #if HV_APPLE #pragma mark - Tabread - Linear Access #endif // this tabread never stops reading. It is mainly intended for linear reads that loop around a table. static inline void __hv_tabread_f(SignalTabread *o, hv_bOutf_t bOut) { hv_assert((o->head + HV_N_SIMD) <= hTable_getAllocated(o->table)); // assert that we always read within the table bounds hv_uint32_t head = o->head; #if HV_SIMD_AVX *bOut = _mm256_load_ps(hTable_getBuffer(o->table) + head); #elif HV_SIMD_SSE *bOut = _mm_load_ps(hTable_getBuffer(o->table) + head); #elif HV_SIMD_NEON *bOut = vld1q_f32(hTable_getBuffer(o->table) + head); #else // HV_SIMD_NONE *bOut = *(hTable_getBuffer(o->table) + head); #endif o->head = head + HV_N_SIMD; } // unaligned linear tabread, as above static inline void __hv_tabreadu_f(SignalTabread *o, hv_bOutf_t bOut) { hv_assert((o->head + HV_N_SIMD) <= hTable_getAllocated(o->table)); // assert that we always read within the table bounds hv_uint32_t head = o->head; #if HV_SIMD_AVX *bOut = _mm256_loadu_ps(hTable_getBuffer(o->table) + head); #elif HV_SIMD_SSE *bOut = _mm_loadu_ps(hTable_getBuffer(o->table) + head); #elif HV_SIMD_NEON *bOut = vld1q_f32(hTable_getBuffer(o->table) + head); #else // HV_SIMD_NONE *bOut = *(hTable_getBuffer(o->table) + head); #endif o->head = head + HV_N_SIMD; } // this tabread can be instructed to stop. It is mainly intended for linear reads that only process a portion of a buffer. static inline void __hv_tabread_stoppable_f(HeavyContextInterface *_c, SignalTabread *o, hv_bOutf_t bOut, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { hv_uint32_t head = o->head; if (head >= hTable_getAllocated(o->table)) { // stop when we reach the table bounds o->playing = false; } if (!o->playing) { __hv_zero_f(bOut); // output silence when not playing } else { if (o->end > o->head) { // only play when end is further than play head #if HV_SIMD_AVX *bOut = _mm256_loadu_ps(hTable_getBuffer(o->table) + head); #elif HV_SIMD_SSE *bOut = _mm_load_ps(hTable_getBuffer(o->table) + head); #elif HV_SIMD_NEON *bOut = vld1q_f32(hTable_getBuffer(o->table) + head); #else // HV_SIMD_NONE *bOut = *(hTable_getBuffer(o->table) + head); #endif o->head = head + HV_N_SIMD; } else { o->playing = false; __hv_zero_f(bOut); // output silence when not playing HvMessage *n = HV_MESSAGE_ON_STACK(1); msg_initWithBang(n, 0); sendMessage(_c, 2, n); } } } void sTabread_onMessage(HeavyContextInterface *_c, SignalTabread *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); #if HV_APPLE #pragma mark - Tabhead #endif typedef struct SignalTabhead { HvTable *table; } SignalTabhead; hv_size_t sTabhead_init(SignalTabhead *o, HvTable *table); static inline void __hv_tabhead_f(SignalTabhead *o, hv_bOutf_t bOut) { #if HV_SIMD_AVX *bOut = _mm256_set1_ps((float) hTable_getHead(o->table)); #elif HV_SIMD_SSE *bOut = _mm_set1_ps((float) hTable_getHead(o->table)); #elif HV_SIMD_NEON *bOut = vdupq_n_f32((float32_t) hTable_getHead(o->table)); #else // HV_SIMD_NONE *bOut = (float) hTable_getHead(o->table); #endif } void sTabhead_onMessage(HeavyContextInterface *_c, SignalTabhead *o, const HvMessage *m); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_SIGNAL_TABREAD_H_ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5971823 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalTabwrite.c0000644000000000000000000000365314735300037020263 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalTabwrite.h" hv_size_t sTabwrite_init(SignalTabwrite *o, HvTable *table) { o->table = table; o->head = 0; return 0; } void sTabwrite_onMessage(HeavyContextInterface *_c, SignalTabwrite *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { switch (letIn) { // inlet 0 is the signal inlet case 1: { switch (msg_getType(m,0)) { case HV_MSG_BANG: o->head = 0; break; case HV_MSG_FLOAT: { o->head = (msg_getFloat(m,0) >= 0.0f) ? (hv_uint32_t) msg_getFloat(m,0) : HV_TABWRITE_STOPPED; break; } case HV_MSG_SYMBOL: { if (msg_compareSymbol(m, 0, "stop")) { o->head = HV_TABWRITE_STOPPED; } else if (msg_compareSymbol(m, 0, "clear")) { hv_size_t numBytes = o->table->allocated * sizeof(float); hv_memclear(o->table->buffer, numBytes); } break; } default: break; } break; } case 2: { if (msg_isHashLike(m,0)) { o->table = hv_table_get(_c, msg_getHash(m,0)); } break; } default: break; } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5971823 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalTabwrite.h0000644000000000000000000001266014735300037020266 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_SIGNAL_TABWRITE_H_ #define _HEAVY_SIGNAL_TABWRITE_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif #define HV_TABWRITE_STOPPED -1 // ~0x0 typedef struct SignalTabwrite { HvTable *table; hv_uint32_t head; // local write head. Where this object has most recently written to the table. } SignalTabwrite; hv_size_t sTabwrite_init(SignalTabwrite *o, HvTable *table); void sTabwrite_onMessage(HeavyContextInterface *_c, SignalTabwrite *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); // linear write to table static inline void __hv_tabwrite_f(SignalTabwrite *o, hv_bInf_t bIn) { hv_assert((o->head + HV_N_SIMD) <= hTable_getSize(o->table)); // assert that the table bounds are respected hv_uint32_t head = o->head; #if HV_SIMD_AVX _mm256_store_ps(hTable_getBuffer(o->table) + head, bIn); #elif HV_SIMD_SSE _mm_store_ps(hTable_getBuffer(o->table) + head, bIn); #elif HV_SIMD_NEON vst1q_f32(hTable_getBuffer(o->table) + head, bIn); #else // HV_SIMD_NONE *(hTable_getBuffer(o->table) + head) = bIn; #endif head += HV_N_SIMD; o->head = head; // update local write head hTable_setHead(o->table, head); // update the remote write head (e.g. for use by vd~) } // linear unaligned write to table static inline void __hv_tabwriteu_f(SignalTabwrite *o, hv_bInf_t bIn) { hv_uint32_t head = o->head; #if HV_SIMD_AVX _mm256_storeu_ps(hTable_getBuffer(o->table) + head, bIn); #elif HV_SIMD_SSE _mm_storeu_ps(hTable_getBuffer(o->table) + head, bIn); #elif HV_SIMD_NEON vst1q_f32(hTable_getBuffer(o->table) + head, bIn); #else // HV_SIMD_NONE *(hTable_getBuffer(o->table) + head) = bIn; #endif head += HV_N_SIMD; o->head = head; // update local write head hTable_setHead(o->table, head); // update remote write head } // this tabwrite can be instructed to stop. It is mainly intended for linear reads that only process a portion of a buffer. // Stores are unaligned, which can be slow but allows any indicies to be written to. // TODO(mhroth): this is not stopping! static inline void __hv_tabwrite_stoppable_f(SignalTabwrite *o, hv_bInf_t bIn) { if (o->head != HV_TABWRITE_STOPPED) { #if HV_SIMD_AVX _mm256_storeu_ps(hTable_getBuffer(o->table) + o->head, bIn); #elif HV_SIMD_SSE _mm_storeu_ps(hTable_getBuffer(o->table) + o->head, bIn); #elif HV_SIMD_NEON vst1q_f32(hTable_getBuffer(o->table) + o->head, bIn); #else // HV_SIMD_NONE *(hTable_getBuffer(o->table) + o->head) = bIn; #endif o->head += HV_N_SIMD; } } // random write to table static inline void __hv_tabwrite_if(SignalTabwrite *o, hv_bIni_t bIn0, hv_bInf_t bIn1) { float *const b = hTable_getBuffer(o->table); #if HV_SIMD_AVX const hv_int32_t *const i = (hv_int32_t *) &bIn0; const float *const f = (float *) &bIn1; hv_assert(i[0] >= 0 && i[0] < hTable_getAllocated(o->table)); hv_assert(i[1] >= 0 && i[1] < hTable_getAllocated(o->table)); hv_assert(i[2] >= 0 && i[2] < hTable_getAllocated(o->table)); hv_assert(i[3] >= 0 && i[3] < hTable_getAllocated(o->table)); hv_assert(i[4] >= 0 && i[4] < hTable_getAllocated(o->table)); hv_assert(i[5] >= 0 && i[5] < hTable_getAllocated(o->table)); hv_assert(i[6] >= 0 && i[6] < hTable_getAllocated(o->table)); hv_assert(i[7] >= 0 && i[7] < hTable_getAllocated(o->table)); b[i[0]] = f[0]; b[i[1]] = f[1]; b[i[2]] = f[2]; b[i[3]] = f[3]; b[i[4]] = f[4]; b[i[5]] = f[5]; b[i[6]] = f[6]; b[i[7]] = f[7]; #elif HV_SIMD_SSE const hv_int32_t *const i = (hv_int32_t *) &bIn0; const float *const f = (float *) &bIn1; hv_assert(i[0] >= 0 && ((hv_uint32_t) i[0]) < hTable_getAllocated(o->table)); hv_assert(i[1] >= 0 && ((hv_uint32_t) i[1]) < hTable_getAllocated(o->table)); hv_assert(i[2] >= 0 && ((hv_uint32_t) i[2]) < hTable_getAllocated(o->table)); hv_assert(i[3] >= 0 && ((hv_uint32_t) i[3]) < hTable_getAllocated(o->table)); b[i[0]] = f[0]; b[i[1]] = f[1]; b[i[2]] = f[2]; b[i[3]] = f[3]; #elif HV_SIMD_NEON hv_assert((vgetq_lane_s32(bIn0,0) >= 0) && (vgetq_lane_s32(bIn0,0) < hTable_getSize(o->table))); hv_assert((vgetq_lane_s32(bIn0,1) >= 0) && (vgetq_lane_s32(bIn0,1) < hTable_getSize(o->table))); hv_assert((vgetq_lane_s32(bIn0,2) >= 0) && (vgetq_lane_s32(bIn0,2) < hTable_getSize(o->table))); hv_assert((vgetq_lane_s32(bIn0,3) >= 0) && (vgetq_lane_s32(bIn0,3) < hTable_getSize(o->table))); vst1q_lane_f32(b + vgetq_lane_s32(bIn0, 0), bIn1, 0); vst1q_lane_f32(b + vgetq_lane_s32(bIn0, 1), bIn1, 1); vst1q_lane_f32(b + vgetq_lane_s32(bIn0, 2), bIn1, 2); vst1q_lane_f32(b + vgetq_lane_s32(bIn0, 3), bIn1, 3); #else // HV_SIMD_NONE b[bIn0] = bIn1; #endif } #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_SIGNAL_TABWRITE_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalVar.c0000644000000000000000000000551214435670357017242 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvSignalVar.h" // __var~f static void sVarf_update(SignalVarf *o, float k, float step, bool reverse) { #if HV_SIMD_AVX if (reverse) o->v = _mm256_setr_ps(k+7.0f*step, k+6.0f*step, k+5.0f*step, k+4.0f*step, k+3.0f*step, k+2.0f*step, k+step, k); else o->v = _mm256_set_ps(k+7.0f*step, k+6.0f*step, k+5.0f*step, k+4.0f*step, k+3.0f*step, k+2.0f*step, k+step, k); #elif HV_SIMD_SSE if (reverse) o->v = _mm_setr_ps(k+3.0f*step, k+2.0f*step, k+step, k); else o->v = _mm_set_ps(k+3.0f*step, k+2.0f*step, k+step, k); #elif HV_SIMD_NEON if (reverse) o->v = (float32x4_t) {3.0f*step+k, 2.0f*step+k, step+k, k}; else o->v = (float32x4_t) {k, step+k, 2.0f*step+k, 3.0f*step+k}; #else // HV_SIMD_NONE o->v = k; #endif } hv_size_t sVarf_init(SignalVarf *o, float k, float step, bool reverse) { sVarf_update(o, k, step, reverse); return 0; } void sVarf_onMessage(HeavyContextInterface *_c, SignalVarf *o, const HvMessage *m) { if (msg_isFloat(m,0)) { sVarf_update(o, msg_getFloat(m,0), msg_isFloat(m,1) ? msg_getFloat(m,1) : 0.0f, msg_getNumElements(m) == 3); } } // __var~i static void sVari_update(SignalVari *o, int k, int step, bool reverse) { #if HV_SIMD_AVX if (reverse) o->v = _mm256_setr_epi32(k+7*step, k+6*step, k+5*step, k+4*step, k+3*step, k+2*step, k+step, k); else o->v = _mm256_set_epi32(k+7*step, k+6*step, k+5*step, k+4*step, k+3*step, k+2*step, k+step, k); #elif HV_SIMD_SSE if (reverse) o->v = _mm_setr_epi32(k+3*step, k+2*step, k+step, k); else o->v = _mm_set_epi32(k+3*step, k+2*step, k+step, k); #elif HV_SIMD_NEON if (reverse) o->v = (int32x4_t) {3*step+k, 2*step+k, step+k, k}; else o->v = (int32x4_t) {k, step+k, 2*step+k, 3*step+k}; #else // HV_SIMD_NEON o->v = k; #endif } hv_size_t sVari_init(SignalVari *o, int k, int step, bool reverse) { sVari_update(o, k, step, reverse); return 0; } void sVari_onMessage(HeavyContextInterface *_c, SignalVari *o, const HvMessage *m) { if (msg_isFloat(m,0)) { sVari_update(o, (int) msg_getFloat(m,0), msg_isFloat(m,1) ? (int) msg_getFloat(m,1) : 0, msg_getNumElements(m) == 3); } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvSignalVar.h0000644000000000000000000000621314435670357017246 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_SIGNAL_VAR_H_ #define _HEAVY_SIGNAL_VAR_H_ #include "HvHeavyInternal.h" #ifdef __cplusplus extern "C" { #endif // __var~f, __varread~f, __varwrite~f typedef struct SignalVarf { hv_bufferf_t v; } SignalVarf; hv_size_t sVarf_init(SignalVarf *o, float k, float step, bool reverse); static inline void __hv_varread_f(SignalVarf *o, hv_bOutf_t bOut) { *bOut = o->v; } static inline void __hv_varwrite_f(SignalVarf *o, hv_bInf_t bIn) { o->v = bIn; } void sVarf_onMessage(HeavyContextInterface *_c, SignalVarf *o, const HvMessage *m); // __var~i, __varread~i, __varwrite~i typedef struct SignalVari { hv_bufferi_t v; } SignalVari; hv_size_t sVari_init(SignalVari *o, int k, int step, bool reverse); static inline void __hv_varread_i(SignalVari *o, hv_bOuti_t bOut) { *bOut = o->v; } static inline void __hv_varwrite_i(SignalVari *o, hv_bIni_t bIn) { o->v = bIn; } void sVari_onMessage(HeavyContextInterface *_c, SignalVari *o, const HvMessage *m); // __var_k~f, __var_k~i #if HV_SIMD_AVX #define __hv_var_k_i(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_mm256_set_epi32(_h,_g,_f,_e,_d,_c,_b,_a) #define __hv_var_k_i_r(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_mm256_set_epi32(_a,_b,_c,_d,_e,_f,_g,_h) #define __hv_var_k_f(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_mm256_set_ps(_h,_g,_f,_e,_d,_c,_b,_a) #define __hv_var_k_f_r(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_mm256_set_ps(_a,_b,_c,_d,_e,_f,_g,_h) #elif HV_SIMD_SSE #define __hv_var_k_i(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_mm_set_epi32(_d,_c,_b,_a) #define __hv_var_k_i_r(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_mm_set_epi32(_a,_b,_c,_d) #define __hv_var_k_f(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_mm_set_ps(_d,_c,_b,_a) #define __hv_var_k_f_r(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_mm_set_ps(_a,_b,_c,_d) #elif HV_SIMD_NEON #define __hv_var_k_i(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((int32x4_t) {_a,_b,_c,_d}) #define __hv_var_k_i_r(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((int32x4_t) {_d,_c,_b,_a}) #define __hv_var_k_f(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((float32x4_t) {_a,_b,_c,_d}) #define __hv_var_k_f_r(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((float32x4_t) {_d,_c,_b,_a}) #else // HV_SIMD_NONE #define __hv_var_k_i(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_a #define __hv_var_k_i_r(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_a #define __hv_var_k_f(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_a #define __hv_var_k_f_r(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_a #endif #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_SIGNAL_VAR_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvTable.c0000644000000000000000000001023314435670357016377 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvTable.h" #include "HvMessage.h" hv_size_t hTable_init(HvTable *o, int length) { o->length = length; // true size of the table is always an integer multple of HV_N_SIMD o->size = (length + HV_N_SIMD_MASK) & ~HV_N_SIMD_MASK; // add an extra length for mirroring o->allocated = o->size + HV_N_SIMD; o->head = 0; hv_size_t numBytes = o->allocated * sizeof(float); o->buffer = (float *) hv_malloc(numBytes); hv_assert(o->buffer != NULL); hv_memclear(o->buffer, numBytes); return numBytes; } hv_size_t hTable_initWithData(HvTable *o, int length, const float *data) { o->length = length; o->size = (length + HV_N_SIMD_MASK) & ~HV_N_SIMD_MASK; o->allocated = o->size + HV_N_SIMD; o->head = 0; hv_size_t numBytes = o->size * sizeof(float); o->buffer = (float *) hv_malloc(numBytes); hv_assert(o->buffer != NULL); hv_memclear(o->buffer, numBytes); hv_memcpy(o->buffer, data, length*sizeof(float)); return numBytes; } hv_size_t hTable_initWithFinalData(HvTable *o, int length, float *data) { o->length = length; o->size = length; o->allocated = length; o->buffer = data; o->head = 0; return 0; } void hTable_free(HvTable *o) { hv_free(o->buffer); } int hTable_resize(HvTable *o, hv_uint32_t newLength) { // TODO(mhroth): update context with memory allocated by table // NOTE(mhroth): mirrored bytes are not necessarily carried over const hv_uint32_t newSize = (newLength + HV_N_SIMD_MASK) & ~HV_N_SIMD_MASK; if (newSize == o->size) return 0; // early exit if no change in size const hv_uint32_t oldSizeBytes = (hv_uint32_t) (o->size * sizeof(float)); const hv_uint32_t newAllocated = newSize + HV_N_SIMD; const hv_uint32_t newAllocatedBytes = (hv_uint32_t) (newAllocated * sizeof(float)); float *b = (float *) hv_realloc(o->buffer, newAllocatedBytes); hv_assert(b != NULL); // error while reallocing! // ensure that hv_realloc has given us a correctly aligned buffer if ((((hv_uintptr_t) (const void *) b) & ((0x1< o->size) { hv_memclear(b + o->size, (newAllocated - o->size) * sizeof(float)); // clear new parts of the buffer } o->buffer = b; } else { // if not, we have to re-malloc ourselves char *c = (char *) hv_malloc(newAllocatedBytes); hv_assert(c != NULL); // error while allocating new buffer! if (newAllocatedBytes > oldSizeBytes) { hv_memcpy(c, b, oldSizeBytes); hv_memclear(c + oldSizeBytes, newAllocatedBytes - oldSizeBytes); } else { hv_memcpy(c, b, newAllocatedBytes); } hv_free(b); o->buffer = (float *) c; } o->length = newLength; o->size = newSize; o->allocated = newAllocated; return (int) (newAllocated - oldSizeBytes - (HV_N_SIMD*sizeof(float))); } void hTable_onMessage(HeavyContextInterface *_c, HvTable *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)) { if (msg_compareSymbol(m,0,"resize") && msg_isFloat(m,1) && msg_getFloat(m,1) >= 0.0f) { hTable_resize(o, (int) hv_ceil_f(msg_getFloat(m,1))); // apply ceil to ensure that tables always have enough space // send out the new size of the table HvMessage *n = HV_MESSAGE_ON_STACK(1); msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getSize(o)); sendMessage(_c, 0, n); } else if (msg_compareSymbol(m,0,"mirror")) { hv_memcpy(o->buffer+o->size, o->buffer, HV_N_SIMD*sizeof(float)); } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvTable.h0000644000000000000000000000510114435670357016402 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_TABLE_H_ #define _HEAVY_TABLE_H_ #include "HvHeavy.h" #include "HvUtils.h" #ifdef __cplusplus extern "C" { #endif typedef struct HvTable { float *buffer; // the number of values that the table is requested to have hv_uint32_t length; // the number of usable values that the table actually has // this is always an even multiple of HV_N_SIMD hv_uint32_t size; // Note that the true size of the table is (size + HV_N_SIMD), // with the trailing values used by the system, e.g. to create a circular // buffer hv_uint32_t allocated; hv_uint32_t head; // the most recently written point } HvTable; hv_size_t hTable_init(HvTable *o, int length); hv_size_t hTable_initWithData(HvTable *o, int length, const float *data); hv_size_t hTable_initWithFinalData(HvTable *o, int length, float *data); void hTable_free(HvTable *o); int hTable_resize(HvTable *o, hv_uint32_t newLength); void hTable_onMessage(HeavyContextInterface *_c, HvTable *o, int letIn, const HvMessage *m, void (*sendMessage)(HeavyContextInterface *, int, const HvMessage *)); static inline float *hTable_getBuffer(HvTable *o) { return o->buffer; } // the user-requested length of the table (number of floats) static inline hv_uint32_t hTable_getLength(HvTable *o) { return o->length; } // the usable length of the table (an even multiple of HV_N_SIMD) static inline hv_uint32_t hTable_getSize(HvTable *o) { return o->size; } // the number of floats allocated to this table (usually size + HV_N_SIMD) static inline hv_uint32_t hTable_getAllocated(HvTable *o) { return o->allocated; } static inline hv_uint32_t hTable_getHead(HvTable *o) { return o->head; } static inline void hTable_setHead(HvTable *o, hv_uint32_t head) { o->head = head; } #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_TABLE_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/HvUtils.c0000644000000000000000000000316514435670357016456 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "HvUtils.h" hv_uint32_t hv_string_to_hash(const char *str) { // this hash is based MurmurHash2 // http://en.wikipedia.org/wiki/MurmurHash // https://sites.google.com/site/murmurhash/ static const hv_uint32_t n = 0x5bd1e995; static const hv_int32_t r = 24; if (str == NULL) return 0; hv_uint32_t len = (hv_uint32_t) hv_strlen(str); hv_uint32_t x = len; // seed (0) ^ len while (len >= 4) { #if HV_EMSCRIPTEN hv_uint32_t k = str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24); #else hv_uint32_t k = *((hv_uint32_t *) str); #endif k *= n; k ^= (k >> r); k *= n; x *= n; x ^= k; str += 4; len -= 4; } switch (len) { case 3: x ^= (str[2] << 16); case 2: x ^= (str[1] << 8); case 1: x ^= str[0]; x *= n; default: break; } x ^= (x >> 13); x *= n; x ^= (x >> 15); return x; } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754040.029784 hvcc-0.13.3/hvcc/generators/ir2c/static/HvUtils.h0000644000000000000000000002307214735300470016447 0ustar00/** * Copyright (c) 2014-2018 Enzien Audio Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HEAVY_UTILS_H_ #define _HEAVY_UTILS_H_ // platform definitions #if _WIN32 || _WIN64 || _MSC_VER #define HV_WIN 1 #elif __APPLE__ #define HV_APPLE 1 #elif __ANDROID__ #define HV_ANDROID 1 #elif __unix__ || __unix #define HV_UNIX 1 #else #warning Could not detect platform. Assuming Unix-like. #endif #ifdef EMSCRIPTEN #define HV_EMSCRIPTEN 1 #endif // basic includes #include #include #include // type definitions #include #include #define hv_uint8_t uint8_t #define hv_int16_t int16_t #define hv_uint16_t uint16_t #define hv_int32_t int32_t #define hv_uint32_t uint32_t #define hv_uint64_t uint64_t #define hv_size_t size_t #define hv_uintptr_t uintptr_t // SIMD-specific includes #if !(HV_SIMD_NONE || HV_SIMD_NEON || HV_SIMD_SSE || HV_SIMD_AVX) #define HV_SIMD_NEON __ARM_NEON__ #define HV_SIMD_SSE (__SSE__ && __SSE2__ && __SSE3__ && __SSSE3__ && __SSE4_1__) #define HV_SIMD_AVX (__AVX__ && HV_SIMD_SSE) #endif #ifndef HV_SIMD_FMA #define HV_SIMD_FMA __FMA__ #endif #if HV_SIMD_AVX || HV_SIMD_SSE #include #elif HV_SIMD_NEON #include #endif #if HV_SIMD_NEON // NEON #define HV_N_SIMD 4 #define hv_bufferf_t float32x4_t #define hv_bufferi_t int32x4_t #define hv_bInf_t float32x4_t #define hv_bOutf_t float32x4_t* #define hv_bIni_t int32x4_t #define hv_bOuti_t int32x4_t* #define VIf(_x) (_x) #define VOf(_x) (&_x) #define VIi(_x) (_x) #define VOi(_x) (&_x) #elif HV_SIMD_AVX // AVX #define HV_N_SIMD 8 #define hv_bufferf_t __m256 #define hv_bufferi_t __m256i #define hv_bInf_t __m256 #define hv_bOutf_t __m256* #define hv_bIni_t __m256i #define hv_bOuti_t __m256i* #define VIf(_x) (_x) #define VOf(_x) (&_x) #define VIi(_x) (_x) #define VOi(_x) (&_x) #elif HV_SIMD_SSE // SSE #define HV_N_SIMD 4 #define hv_bufferf_t __m128 #define hv_bufferi_t __m128i #define hv_bInf_t __m128 #define hv_bOutf_t __m128* #define hv_bIni_t __m128i #define hv_bOuti_t __m128i* #define VIf(_x) (_x) #define VOf(_x) (&_x) #define VIi(_x) (_x) #define VOi(_x) (&_x) #else // DEFAULT #define HV_N_SIMD 1 #undef HV_SIMD_NONE #define HV_SIMD_NONE 1 #define hv_bufferf_t float #define hv_bufferi_t int #define hv_bInf_t float #define hv_bOutf_t float* #define hv_bIni_t int #define hv_bOuti_t int* #define VIf(_x) (_x) #define VOf(_x) (&_x) #define VIi(_x) (_x) #define VOi(_x) (&_x) #endif #define HV_N_SIMD_MASK (HV_N_SIMD-1) // Strings #include #define hv_strlen(a) strlen(a) #define hv_strcmp(a, b) strcmp(a, b) #define hv_snprintf(a, b, c, ...) snprintf(a, b, c, __VA_ARGS__) #if HV_WIN #define hv_strncpy(_dst, _src, _len) strncpy_s(_dst, _len, _src, _TRUNCATE) #else #define hv_strncpy(_dst, _src, _len) strncpy(_dst, _src, _len) #endif // Memory management #define hv_memcpy(a, b, c) memcpy(a, b, c) #define hv_memclear(a, b) memset(a, 0, b) #if HV_WIN #include #define hv_alloca(_n) _alloca(_n) #if HV_SIMD_AVX #define hv_malloc(_n) _aligned_malloc(_n, 32) #define hv_realloc(a, b) _aligned_realloc(a, b, 32) #define hv_free(x) _aligned_free(x) #elif HV_SIMD_SSE || HV_SIMD_NEON #define hv_malloc(_n) _aligned_malloc(_n, 16) #define hv_realloc(a, b) _aligned_realloc(a, b, 16) #define hv_free(x) _aligned_free(x) #else // HV_SIMD_NONE #define hv_malloc(_n) malloc(_n) #define hv_realloc(a, b) realloc(a, b) #define hv_free(_n) free(_n) #endif #elif HV_APPLE #define hv_alloca(_n) alloca(_n) #define hv_realloc(a, b) realloc(a, b) #if HV_SIMD_AVX #include #define hv_malloc(_n) _mm_malloc(_n, 32) #define hv_free(x) _mm_free(x) #elif HV_SIMD_SSE #include #define hv_malloc(_n) _mm_malloc(_n, 16) #define hv_free(x) _mm_free(x) #elif HV_SIMD_NEON // malloc on ios always has 16-byte alignment #define hv_malloc(_n) malloc(_n) #define hv_free(x) free(x) #else // HV_SIMD_NONE #define hv_malloc(_n) malloc(_n) #define hv_free(x) free(x) #endif #else #include #define hv_alloca(_n) alloca(_n) #define hv_realloc(a, b) realloc(a, b) #if HV_SIMD_AVX #define hv_malloc(_n) aligned_alloc(32, _n) #define hv_free(x) free(x) #elif HV_SIMD_SSE #define hv_malloc(_n) aligned_alloc(16, _n) #define hv_free(x) free(x) #elif HV_SIMD_NEON #if HV_ANDROID #define hv_malloc(_n) memalign(16, _n) #define hv_free(x) free(x) #else #define hv_malloc(_n) aligned_alloc(16, _n) #define hv_free(x) free(x) #endif #else // HV_SIMD_NONE #define hv_malloc(_n) malloc(_n) #define hv_free(_n) free(_n) #endif #endif // Assert #include #define hv_assert(e) assert(e) // Export and Inline #if HV_WIN #define HV_EXPORT __declspec(dllexport) #ifndef __cplusplus // MSVC doesn't like redefining "inline" keyword #define inline __inline #endif #define HV_FORCE_INLINE __forceinline #else #define HV_EXPORT #define HV_FORCE_INLINE inline __attribute__((always_inline)) #endif #ifdef __cplusplus extern "C" { #endif // Returns a 32-bit hash of any string. Returns 0 if string is NULL. hv_uint32_t hv_string_to_hash(const char *str); #ifdef __cplusplus } #endif // Math #include static inline hv_size_t __hv_utils_max_ui(hv_size_t x, hv_size_t y) { return (x > y) ? x : y; } static inline hv_size_t __hv_utils_min_ui(hv_size_t x, hv_size_t y) { return (x < y) ? x : y; } static inline hv_int32_t __hv_utils_max_i(hv_int32_t x, hv_int32_t y) { return (x > y) ? x : y; } static inline hv_int32_t __hv_utils_min_i(hv_int32_t x, hv_int32_t y) { return (x < y) ? x : y; } #define hv_max_ui(a, b) __hv_utils_max_ui(a, b) #define hv_min_ui(a, b) __hv_utils_min_ui(a, b) #define hv_max_i(a, b) __hv_utils_max_i(a, b) #define hv_min_i(a, b) __hv_utils_min_i(a, b) #define hv_max_f(a, b) fmaxf(a, b) #define hv_min_f(a, b) fminf(a, b) #define hv_max_d(a, b) fmax(a, b) #define hv_min_d(a, b) fmin(a, b) #define hv_sin_f(a) sinf(a) #define hv_sinh_f(a) sinhf(a) #define hv_cos_f(a) cosf(a) #define hv_cosh_f(a) coshf(a) #define hv_tan_f(a) tanf(a) #define hv_tanh_f(a) tanhf(a) #define hv_asin_f(a) asinf(a) #define hv_asinh_f(a) asinhf(a) #define hv_acos_f(a) acosf(a) #define hv_acosh_f(a) acoshf(a) #define hv_atan_f(a) atanf(a) #define hv_atanh_f(a) atanhf(a) #define hv_atan2_f(a, b) atan2f(a, b) #define hv_exp_f(a) expf(a) #define hv_abs_f(a) fabsf(a) #define hv_sqrt_f(a) sqrtf(a) #define hv_log_f(a) logf(a) #define hv_ceil_f(a) ceilf(a) #define hv_floor_f(a) floorf(a) #define hv_round_f(a) roundf(a) #define hv_pow_f(a, b) powf(a, b) #if HV_EMSCRIPTEN #define hv_fma_f(a, b, c) ((a*b)+c) // emscripten does not support fmaf (yet?) #else #define hv_fma_f(a, b, c) fmaf(a, b, c) #endif #if HV_WIN // finds ceil(log2(x)) #include static inline hv_uint32_t __hv_utils_min_max_log2(hv_uint32_t x) { unsigned long z = 0; _BitScanReverse(&z, x); return (hv_uint32_t) (z+1); } #else static inline hv_uint32_t __hv_utils_min_max_log2(hv_uint32_t x) { return (hv_uint32_t) (32 - __builtin_clz(x-1)); } #endif #define hv_min_max_log2(a) __hv_utils_min_max_log2(a) // Atomics #if HV_WIN #include #define hv_atomic_bool volatile LONG #define HV_SPINLOCK_ACQUIRE(_x) while (InterlockedCompareExchange(&_x, true, false)) { } #define HV_SPINLOCK_TRY(_x) return !InterlockedCompareExchange(&_x, true, false) #define HV_SPINLOCK_RELEASE(_x) (_x = false) #elif HV_ANDROID // Android support for atomics isn't that great, we'll do it manually // https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html #define hv_atomic_bool hv_uint8_t #define HV_SPINLOCK_ACQUIRE(_x) while (__sync_lock_test_and_set(&_x, 1)) #define HV_SPINLOCK_TRY(_x) return !__sync_lock_test_and_set(&_x, 1) #define HV_SPINLOCK_RELEASE(_x) __sync_lock_release(&_x) #elif __cplusplus #include #define hv_atomic_bool std::atomic_flag #define HV_SPINLOCK_ACQUIRE(_x) while (_x.test_and_set(std::memory_order_acquire)) #define HV_SPINLOCK_TRY(_x) return !_x.test_and_set(std::memory_order_acquire) #define HV_SPINLOCK_RELEASE(_x) _x.clear(std::memory_order_release) #elif defined(__has_include) #if __has_include() #include #define hv_atomic_bool atomic_flag #define HV_SPINLOCK_ACQUIRE(_x) while (atomic_flag_test_and_set_explicit(&_x, memory_order_acquire)) #define HV_SPINLOCK_TRY(_x) return !atomic_flag_test_and_set_explicit(&_x, memory_order_acquire) #define HV_SPINLOCK_RELEASE(_x) atomic_flag_clear_explicit(memory_order_release) #endif #endif #ifndef hv_atomic_bool #define hv_atomic_bool volatile bool #define HV_SPINLOCK_ACQUIRE(_x) \ while (_x) {} \ _x = true; #define HV_SPINLOCK_TRY(_x) \ if (!_x) { \ _x = true; \ return true; \ } else return false; #define HV_SPINLOCK_RELEASE(_x) (_x = false) #endif #endif // _HEAVY_UTILS_H_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/cpuid.c0000644000000000000000000001071114435670357016157 0ustar00/* cpuid.c * * Author : Alexander J. Yee * Date Created : 01/19/2012 * Last Modified : 01/25/2012 * * * * And of course... The typical copyright stuff... * * Redistribution of this program in both source or binary, regardless of * form, with or without modification is permitted as long as the following * conditions are met: * 1. This copyright notice is maintained either inline in the source * or distributed with the binary. * 2. A list of all contributing authors along with their contributions * is included either inline in the source or distributed with the * binary. * 3. The following disclaimer is maintained either inline in the * source or distributed with the binary. * * Disclaimer: * This software is provided "as is", without any guarantee made to its * suitability or fitness for any particular use. It may contain bugs so use * of this program is at your own risk. I take no responsibility for any * damage that may unintentionally be caused through its use. */ // https://github.com/Mysticial/Flops/blob/e571da6e94f7b6d2d1a90e87b19398c5c4de4375/version1/source/cpuid.c // http://www.sandpile.org/x86/cpuid.htm #ifndef _cpuid_c #define _cpuid_c #include //#include #include "cpuid.h" //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// #ifdef WIN32 #else void cpuid(int *info,int x){ int ax,bx,cx,dx; __asm__ __volatile__ ("cpuid": "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (x)); info[0] = ax; info[1] = bx; info[2] = cx; info[3] = dx; } #endif //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void cpuid_print_name(){ int name[13]; cpuid(name + 0,0x80000002); cpuid(name + 4,0x80000003); cpuid(name + 8,0x80000004); name[12] = '\0'; printf("CPU Name = %s\n",(char*)name); // printf("Threads = %d\n",omp_get_max_threads()); printf("\n"); } void cpuid_print_exts(){ int x64 = 0; int MMX = 0; int SSE = 0; int SSE2 = 0; int SSE3 = 0; int SSSE3 = 0; int SSE41 = 0; int SSE42 = 0; int SSE4a = 0; int AVX = 0; int AVX2 = 0; int XOP = 0; int FMA3 = 0; int FMA4 = 0; int info[4]; cpuid(info, 0); int nIds = info[0]; cpuid(info, 0x80000000); int nExIds = info[0]; // Detect Instruction Set if (nIds >= 1){ cpuid(info,0x00000001); MMX = (info[3] & ((int)1 << 23)) != 0; SSE = (info[3] & ((int)1 << 25)) != 0; SSE2 = (info[3] & ((int)1 << 26)) != 0; SSE3 = (info[2] & ((int)1 << 0)) != 0; SSSE3 = (info[2] & ((int)1 << 9)) != 0; SSE41 = (info[2] & ((int)1 << 19)) != 0; SSE42 = (info[2] & ((int)1 << 20)) != 0; AVX = (info[2] & ((int)1 << 28)) != 0; FMA3 = (info[2] & ((int)1 << 12)) != 0; } if (nExIds >= 0x00000007){ cpuid(info,0x00000007); AVX2 = (info[2] & ((int)1 << 5)) != 0; } if (nExIds >= 0x80000001){ cpuid(info,0x80000001); x64 = (info[3] & ((int)1 << 29)) != 0; SSE4a = (info[2] & ((int)1 << 6)) != 0; FMA4 = (info[2] & ((int)1 << 16)) != 0; XOP = (info[2] & ((int)1 << 11)) != 0; } printf("Hardware Features:\n"); printf("x64 = %d\n",x64); printf("MMX = %d\n",MMX); printf("SSE = %d\n",SSE); printf("SSE2 = %d\n",SSE2); printf("SSE3 = %d\n",SSE3); printf("SSSE3 = %d\n",SSSE3); printf("SSE4a = %d\n",SSE4a); printf("SSE41 = %d\n",SSE41); printf("SSE42 = %d\n",SSE42); printf("AVX = %d\n",AVX); printf("AVX2 = %d\n",AVX2); printf("FMA3 = %d\n",FMA3); printf("FMA4 = %d\n",FMA4); printf("XOP = %d\n",XOP); printf("\n"); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// #endif ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.765207 hvcc-0.13.3/hvcc/generators/ir2c/static/cpuid.h0000644000000000000000000000441714435670357016172 0ustar00/* cpuid.h * * Author : Alexander J. Yee * Date Created : 01/19/2012 * Last Modified : 01/25/2012 * * * * And of course... The typical copyright stuff... * * Redistribution of this program in both source or binary, regardless of * form, with or without modification is permitted as long as the following * conditions are met: * 1. This copyright notice is maintained either inline in the source * or distributed with the binary. * 2. A list of all contributing authors along with their contributions * is included either inline in the source or distributed with the * binary. * 3. The following disclaimer is maintained either inline in the * source or distributed with the binary. * * Disclaimer: * This software is provided "as is", without any guarantee made to its * suitability or fitness for any particular use. It may contain bugs so use * of this program is at your own risk. I take no responsibility for any * damage that may unintentionally be caused through its use. */ // https://github.com/Mysticial/Flops/blob/e571da6e94f7b6d2d1a90e87b19398c5c4de4375/version1/source/cpuid.h #ifndef _cpuid_h #define _cpuid_h #ifdef __cplusplus extern "C" { #endif //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// #ifdef WIN32 #include #define cpuid __cpuid #else void cpuid(int *info,int x); #endif //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void cpuid_print_name(); void cpuid_print_exts(); //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// #ifdef __cplusplus } #endif #endif ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735983617.1410897 hvcc-0.13.3/hvcc/generators/ir2c/templates/Heavy_NAME.cpp0000644000000000000000000002702314736201001017756 0ustar00{{copyright}} #include "Heavy_{{name}}.hpp" #include #define Context(_c) static_cast(_c) /* * C Functions */ extern "C" { HV_EXPORT HeavyContextInterface *hv_{{name}}_new(double sampleRate) { // allocate aligned memory void *ptr = hv_malloc(sizeof(Heavy_{{name}})); // ensure non-null if (!ptr) return nullptr; // call constructor new(ptr) Heavy_{{name}}(sampleRate); return Context(ptr); } HV_EXPORT HeavyContextInterface *hv_{{name}}_new_with_options(double sampleRate, int poolKb, int inQueueKb, int outQueueKb) { // allocate aligned memory void *ptr = hv_malloc(sizeof(Heavy_{{name}})); // ensure non-null if (!ptr) return nullptr; // call constructor new(ptr) Heavy_{{name}}(sampleRate, poolKb, inQueueKb, outQueueKb); return Context(ptr); } HV_EXPORT void hv_{{name}}_free(HeavyContextInterface *instance) { // call destructor Context(instance)->~Heavy_{{name}}(); // free memory hv_free(instance); } } // extern "C" {% if table_data_list|length > 0 -%} /* * Table Data */ {% for x in table_data_list %} {{x}} {%- endfor %} {%- endif %} /* * Class Functions */ Heavy_{{name}}::Heavy_{{name}}(double sampleRate, int poolKb, int inQueueKb, int outQueueKb) : HeavyContext(sampleRate, poolKb, inQueueKb, outQueueKb) { {%- for x in init_list %} numBytes += {{x}} {%- endfor %} {% if "__hv_init" in send_receive %} // schedule a message to trigger all loadbangs via the __hv_init receiver scheduleMessageForReceiver({{send_receive["__hv_init"]["hash"]}}, msg_initWithBang(HV_MESSAGE_ON_STACK(1), 0)); {%- endif %} } Heavy_{{name}}::~Heavy_{{name}}() { {%- if free_list|length > 0 %} {%- for x in free_list %} {{x}} {%- endfor %} {%- else %} // nothing to free {%- endif %} } HvTable *Heavy_{{name}}::getTableForHash(hv_uint32_t tableHash) { {%- if send_table|length > 0 -%} switch (tableHash) { {%- for k,v in send_table.items() %} case {{v.hash}}: return &hTable_{{v.id}}; // {{v.display}} {%- endfor %} default: return nullptr; } {%- else %} return nullptr; {%- endif %} } void Heavy_{{name}}::scheduleMessageForReceiver(hv_uint32_t receiverHash, HvMessage *m) { switch (receiverHash) { {%- for k,v in send_receive.items() %} case {{v.hash}}: { // {{v.display}} {%- for obj_id in v.ids %} mq_addMessageByTimestamp(&mq, m, 0, &cReceive_{{obj_id}}_sendMessage); {%- endfor %} break; } {%- endfor %} default: return; } } int Heavy_{{name}}::getParameterInfo(int index, HvParameterInfo *info) { if (info != nullptr) { switch (index) { {%- for v in (send_receive|extern).values() %} case {{loop.index-1}}: { info->name = "{{v.display}}"; info->hash = {{v.hash}}; {%- if v.extern == "param" %} info->type = HvParameterType::HV_PARAM_TYPE_PARAMETER_IN; info->minVal = {{v.attributes.min}}f; info->maxVal = {{v.attributes.max}}f; info->defaultVal = {{v.attributes.default}}f; {%- else %} info->type = HvParameterType::HV_PARAM_TYPE_EVENT_IN; info->minVal = 0.0f; info->maxVal = 0.0f; info->defaultVal = 0.0f; {%- endif %} break; } {%- endfor %} default: { info->name = "invalid parameter index"; info->hash = 0; info->type = HvParameterType::HV_PARAM_TYPE_PARAMETER_IN; info->minVal = 0.0f; info->maxVal = 0.0f; info->defaultVal = 0.0f; break; } } } return {{send_receive|extern|length}}; } /* * Send Function Implementations */ {% for x in impl_list %} void Heavy_{{name}}::{{x}} {% if not loop.last -%} {%- endif %} {%- endfor %} /* * Context Process Implementation */ int Heavy_{{name}}::process(float **inputBuffers, float **outputBuffers, int n) { while (hLp_hasData(&inQueue)) { hv_uint32_t numBytes = 0; ReceiverMessagePair *p = reinterpret_cast(hLp_getReadBuffer(&inQueue, &numBytes)); hv_assert(numBytes >= sizeof(ReceiverMessagePair)); scheduleMessageForReceiver(p->receiverHash, &p->msg); hLp_consume(&inQueue); } sendBangToReceiver(0xDD21C0EB); // send to __hv_bang~ on next cycle {%- if nodsp is sameas false %} const int n4 = n & ~HV_N_SIMD_MASK; // ensure that the block size is a multiple of HV_N_SIMD // temporary signal vars {%- if signal.numTemporaryBuffers.float > 0 %} hv_bufferf_t {% for i in range(signal.numTemporaryBuffers.float) %}Bf{{i}}{% if not loop.last %}, {%endif%}{% endfor %}; {%- endif %} {%- if signal.numTemporaryBuffers.integer > 0 %} hv_bufferi_t {% for i in range(signal.numTemporaryBuffers.integer) %}Bi{{i}}{% if not loop.last %}, {%endif%}{% endfor %}; {%- endif %} // input and output vars {%- if signal.numOutputBuffers > 0 %} hv_bufferf_t {% for i in range(signal.numOutputBuffers) %}O{{i}}{% if not loop.last %}, {%endif%}{% endfor %}; {%- endif %} {%- if signal.numInputBuffers > 0 %} hv_bufferf_t {% for i in range(signal.numInputBuffers) %}I{{i}}{% if not loop.last %}, {%endif%}{% endfor %}; {%- endif %} // declare and init the zero buffer hv_bufferf_t ZERO; __hv_zero_f(VOf(ZERO)); hv_uint32_t nextBlock = blockStartTimestamp; for (int n = 0; n < n4; n += HV_N_SIMD) { // process all of the messages for this block nextBlock += HV_N_SIMD; while (mq_hasMessageBefore(&mq, nextBlock)) { MessageNode *const node = mq_peek(&mq); node->sendMessage(this, node->let, node->m); mq_pop(&mq); } {% if signal.numInputBuffers > 0 -%} // load input buffers {%- for i in range(signal.numInputBuffers) %} __hv_load_f(inputBuffers[{{i}}]+n, VOf(I{{i}})); {%- endfor %} {%- endif %} {% if signal.numOutputBuffers > 0 -%} // zero output buffers {%- for i in range(signal.numOutputBuffers) %} __hv_zero_f(VOf(O{{i}})); {%- endfor %} {%- endif %} // process all signal functions {%- for f in process_list %} {{f}} {%- endfor %} // save output vars to output buffer {%- if signal.numOutputBuffers > 0 %} {%- for i in range(signal.numOutputBuffers) %} __hv_store_f(outputBuffers[{{i}}]+n, VIf(O{{i}})); {%- endfor %} {%- else %} // no output channels {%- endif %} } blockStartTimestamp = nextBlock; return n4; // return the number of frames processed {%- else %} {# if this is a control-only patch, the process loop is substantially simpler. #} hv_uint32_t nextBlock = blockStartTimestamp + n; while (mq_hasMessageBefore(&mq, nextBlock)) { MessageNode *const node = mq_peek(&mq); node->sendMessage(this, node->let, node->m); mq_pop(&mq); } blockStartTimestamp = nextBlock; return n; {%- endif %} } int Heavy_{{name}}::processInline(float *inputBuffers, float *outputBuffers, int n4) { hv_assert(!(n4 & HV_N_SIMD_MASK)); // ensure that n4 is a multiple of HV_N_SIMD // define the heavy input buffer for {{signal.numInputBuffers}} channel(s) {%- if signal.numInputBuffers == 0 %} float **const bIn = NULL; {%- elif signal.numInputBuffers == 1 %} float **const bIn = &inputBuffers; {%- else %} float **const bIn = reinterpret_cast(hv_alloca({{signal.numInputBuffers}}*sizeof(float *))); {%- for i in range(signal.numInputBuffers) %} bIn[{{i}}] = inputBuffers+({{i}}*n4); {%- endfor %} {%- endif %} // define the heavy output buffer for {{signal.numOutputBuffers}} channel(s) {%- if signal.numOutputBuffers == 0 %} float **const bOut = NULL; {%- elif signal.numOutputBuffers == 1 %} float **const bOut = &outputBuffers; {%- else %} float **const bOut = reinterpret_cast(hv_alloca({{signal.numOutputBuffers}}*sizeof(float *))); {%- for i in range(signal.numOutputBuffers) %} bOut[{{i}}] = outputBuffers+({{i}}*n4); {%- endfor %} {%- endif %} int n = process(bIn, bOut, n4); return n; } int Heavy_{{name}}::processInlineInterleaved(float *inputBuffers, float *outputBuffers, int n4) { hv_assert(n4 & ~HV_N_SIMD_MASK); // ensure that n4 is a multiple of HV_N_SIMD // define the heavy input buffer for {{signal.numInputBuffers}} channel(s), uninterleave {%- if signal.numInputBuffers == 0 %} float *const bIn = NULL; {%- elif signal.numInputBuffers == 1 %} float *const bIn = inputBuffers; {%- elif signal.numInputBuffers == 2 %} float *const bIn = reinterpret_cast(hv_alloca(2*n4*sizeof(float))); #if HV_SIMD_SSE || HV_SIMD_AVX for (int i = 0, j = 0; j < n4; j += 4, i += 8) { __m128 a = _mm_load_ps(inputBuffers+i); // LRLR __m128 b = _mm_load_ps(inputBuffers+4+i); // LRLR __m128 x = _mm_shuffle_ps(a, b, _MM_SHUFFLE(2,0,2,0)); // LLLL __m128 y = _mm_shuffle_ps(a, b, _MM_SHUFFLE(3,1,3,1)); // RRRR _mm_store_ps(bIn+j, x); _mm_store_ps(bIn+n4+j, y); } #elif HV_SIMD_NEON for (int i = 0, j = 0; j < n4; j += 4, i += 8) { float32x4x2_t a = vld2q_f32(inputBuffers+i); // load and uninterleave vst1q_f32(bIn+j, a.val[0]); vst1q_f32(bIn+n4+j, a.val[1]); } #else // HV_SIMD_NONE for (int j = 0; j < n4; ++j) { {%- for i in range(signal.numInputBuffers) %} bIn[{{i}}*n4+j] = inputBuffers[{{i}}+{{signal.numInputBuffers}}*j]; {%- endfor %} } #endif {%- else %} float *const bIn = (float *) hv_alloca({{signal.numInputBuffers}}*n4*sizeof(float)); for (int j = 0; j < n4; ++j) { {%- for i in range(signal.numInputBuffers) %} bIn[{{i}}*n4+j] = inputBuffers[{{i}}+{{signal.numInputBuffers}}*j]; {%- endfor %} } {%- endif %} // define the heavy output buffer for {{signal.numOutputBuffers}} channel(s) {%- if signal.numOutputBuffers == 0 %} float *const bOut = NULL; {%- elif signal.numOutputBuffers == 1 %} float *const bOut = outputBuffers; {%- else %} float *const bOut = reinterpret_cast(hv_alloca({{signal.numOutputBuffers}}*n4*sizeof(float))); {%- endif %} int n = processInline(bIn, bOut, n4); {% if signal.numOutputBuffers == 2 -%} // interleave the heavy output into the output buffer #if HV_SIMD_AVX for (int i = 0, j = 0; j < n4; j += 8, i += 16) { __m256 x = _mm256_load_ps(bOut+j); // LLLLLLLL __m256 y = _mm256_load_ps(bOut+n4+j); // RRRRRRRR __m256 a = _mm256_unpacklo_ps(x, y); // LRLRLRLR __m256 b = _mm256_unpackhi_ps(x, y); // LRLRLRLR _mm256_store_ps(outputBuffers+i, a); _mm256_store_ps(outputBuffers+8+i, b); } #elif HV_SIMD_SSE for (int i = 0, j = 0; j < n4; j += 4, i += 8) { __m128 x = _mm_load_ps(bOut+j); // LLLL __m128 y = _mm_load_ps(bOut+n4+j); // RRRR __m128 a = _mm_unpacklo_ps(x, y); // LRLR __m128 b = _mm_unpackhi_ps(x, y); // LRLR _mm_store_ps(outputBuffers+i, a); _mm_store_ps(outputBuffers+4+i, b); } #elif HV_SIMD_NEON // https://community.arm.com/groups/processors/blog/2012/03/13/coding-for-neon--part-5-rearranging-vectors for (int i = 0, j = 0; j < n4; j += 4, i += 8) { float32x4_t x = vld1q_f32(bOut+j); float32x4_t y = vld1q_f32(bOut+n4+j); float32x4x2_t z = {x, y}; vst2q_f32(outputBuffers+i, z); // interleave and store } #else // HV_SIMD_NONE for (int i = 0; i < {{signal.numOutputBuffers}}; ++i) { for (int j = 0; j < n4; ++j) { outputBuffers[i+{{signal.numOutputBuffers}}*j] = bOut[i*n4+j]; } } #endif {%- elif signal.numOutputBuffers > 2 %} // interleave the heavy output into the output buffer for (int i = 0; i < {{signal.numOutputBuffers}}; ++i) { for (int j = 0; j < n4; ++j) { outputBuffers[i+{{signal.numOutputBuffers}}*j] = bOut[i*n4+j]; } } {%- endif %} return n; } {# force newline #} ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1739952883.945202 hvcc-0.13.3/hvcc/generators/ir2c/templates/Heavy_NAME.h0000644000000000000000000000477514755311364017453 0ustar00{{copyright}} #ifndef _HEAVY_{{name|upper}}_H_ #define _HEAVY_{{name|upper}}_H_ #include "HvHeavy.h" #ifdef __cplusplus extern "C" { #endif #if HV_APPLE #pragma mark - Heavy Context #endif {% if externs.parameters.inParam|length > 0 -%} typedef enum { {%- for k,v in externs.parameters.inParam %} HV_{{name|upper}}_PARAM_IN_{{k|upper}} = {{v.hash}}, // {{v.display}} {%- endfor %} } Hv_{{name}}_ParameterIn; {% endif -%} {% if externs.parameters.outParam|length > 0 %} typedef enum { {%- for k,v in externs.parameters.outParam %} HV_{{name|upper}}_PARAM_OUT_{{k|upper}} = {{v.hash}}, // {{v.display}} {%- endfor %} } Hv_{{name}}_ParameterOut; {% endif -%} {% if externs.events.inEvent|length > 0 %} typedef enum { {%- for k,v in externs.events.inEvent %} HV_{{name|upper}}_EVENT_IN_{{k|upper}} = {{v.hash}}, // {{v.display}} {%- endfor %} } Hv_{{name}}_EventIn; {% endif -%} {% if externs.events.outEvent|length > 0 %} typedef enum { {%- for k,v in externs.events.outEvent %} HV_{{name|upper}}_EVENT_OUT_{{k|upper}} = {{v.hash}}, // {{v.display}} {%- endfor %} } Hv_{{name}}_EventOut; {% endif -%} {% if externs.tables|length > 0 %} typedef enum { {%- for k,v in externs.tables %} HV_{{name|upper}}_TABLE_{{k|upper}} = {{v.hash}}, // {{v.display}} {%- endfor %} } Hv_{{name}}_Table; {%- endif %} /** * Creates a new patch instance. * Sample rate should be positive and in Hertz, e.g. 44100.0. */ HeavyContextInterface *hv_{{name}}_new(double sampleRate); /** * Creates a new patch instance. * @param sampleRate Sample rate should be positive (> 0) and in Hertz, e.g. 48000.0. * @param poolKb Pool size is in kilobytes, and determines the maximum amount of memory * allocated to messages at any time. By default this is 10 KB. * @param inQueueKb The size of the input message queue in kilobytes. It determines the * amount of memory dedicated to holding scheduled messages between calls to * process(). Default is 2 KB. * @param outQueueKb The size of the output message queue in kilobytes. It determines the * amount of memory dedicated to holding scheduled messages to the default sendHook. * See getNextSentMessage() for info on accessing these messages. Default is 0 KB. */ HeavyContextInterface *hv_{{name}}_new_with_options(double sampleRate, int poolKb, int inQueueKb, int outQueueKb); /** * Free the patch instance. */ void hv_{{name}}_free(HeavyContextInterface *instance); #ifdef __cplusplus } // extern "C" #endif #endif // _HEAVY_{{name|upper}}_H_ {# force a new line #} ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.270823 hvcc-0.13.3/hvcc/generators/ir2c/templates/Heavy_NAME.hpp0000644000000000000000000000533414735300474020001 0ustar00{{copyright}} #ifndef _HEAVY_CONTEXT_{{name|upper}}_HPP_ #define _HEAVY_CONTEXT_{{name|upper}}_HPP_ // object includes #include "HeavyContext.hpp" {%- for i in include_set %} #include "{{i}}" {%- endfor %} class Heavy_{{name}} : public HeavyContext { public: Heavy_{{name}}(double sampleRate, int poolKb=10, int inQueueKb=2, int outQueueKb=0); ~Heavy_{{name}}(); const char *getName() override { return "{{name}}"; } int getNumInputChannels() override { return {{signal.numInputBuffers}}; } int getNumOutputChannels() override { return {{signal.numOutputBuffers}}; } int process(float **inputBuffers, float **outputBuffer, int n) override; int processInline(float *inputBuffers, float *outputBuffer, int n) override; int processInlineInterleaved(float *inputBuffers, float *outputBuffer, int n) override; int getParameterInfo(int index, HvParameterInfo *info) override; {%- if externs.parameters.inParam|length > 0 or externs.parameters.outParam|length > 0 %} struct Parameter { {% if externs.parameters.inParam|length > 0 -%} struct In { enum ParameterIn : hv_uint32_t { {%- for k,v in externs.parameters.inParam %} {{k|upper}} = {{v.hash}}, // {{v.display}} {%- endfor %} }; }; {%- endif %} {%- if externs.parameters.outParam|length > 0 %} struct Out { enum ParameterOut : hv_uint32_t { {%- for k,v in externs.parameters.outParam %} {{k|upper}} = {{v.hash}}, // {{v.display}} {%- endfor %} }; }; {%- endif %} }; {%- endif %} {%- if externs.events.inEvent|length > 0 or externs.events.outEvent|length > 0 %} struct Event { {%- if externs.events.inEvent|length > 0 %} struct In { enum EventIn : hv_uint32_t { {%- for k,v in externs.events.inEvent %} {{k|upper}} = {{v.hash}}, // {{v.display}} {%- endfor %} }; }; {%- endif %} {%- if externs.events.outEvent|length > 0 %} struct Out { enum EventOut : hv_uint32_t { {%- for k,v in externs.events.outEvent %} {{k|upper}} = {{v.hash}}, // {{v.display}} {%- endfor %} }; }; {%- endif %} }; {%- endif %} {%- if externs.tables|length > 0 %} enum Table : hv_uint32_t { {%- for k,v in externs.tables %} {{k|upper}} = {{v.hash}}, // {{v.display}} {%- endfor %} }; {%- endif %} private: HvTable *getTableForHash(hv_uint32_t tableHash) override; void scheduleMessageForReceiver(hv_uint32_t receiverHash, HvMessage *m) override; // static sendMessage functions {%- for d in decl_list %} static void {{d}} {%- endfor %} // objects {%- for d in def_list %} {{d}} {%- endfor %} }; #endif // _HEAVY_CONTEXT_{{name|upper}}_HPP_ {# force newline #} ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/vs2015/Heavy/Heavy.sln0000644000000000000000000000235714435670357016376 0ustar00 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Heavy", "Heavy.vcxproj", "{B1085EE2-C54E-4892-A24D-06B80001DB68}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {B1085EE2-C54E-4892-A24D-06B80001DB68}.Debug|x64.ActiveCfg = Debug|x64 {B1085EE2-C54E-4892-A24D-06B80001DB68}.Debug|x64.Build.0 = Debug|x64 {B1085EE2-C54E-4892-A24D-06B80001DB68}.Debug|x86.ActiveCfg = Debug|Win32 {B1085EE2-C54E-4892-A24D-06B80001DB68}.Debug|x86.Build.0 = Debug|Win32 {B1085EE2-C54E-4892-A24D-06B80001DB68}.Release|x64.ActiveCfg = Release|x64 {B1085EE2-C54E-4892-A24D-06B80001DB68}.Release|x64.Build.0 = Release|x64 {B1085EE2-C54E-4892-A24D-06B80001DB68}.Release|x86.ActiveCfg = Release|Win32 {B1085EE2-C54E-4892-A24D-06B80001DB68}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/vs2015/Heavy/Heavy.vcxproj0000644000000000000000000003132714435670357017274 0ustar00 Debug Win32 Release Win32 Debug x64 Release x64 {B1085EE2-C54E-4892-A24D-06B80001DB68} Win32Proj Heavy 8.1 Application true v140 Unicode Application false v140 true Unicode Application true v140 Unicode Application false v140 true Unicode true true false false Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS Console true python $(SolutionDir)\..\..\..\hvcc.py C:\Users\Joe\Downloads\woosh.iX2jC.pd\_main.pd -o $(SolutionDir)\generated -n heavy Level3 Disabled _DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS Default false StreamingSIMDExtensions2 Console true python $(SolutionDir)..\..\..\hvcc.py C:\Users\enzien\Desktop\test_osc.pd -o $(SolutionDir)\generated -n heavy Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS Console true true true python $(SolutionDir)\..\..\..\hvcc.py C:\Users\Joe\Downloads\woosh.iX2jC.pd\_main.pd -o $(SolutionDir)\generated -n heavy Level3 MaxSpeed true true NDEBUG;_CONSOLE;HV_SIMD_SSE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS Console true true true python $(SolutionDir)..\..\..\hvcc.py C:\Users\enzien\Desktop\test_osc.pd -o $(SolutionDir)\generated -n heavy Default ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/vs2015/Heavy/Heavy.vcxproj.filters0000644000000000000000000002237314435670357020744 0ustar00 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms {0a0854fe-2e4e-4aab-b804-7395e7f2cbbd} {2ff1fc05-5468-4baa-8299-b7b154a49aa2} Header Files Header Files Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Generated Generated Static Source Files Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Static Generated Static Source Files ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/vs2015/Heavy/main.c0000644000000000000000000000473714435670357015700 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include "../../vs2015/Heavy/generated/c/Heavy_heavy.h" void printHook(double timestampMs, const char *name, const char *s, void *userData) { printf("[@ %.3fms] %s: %s\n", timestampMs, name, s); } #define NUM_ITERATIONS 8388600 #define BLOCK_SIZE 512 #define SAMPLE_RATE 48000.0 int main(int argc, const char * argv[]) { Hv_heavy *context = hv_heavy_new(SAMPLE_RATE); hv_setPrintHook(context, &printHook); float *inputBuffers = (float *) malloc(hv_getNumInputChannels(context) * BLOCK_SIZE * sizeof(float)); float *outputBuffers = (float *) malloc(hv_getNumOutputChannels(context) * BLOCK_SIZE * sizeof(float)); uint64_t freq, start, end; QueryPerformanceFrequency((LARGE_INTEGER *) &freq); QueryPerformanceCounter((LARGE_INTEGER *) &start); for (int i = 0; i < NUM_ITERATIONS; ++i) { hv_heavy_process_inline(context, inputBuffers, outputBuffers, BLOCK_SIZE); } QueryPerformanceCounter((LARGE_INTEGER *) &end); const double elapsedTimeUs = 1000.0 * (end - start) / ((double) freq); printf("Executed %i blocks of length %i at a sample rate of %gHz. A total of %i samples were generated.\n", NUM_ITERATIONS, BLOCK_SIZE, SAMPLE_RATE, (int) (NUM_ITERATIONS * BLOCK_SIZE)); printf("Runtime is: %i iterations in %.3f milliseconds\n", NUM_ITERATIONS, elapsedTimeUs); printf(" %f iterations/second.\n", (NUM_ITERATIONS*1000.0)/elapsedTimeUs); printf(" %.6f milliseconds per block.\n", elapsedTimeUs/NUM_ITERATIONS); printf(" %.6f microseconds per block.\n", 1000.0*elapsedTimeUs/NUM_ITERATIONS); printf(" %0.6f%% CPU\n", 100.0*((elapsedTimeUs/1000.0)/NUM_ITERATIONS)/(BLOCK_SIZE/SAMPLE_RATE)); free(inputBuffers); free(outputBuffers); hv_heavy_free(context); Sleep(10000); return 0; } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/vs2015/Heavy/stdafx.cpp0000644000000000000000000000043414435670357016573 0ustar00// stdafx.cpp : source file that includes just the standard includes // Heavy.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "stdafx.h" // TODO: reference any additional headers you need in STDAFX.H // and not in this file ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/vs2015/Heavy/stdafx.h0000644000000000000000000000046114435670357016240 0ustar00// stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // #pragma once #include "targetver.h" #include #include // TODO: reference additional headers your program requires here ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/vs2015/Heavy/targetver.h0000644000000000000000000000046214435670357016753 0ustar00#pragma once // Including SDKDDKVer.h defines the highest available Windows platform. // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. #include ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/xcode/Heavy/main.c0000644000000000000000000000467414435670357016042 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include "cpuid.h" #include "Heavy_heavy.h" void printHook(HeavyContextInterface *c, const char *name, const char *s, const HvMessage *m) { printf("[@ %.3f] %s: %s\n", hv_samplesToMilliseconds(c, hv_msg_getTimestamp(m)), name, s); } #define NUM_ITERATIONS 100000000 // 8388600 #define BLOCK_SIZE 512 #define SAMPLE_RATE 48000.0 int main(int argc, const char * argv[]) { cpuid_print_exts(); HeavyContextInterface *context = hv_heavy_new(SAMPLE_RATE); hv_setPrintHook(context, &printHook); float *inputBuffers = (float *) malloc(hv_getNumInputChannels(context) * BLOCK_SIZE * sizeof(float)); float *outputBuffers = (float *) malloc(hv_getNumOutputChannels(context) * BLOCK_SIZE * sizeof(float)); mach_timebase_info_data_t sTimebaseInfo; mach_timebase_info(&sTimebaseInfo); uint64_t start = mach_absolute_time(); for (int i = 0; i < NUM_ITERATIONS; ++i) { hv_processInline(context, inputBuffers, outputBuffers, BLOCK_SIZE); } uint64_t end = mach_absolute_time(); uint64_t elapsedTimeNs = (end - start) * sTimebaseInfo.numer / sTimebaseInfo.denom; printf("Executed %i blocks of length %i at a sample rate of %gHz. A total of %llu samples were generated.\n", NUM_ITERATIONS, BLOCK_SIZE, SAMPLE_RATE, (1LLU*NUM_ITERATIONS) * BLOCK_SIZE); printf("Runtime is: %i iterations in %.3f seconds\n", NUM_ITERATIONS, elapsedTimeNs/1000000000.0); printf(" %f iterations/second.\n", (NUM_ITERATIONS*1000000000.0)/elapsedTimeNs); printf(" %.3f nanoseconds/block.\n", (1.0*elapsedTimeNs)/NUM_ITERATIONS); printf(" %0.6f%% CPU\n", 100.0*((elapsedTimeNs/1000000000.0)/NUM_ITERATIONS)/(BLOCK_SIZE/SAMPLE_RATE)); free(inputBuffers); free(outputBuffers); hv_delete(context); return 0; } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/xcode/Heavy.xcodeproj/project.pbxproj0000644000000000000000000023672114435670357022022 0ustar00// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 900D618A1AD9EFAD001BDB71 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 900D61891AD9EFAD001BDB71 /* Accelerate.framework */; }; 900D618C1AD9F2AE001BDB71 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 900D618B1AD9F2AE001BDB71 /* AVFoundation.framework */; }; 9036C1B01AD57CDF00C7B994 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9036C1AF1AD57CDF00C7B994 /* main.m */; }; 9036C1B31AD57CDF00C7B994 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9036C1B21AD57CDF00C7B994 /* AppDelegate.m */; }; 9036C1B61AD57CDF00C7B994 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9036C1B51AD57CDF00C7B994 /* ViewController.m */; }; 9036C1B91AD57CDF00C7B994 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9036C1B71AD57CDF00C7B994 /* Main.storyboard */; }; 9036C1BB1AD57CDF00C7B994 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9036C1BA1AD57CDF00C7B994 /* Images.xcassets */; }; 9036C1BE1AD57CDF00C7B994 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9036C1BC1AD57CDF00C7B994 /* LaunchScreen.xib */; }; 9036C1D51AD58B3A00C7B994 /* TPCircularBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 9036C1D11AD58B3A00C7B994 /* TPCircularBuffer.c */; }; 9036C1D91AD58B9B00C7B994 /* HeavyAudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 9036C1D81AD58B9B00C7B994 /* HeavyAudio.m */; }; 9059F9271BECEE5100589DE5 /* tinywav.c in Sources */ = {isa = PBXBuildFile; fileRef = 9059F9251BECEE5100589DE5 /* tinywav.c */; }; 906644F61E5E43F7007F4762 /* HvUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 906644F51E5E43F7007F4762 /* HvUtils.c */; }; 906644F71E5E43F7007F4762 /* HvUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 906644F51E5E43F7007F4762 /* HvUtils.c */; }; 906644F81E5E43F7007F4762 /* HvUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 906644F51E5E43F7007F4762 /* HvUtils.c */; }; 90AA59441A63407400F3B66E /* cpuid.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA590B1A63407400F3B66E /* cpuid.c */; }; 90B848C41D95C8E60004BCE3 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 90B848C31D95C8E60004BCE3 /* AudioUnit.framework */; }; 90B848C61D95C8EB0004BCE3 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 90B848C51D95C8EB0004BCE3 /* Accelerate.framework */; }; 90B848D01D95CA310004BCE3 /* HvHeavy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FBA0431D573C86002E49ED /* HvHeavy.cpp */; }; 90B848D11D95CA310004BCE3 /* HeavyContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FBA0451D573C86002E49ED /* HeavyContext.cpp */; }; 90B848D21D95CA310004BCE3 /* HvControlBinop.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58F71A63407400F3B66E /* HvControlBinop.c */; }; 90B848D31D95CA310004BCE3 /* HvControlCast.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58F91A63407400F3B66E /* HvControlCast.c */; }; 90B848D41D95CA310004BCE3 /* HvControlDelay.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58FB1A63407400F3B66E /* HvControlDelay.c */; }; 90B848D51D95CA310004BCE3 /* HvControlIf.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58FD1A63407400F3B66E /* HvControlIf.c */; }; 90B848D61D95CA310004BCE3 /* HvControlPack.c in Sources */ = {isa = PBXBuildFile; fileRef = D8A281EA1AEFC765004F8531 /* HvControlPack.c */; }; 90B848D71D95CA310004BCE3 /* HvControlPrint.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58FF1A63407400F3B66E /* HvControlPrint.c */; }; 90B848D81D95CA310004BCE3 /* HvControlRandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59011A63407400F3B66E /* HvControlRandom.c */; }; 90B848D91D95CA310004BCE3 /* HvControlSlice.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59031A63407400F3B66E /* HvControlSlice.c */; }; 90B848DA1D95CA310004BCE3 /* HvControlSystem.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59051A63407400F3B66E /* HvControlSystem.c */; }; 90B848DB1D95CA310004BCE3 /* HvControlTabhead.c in Sources */ = {isa = PBXBuildFile; fileRef = 90226C171A9F8DAD005D8253 /* HvControlTabhead.c */; }; 90B848DC1D95CA310004BCE3 /* HvControlTabread.c in Sources */ = {isa = PBXBuildFile; fileRef = 906FAB781AEF85C000B9F165 /* HvControlTabread.c */; }; 90B848DD1D95CA310004BCE3 /* HvControlTabwrite.c in Sources */ = {isa = PBXBuildFile; fileRef = 906FAB7D1AEF895E00B9F165 /* HvControlTabwrite.c */; }; 90B848DE1D95CA310004BCE3 /* HvControlUnop.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59071A63407400F3B66E /* HvControlUnop.c */; }; 90B848DF1D95CA310004BCE3 /* HvControlVar.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59091A63407400F3B66E /* HvControlVar.c */; }; 90B848E01D95CA310004BCE3 /* HvLightPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = 9088F1B81CB36DA600569945 /* HvLightPipe.c */; }; 90B848E11D95CA310004BCE3 /* HvMessage.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59111A63407400F3B66E /* HvMessage.c */; }; 90B848E21D95CA310004BCE3 /* HvTable.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59131A63407400F3B66E /* HvTable.c */; }; 90B848E31D95CA310004BCE3 /* HvMessagePool.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59151A63407400F3B66E /* HvMessagePool.c */; }; 90B848E41D95CA310004BCE3 /* HvMessageQueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59171A63407400F3B66E /* HvMessageQueue.c */; }; 90B848E51D95CA310004BCE3 /* HvSignalBiquad.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59191A63407400F3B66E /* HvSignalBiquad.c */; }; 90B848E61D95CA310004BCE3 /* HvSignalConvolution.c in Sources */ = {isa = PBXBuildFile; fileRef = 90D200C01BC2AB6400E45A9D /* HvSignalConvolution.c */; }; 90B848E71D95CA310004BCE3 /* HvSignalCPole.c in Sources */ = {isa = PBXBuildFile; fileRef = D89405DA1BE19A8300491551 /* HvSignalCPole.c */; }; 90B848E81D95CA310004BCE3 /* HvSignalDel1.c in Sources */ = {isa = PBXBuildFile; fileRef = D8500AD81BD9B9D400D12C3A /* HvSignalDel1.c */; }; 90B848E91D95CA310004BCE3 /* HvSignalEnvelope.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA591B1A63407400F3B66E /* HvSignalEnvelope.c */; }; 90B848EA1D95CA310004BCE3 /* HvSignalLine.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA591D1A63407400F3B66E /* HvSignalLine.c */; }; 90B848EB1D95CA310004BCE3 /* HvSignalLorenz.c in Sources */ = {isa = PBXBuildFile; fileRef = D88AD8F91C5EEFEC000AC60F /* HvSignalLorenz.c */; }; 90B848EC1D95CA310004BCE3 /* HvSignalPhasor.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA591F1A63407400F3B66E /* HvSignalPhasor.c */; }; 90B848ED1D95CA310004BCE3 /* HvSignalRPole.c in Sources */ = {isa = PBXBuildFile; fileRef = 9015F0C51BDDB25300070222 /* HvSignalRPole.c */; }; 90B848EE1D95CA310004BCE3 /* HvSignalSamphold.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AC14541BD51F67006C126E /* HvSignalSamphold.c */; }; 90B848EF1D95CA310004BCE3 /* HvSignalSample.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59211A63407400F3B66E /* HvSignalSample.c */; }; 90B848F01D95CA310004BCE3 /* HvSignalTabread.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59231A63407400F3B66E /* HvSignalTabread.c */; }; 90B848F11D95CA310004BCE3 /* HvSignalTabwrite.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59251A63407400F3B66E /* HvSignalTabwrite.c */; }; 90B848F21D95CA310004BCE3 /* HvSignalVar.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59271A63407400F3B66E /* HvSignalVar.c */; }; 90B848F31D95CA320004BCE3 /* HvHeavy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FBA0431D573C86002E49ED /* HvHeavy.cpp */; }; 90B848F41D95CA320004BCE3 /* HeavyContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FBA0451D573C86002E49ED /* HeavyContext.cpp */; }; 90B848F51D95CA320004BCE3 /* HvControlBinop.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58F71A63407400F3B66E /* HvControlBinop.c */; }; 90B848F61D95CA320004BCE3 /* HvControlCast.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58F91A63407400F3B66E /* HvControlCast.c */; }; 90B848F71D95CA320004BCE3 /* HvControlDelay.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58FB1A63407400F3B66E /* HvControlDelay.c */; }; 90B848F81D95CA320004BCE3 /* HvControlIf.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58FD1A63407400F3B66E /* HvControlIf.c */; }; 90B848F91D95CA320004BCE3 /* HvControlPack.c in Sources */ = {isa = PBXBuildFile; fileRef = D8A281EA1AEFC765004F8531 /* HvControlPack.c */; }; 90B848FA1D95CA320004BCE3 /* HvControlPrint.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58FF1A63407400F3B66E /* HvControlPrint.c */; }; 90B848FB1D95CA320004BCE3 /* HvControlRandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59011A63407400F3B66E /* HvControlRandom.c */; }; 90B848FC1D95CA320004BCE3 /* HvControlSlice.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59031A63407400F3B66E /* HvControlSlice.c */; }; 90B848FD1D95CA320004BCE3 /* HvControlSystem.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59051A63407400F3B66E /* HvControlSystem.c */; }; 90B848FE1D95CA320004BCE3 /* HvControlTabhead.c in Sources */ = {isa = PBXBuildFile; fileRef = 90226C171A9F8DAD005D8253 /* HvControlTabhead.c */; }; 90B848FF1D95CA320004BCE3 /* HvControlTabread.c in Sources */ = {isa = PBXBuildFile; fileRef = 906FAB781AEF85C000B9F165 /* HvControlTabread.c */; }; 90B849001D95CA320004BCE3 /* HvControlTabwrite.c in Sources */ = {isa = PBXBuildFile; fileRef = 906FAB7D1AEF895E00B9F165 /* HvControlTabwrite.c */; }; 90B849011D95CA320004BCE3 /* HvControlUnop.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59071A63407400F3B66E /* HvControlUnop.c */; }; 90B849021D95CA320004BCE3 /* HvControlVar.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59091A63407400F3B66E /* HvControlVar.c */; }; 90B849031D95CA320004BCE3 /* HvLightPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = 9088F1B81CB36DA600569945 /* HvLightPipe.c */; }; 90B849041D95CA320004BCE3 /* HvMessage.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59111A63407400F3B66E /* HvMessage.c */; }; 90B849051D95CA320004BCE3 /* HvTable.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59131A63407400F3B66E /* HvTable.c */; }; 90B849061D95CA320004BCE3 /* HvMessagePool.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59151A63407400F3B66E /* HvMessagePool.c */; }; 90B849071D95CA320004BCE3 /* HvMessageQueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59171A63407400F3B66E /* HvMessageQueue.c */; }; 90B849081D95CA320004BCE3 /* HvSignalBiquad.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59191A63407400F3B66E /* HvSignalBiquad.c */; }; 90B849091D95CA320004BCE3 /* HvSignalConvolution.c in Sources */ = {isa = PBXBuildFile; fileRef = 90D200C01BC2AB6400E45A9D /* HvSignalConvolution.c */; }; 90B8490A1D95CA320004BCE3 /* HvSignalCPole.c in Sources */ = {isa = PBXBuildFile; fileRef = D89405DA1BE19A8300491551 /* HvSignalCPole.c */; }; 90B8490B1D95CA320004BCE3 /* HvSignalDel1.c in Sources */ = {isa = PBXBuildFile; fileRef = D8500AD81BD9B9D400D12C3A /* HvSignalDel1.c */; }; 90B8490C1D95CA320004BCE3 /* HvSignalEnvelope.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA591B1A63407400F3B66E /* HvSignalEnvelope.c */; }; 90B8490D1D95CA320004BCE3 /* HvSignalLine.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA591D1A63407400F3B66E /* HvSignalLine.c */; }; 90B8490E1D95CA320004BCE3 /* HvSignalLorenz.c in Sources */ = {isa = PBXBuildFile; fileRef = D88AD8F91C5EEFEC000AC60F /* HvSignalLorenz.c */; }; 90B8490F1D95CA320004BCE3 /* HvSignalPhasor.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA591F1A63407400F3B66E /* HvSignalPhasor.c */; }; 90B849101D95CA320004BCE3 /* HvSignalRPole.c in Sources */ = {isa = PBXBuildFile; fileRef = 9015F0C51BDDB25300070222 /* HvSignalRPole.c */; }; 90B849111D95CA320004BCE3 /* HvSignalSamphold.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AC14541BD51F67006C126E /* HvSignalSamphold.c */; }; 90B849121D95CA320004BCE3 /* HvSignalSample.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59211A63407400F3B66E /* HvSignalSample.c */; }; 90B849131D95CA320004BCE3 /* HvSignalTabread.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59231A63407400F3B66E /* HvSignalTabread.c */; }; 90B849141D95CA320004BCE3 /* HvSignalTabwrite.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59251A63407400F3B66E /* HvSignalTabwrite.c */; }; 90B849151D95CA320004BCE3 /* HvSignalVar.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59271A63407400F3B66E /* HvSignalVar.c */; }; 90B849161D95CA320004BCE3 /* HvHeavy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FBA0431D573C86002E49ED /* HvHeavy.cpp */; }; 90B849171D95CA320004BCE3 /* HeavyContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FBA0451D573C86002E49ED /* HeavyContext.cpp */; }; 90B849181D95CA320004BCE3 /* HvControlBinop.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58F71A63407400F3B66E /* HvControlBinop.c */; }; 90B849191D95CA320004BCE3 /* HvControlCast.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58F91A63407400F3B66E /* HvControlCast.c */; }; 90B8491A1D95CA320004BCE3 /* HvControlDelay.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58FB1A63407400F3B66E /* HvControlDelay.c */; }; 90B8491B1D95CA320004BCE3 /* HvControlIf.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58FD1A63407400F3B66E /* HvControlIf.c */; }; 90B8491C1D95CA320004BCE3 /* HvControlPack.c in Sources */ = {isa = PBXBuildFile; fileRef = D8A281EA1AEFC765004F8531 /* HvControlPack.c */; }; 90B8491D1D95CA320004BCE3 /* HvControlPrint.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA58FF1A63407400F3B66E /* HvControlPrint.c */; }; 90B8491E1D95CA320004BCE3 /* HvControlRandom.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59011A63407400F3B66E /* HvControlRandom.c */; }; 90B8491F1D95CA320004BCE3 /* HvControlSlice.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59031A63407400F3B66E /* HvControlSlice.c */; }; 90B849201D95CA320004BCE3 /* HvControlSystem.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59051A63407400F3B66E /* HvControlSystem.c */; }; 90B849211D95CA320004BCE3 /* HvControlTabhead.c in Sources */ = {isa = PBXBuildFile; fileRef = 90226C171A9F8DAD005D8253 /* HvControlTabhead.c */; }; 90B849221D95CA320004BCE3 /* HvControlTabread.c in Sources */ = {isa = PBXBuildFile; fileRef = 906FAB781AEF85C000B9F165 /* HvControlTabread.c */; }; 90B849231D95CA320004BCE3 /* HvControlTabwrite.c in Sources */ = {isa = PBXBuildFile; fileRef = 906FAB7D1AEF895E00B9F165 /* HvControlTabwrite.c */; }; 90B849241D95CA320004BCE3 /* HvControlUnop.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59071A63407400F3B66E /* HvControlUnop.c */; }; 90B849251D95CA320004BCE3 /* HvControlVar.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59091A63407400F3B66E /* HvControlVar.c */; }; 90B849261D95CA320004BCE3 /* HvLightPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = 9088F1B81CB36DA600569945 /* HvLightPipe.c */; }; 90B849271D95CA320004BCE3 /* HvMessage.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59111A63407400F3B66E /* HvMessage.c */; }; 90B849281D95CA320004BCE3 /* HvTable.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59131A63407400F3B66E /* HvTable.c */; }; 90B849291D95CA320004BCE3 /* HvMessagePool.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59151A63407400F3B66E /* HvMessagePool.c */; }; 90B8492A1D95CA320004BCE3 /* HvMessageQueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59171A63407400F3B66E /* HvMessageQueue.c */; }; 90B8492B1D95CA320004BCE3 /* HvSignalBiquad.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59191A63407400F3B66E /* HvSignalBiquad.c */; }; 90B8492C1D95CA320004BCE3 /* HvSignalConvolution.c in Sources */ = {isa = PBXBuildFile; fileRef = 90D200C01BC2AB6400E45A9D /* HvSignalConvolution.c */; }; 90B8492D1D95CA320004BCE3 /* HvSignalCPole.c in Sources */ = {isa = PBXBuildFile; fileRef = D89405DA1BE19A8300491551 /* HvSignalCPole.c */; }; 90B8492E1D95CA320004BCE3 /* HvSignalDel1.c in Sources */ = {isa = PBXBuildFile; fileRef = D8500AD81BD9B9D400D12C3A /* HvSignalDel1.c */; }; 90B8492F1D95CA320004BCE3 /* HvSignalEnvelope.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA591B1A63407400F3B66E /* HvSignalEnvelope.c */; }; 90B849301D95CA320004BCE3 /* HvSignalLine.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA591D1A63407400F3B66E /* HvSignalLine.c */; }; 90B849311D95CA320004BCE3 /* HvSignalLorenz.c in Sources */ = {isa = PBXBuildFile; fileRef = D88AD8F91C5EEFEC000AC60F /* HvSignalLorenz.c */; }; 90B849321D95CA320004BCE3 /* HvSignalPhasor.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA591F1A63407400F3B66E /* HvSignalPhasor.c */; }; 90B849331D95CA320004BCE3 /* HvSignalRPole.c in Sources */ = {isa = PBXBuildFile; fileRef = 9015F0C51BDDB25300070222 /* HvSignalRPole.c */; }; 90B849341D95CA320004BCE3 /* HvSignalSamphold.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AC14541BD51F67006C126E /* HvSignalSamphold.c */; }; 90B849351D95CA320004BCE3 /* HvSignalSample.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59211A63407400F3B66E /* HvSignalSample.c */; }; 90B849361D95CA320004BCE3 /* HvSignalTabread.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59231A63407400F3B66E /* HvSignalTabread.c */; }; 90B849371D95CA320004BCE3 /* HvSignalTabwrite.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59251A63407400F3B66E /* HvSignalTabwrite.c */; }; 90B849381D95CA320004BCE3 /* HvSignalVar.c in Sources */ = {isa = PBXBuildFile; fileRef = 90AA59271A63407400F3B66E /* HvSignalVar.c */; }; 90B849391D95CAA80004BCE3 /* Heavy_heavy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FBA04A1D573D0F002E49ED /* Heavy_heavy.cpp */; }; 90B8493A1D95CAA90004BCE3 /* Heavy_heavy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FBA04A1D573D0F002E49ED /* Heavy_heavy.cpp */; }; 90FBA04E1D573DD3002E49ED /* Heavy_heavy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FBA04A1D573D0F002E49ED /* Heavy_heavy.cpp */; }; D827FD591DF5BBB300FFB63E /* AudioEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = D827FD581DF5BBB300FFB63E /* AudioEngine.m */; }; D84C615119D1038F00D01F59 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D84C615019D1038F00D01F59 /* Cocoa.framework */; }; D84C615B19D1038F00D01F59 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D84C615919D1038F00D01F59 /* InfoPlist.strings */; }; D84C615D19D1038F00D01F59 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D84C615C19D1038F00D01F59 /* main.m */; }; D84C616119D1038F00D01F59 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = D84C615F19D1038F00D01F59 /* Credits.rtf */; }; D84C616419D1038F00D01F59 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D84C616319D1038F00D01F59 /* AppDelegate.m */; }; D84C616719D1038F00D01F59 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D84C616519D1038F00D01F59 /* MainMenu.xib */; }; D84C616919D1038F00D01F59 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D84C616819D1038F00D01F59 /* Images.xcassets */; }; D84C618519D1042000D01F59 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D84C618319D1042000D01F59 /* MainViewController.m */; }; D84C618619D1042000D01F59 /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D84C618419D1042000D01F59 /* MainViewController.xib */; }; D8B4BE64198BC76B00987698 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = D8B4BE63198BC76B00987698 /* main.c */; }; D8B4BE66198BC76B00987698 /* Heavy.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = D8B4BE65198BC76B00987698 /* Heavy.1 */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ D8B4BE5E198BC76B00987698 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( D8B4BE66198BC76B00987698 /* Heavy.1 in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 900D61891AD9EFAD001BDB71 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk/System/Library/Frameworks/Accelerate.framework; sourceTree = DEVELOPER_DIR; }; 900D618B1AD9F2AE001BDB71 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk/System/Library/Frameworks/AVFoundation.framework; sourceTree = DEVELOPER_DIR; }; 9015F0C51BDDB25300070222 /* HvSignalRPole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalRPole.c; path = ../ir2c/static/HvSignalRPole.c; sourceTree = ""; }; 9015F0C61BDDB25300070222 /* HvSignalRPole.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalRPole.h; path = ../ir2c/static/HvSignalRPole.h; sourceTree = ""; }; 90226C171A9F8DAD005D8253 /* HvControlTabhead.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlTabhead.c; path = ../ir2c/static/HvControlTabhead.c; sourceTree = ""; }; 90226C181A9F8DAD005D8253 /* HvControlTabhead.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlTabhead.h; path = ../ir2c/static/HvControlTabhead.h; sourceTree = ""; }; 9036C1AB1AD57CDF00C7B994 /* Heavy_iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Heavy_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; 9036C1AE1AD57CDF00C7B994 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9036C1AF1AD57CDF00C7B994 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 9036C1B11AD57CDF00C7B994 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 9036C1B21AD57CDF00C7B994 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 9036C1B41AD57CDF00C7B994 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 9036C1B51AD57CDF00C7B994 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 9036C1B81AD57CDF00C7B994 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 9036C1BA1AD57CDF00C7B994 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 9036C1BD1AD57CDF00C7B994 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 9036C1D11AD58B3A00C7B994 /* TPCircularBuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = TPCircularBuffer.c; sourceTree = ""; }; 9036C1D21AD58B3A00C7B994 /* TPCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPCircularBuffer.h; sourceTree = ""; }; 9036C1D71AD58B9B00C7B994 /* HeavyAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeavyAudio.h; sourceTree = ""; }; 9036C1D81AD58B9B00C7B994 /* HeavyAudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HeavyAudio.m; sourceTree = ""; }; 905185D51D9E5BF20001CB5F /* HeavyContextInterface.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = HeavyContextInterface.hpp; path = ../ir2c/static/HeavyContextInterface.hpp; sourceTree = ""; }; 9053E1181D95519300D3B881 /* Heavy_heavy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Heavy_heavy.h; path = build/c/Heavy_heavy.h; sourceTree = ""; }; 9053E1191D95519300D3B881 /* Heavy_heavy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Heavy_heavy.hpp; path = build/c/Heavy_heavy.hpp; sourceTree = ""; }; 9053E11A1D95531C00D3B881 /* HeavyContext.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = HeavyContext.hpp; path = ../ir2c/static/HeavyContext.hpp; sourceTree = ""; }; 9053E11C1D9555C600D3B881 /* HvHeavyInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvHeavyInternal.h; path = ../ir2c/static/HvHeavyInternal.h; sourceTree = ""; }; 9053E11D1D95565000D3B881 /* Heavy_NAME.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Heavy_NAME.hpp; sourceTree = ""; }; 9059F9251BECEE5100589DE5 /* tinywav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tinywav.c; path = tinywav/tinywav.c; sourceTree = ""; }; 9059F9261BECEE5100589DE5 /* tinywav.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tinywav.h; path = tinywav/tinywav.h; sourceTree = ""; }; 906644F51E5E43F7007F4762 /* HvUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvUtils.c; path = ../ir2c/static/HvUtils.c; sourceTree = ""; }; 906FAB781AEF85C000B9F165 /* HvControlTabread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlTabread.c; path = ../ir2c/static/HvControlTabread.c; sourceTree = ""; }; 906FAB791AEF85C000B9F165 /* HvControlTabread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlTabread.h; path = ../ir2c/static/HvControlTabread.h; sourceTree = ""; }; 906FAB7D1AEF895E00B9F165 /* HvControlTabwrite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlTabwrite.c; path = ../ir2c/static/HvControlTabwrite.c; sourceTree = ""; }; 906FAB7E1AEF895E00B9F165 /* HvControlTabwrite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlTabwrite.h; path = ../ir2c/static/HvControlTabwrite.h; sourceTree = ""; }; 9088F1B81CB36DA600569945 /* HvLightPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvLightPipe.c; path = ../ir2c/static/HvLightPipe.c; sourceTree = ""; }; 9088F1B91CB36DA600569945 /* HvLightPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvLightPipe.h; path = ../ir2c/static/HvLightPipe.h; sourceTree = ""; }; 90AA58F71A63407400F3B66E /* HvControlBinop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlBinop.c; path = ../ir2c/static/HvControlBinop.c; sourceTree = ""; }; 90AA58F81A63407400F3B66E /* HvControlBinop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlBinop.h; path = ../ir2c/static/HvControlBinop.h; sourceTree = ""; }; 90AA58F91A63407400F3B66E /* HvControlCast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlCast.c; path = ../ir2c/static/HvControlCast.c; sourceTree = ""; }; 90AA58FA1A63407400F3B66E /* HvControlCast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlCast.h; path = ../ir2c/static/HvControlCast.h; sourceTree = ""; }; 90AA58FB1A63407400F3B66E /* HvControlDelay.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlDelay.c; path = ../ir2c/static/HvControlDelay.c; sourceTree = ""; }; 90AA58FC1A63407400F3B66E /* HvControlDelay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlDelay.h; path = ../ir2c/static/HvControlDelay.h; sourceTree = ""; }; 90AA58FD1A63407400F3B66E /* HvControlIf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlIf.c; path = ../ir2c/static/HvControlIf.c; sourceTree = ""; }; 90AA58FE1A63407400F3B66E /* HvControlIf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlIf.h; path = ../ir2c/static/HvControlIf.h; sourceTree = ""; }; 90AA58FF1A63407400F3B66E /* HvControlPrint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlPrint.c; path = ../ir2c/static/HvControlPrint.c; sourceTree = ""; }; 90AA59001A63407400F3B66E /* HvControlPrint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlPrint.h; path = ../ir2c/static/HvControlPrint.h; sourceTree = ""; }; 90AA59011A63407400F3B66E /* HvControlRandom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlRandom.c; path = ../ir2c/static/HvControlRandom.c; sourceTree = ""; }; 90AA59021A63407400F3B66E /* HvControlRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlRandom.h; path = ../ir2c/static/HvControlRandom.h; sourceTree = ""; }; 90AA59031A63407400F3B66E /* HvControlSlice.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlSlice.c; path = ../ir2c/static/HvControlSlice.c; sourceTree = ""; }; 90AA59041A63407400F3B66E /* HvControlSlice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlSlice.h; path = ../ir2c/static/HvControlSlice.h; sourceTree = ""; }; 90AA59051A63407400F3B66E /* HvControlSystem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlSystem.c; path = ../ir2c/static/HvControlSystem.c; sourceTree = ""; }; 90AA59061A63407400F3B66E /* HvControlSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlSystem.h; path = ../ir2c/static/HvControlSystem.h; sourceTree = ""; }; 90AA59071A63407400F3B66E /* HvControlUnop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlUnop.c; path = ../ir2c/static/HvControlUnop.c; sourceTree = ""; }; 90AA59081A63407400F3B66E /* HvControlUnop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlUnop.h; path = ../ir2c/static/HvControlUnop.h; sourceTree = ""; }; 90AA59091A63407400F3B66E /* HvControlVar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlVar.c; path = ../ir2c/static/HvControlVar.c; sourceTree = ""; }; 90AA590A1A63407400F3B66E /* HvControlVar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlVar.h; path = ../ir2c/static/HvControlVar.h; sourceTree = ""; }; 90AA590B1A63407400F3B66E /* cpuid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cpuid.c; path = ../ir2c/static/cpuid.c; sourceTree = ""; }; 90AA590C1A63407400F3B66E /* cpuid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cpuid.h; path = ../ir2c/static/cpuid.h; sourceTree = ""; }; 90AA590E1A63407400F3B66E /* HvMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvMath.h; path = ../ir2c/static/HvMath.h; sourceTree = ""; }; 90AA59111A63407400F3B66E /* HvMessage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvMessage.c; path = ../ir2c/static/HvMessage.c; sourceTree = ""; }; 90AA59121A63407400F3B66E /* HvMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvMessage.h; path = ../ir2c/static/HvMessage.h; sourceTree = ""; }; 90AA59131A63407400F3B66E /* HvTable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvTable.c; path = ../ir2c/static/HvTable.c; sourceTree = ""; }; 90AA59141A63407400F3B66E /* HvTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvTable.h; path = ../ir2c/static/HvTable.h; sourceTree = ""; }; 90AA59151A63407400F3B66E /* HvMessagePool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvMessagePool.c; path = ../ir2c/static/HvMessagePool.c; sourceTree = ""; }; 90AA59161A63407400F3B66E /* HvMessagePool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvMessagePool.h; path = ../ir2c/static/HvMessagePool.h; sourceTree = ""; }; 90AA59171A63407400F3B66E /* HvMessageQueue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvMessageQueue.c; path = ../ir2c/static/HvMessageQueue.c; sourceTree = ""; }; 90AA59181A63407400F3B66E /* HvMessageQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvMessageQueue.h; path = ../ir2c/static/HvMessageQueue.h; sourceTree = ""; }; 90AA59191A63407400F3B66E /* HvSignalBiquad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalBiquad.c; path = ../ir2c/static/HvSignalBiquad.c; sourceTree = ""; }; 90AA591A1A63407400F3B66E /* HvSignalBiquad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalBiquad.h; path = ../ir2c/static/HvSignalBiquad.h; sourceTree = ""; }; 90AA591B1A63407400F3B66E /* HvSignalEnvelope.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalEnvelope.c; path = ../ir2c/static/HvSignalEnvelope.c; sourceTree = ""; }; 90AA591C1A63407400F3B66E /* HvSignalEnvelope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalEnvelope.h; path = ../ir2c/static/HvSignalEnvelope.h; sourceTree = ""; }; 90AA591D1A63407400F3B66E /* HvSignalLine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalLine.c; path = ../ir2c/static/HvSignalLine.c; sourceTree = ""; }; 90AA591E1A63407400F3B66E /* HvSignalLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalLine.h; path = ../ir2c/static/HvSignalLine.h; sourceTree = ""; }; 90AA591F1A63407400F3B66E /* HvSignalPhasor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalPhasor.c; path = ../ir2c/static/HvSignalPhasor.c; sourceTree = ""; }; 90AA59201A63407400F3B66E /* HvSignalPhasor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalPhasor.h; path = ../ir2c/static/HvSignalPhasor.h; sourceTree = ""; }; 90AA59211A63407400F3B66E /* HvSignalSample.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalSample.c; path = ../ir2c/static/HvSignalSample.c; sourceTree = ""; }; 90AA59221A63407400F3B66E /* HvSignalSample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalSample.h; path = ../ir2c/static/HvSignalSample.h; sourceTree = ""; }; 90AA59231A63407400F3B66E /* HvSignalTabread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalTabread.c; path = ../ir2c/static/HvSignalTabread.c; sourceTree = ""; }; 90AA59241A63407400F3B66E /* HvSignalTabread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalTabread.h; path = ../ir2c/static/HvSignalTabread.h; sourceTree = ""; }; 90AA59251A63407400F3B66E /* HvSignalTabwrite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalTabwrite.c; path = ../ir2c/static/HvSignalTabwrite.c; sourceTree = ""; }; 90AA59261A63407400F3B66E /* HvSignalTabwrite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalTabwrite.h; path = ../ir2c/static/HvSignalTabwrite.h; sourceTree = ""; }; 90AA59271A63407400F3B66E /* HvSignalVar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalVar.c; path = ../ir2c/static/HvSignalVar.c; sourceTree = ""; }; 90AA59281A63407400F3B66E /* HvSignalVar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalVar.h; path = ../ir2c/static/HvSignalVar.h; sourceTree = ""; }; 90AA592F1A63407400F3B66E /* HvUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvUtils.h; path = ../ir2c/static/HvUtils.h; sourceTree = ""; }; 90AC14541BD51F67006C126E /* HvSignalSamphold.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalSamphold.c; path = ../ir2c/static/HvSignalSamphold.c; sourceTree = ""; }; 90AC14551BD51F67006C126E /* HvSignalSamphold.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalSamphold.h; path = ../ir2c/static/HvSignalSamphold.h; sourceTree = ""; }; 90B848C31D95C8E60004BCE3 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; }; 90B848C51D95C8EB0004BCE3 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; 90D200C01BC2AB6400E45A9D /* HvSignalConvolution.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalConvolution.c; path = ../ir2c/static/HvSignalConvolution.c; sourceTree = ""; }; 90D200C11BC2AB6400E45A9D /* HvSignalConvolution.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalConvolution.h; path = ../ir2c/static/HvSignalConvolution.h; sourceTree = ""; }; 90FBA03E1D573C63002E49ED /* Heavy_NAME.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Heavy_NAME.cpp; sourceTree = ""; }; 90FBA03F1D573C63002E49ED /* Heavy_NAME.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Heavy_NAME.h; sourceTree = ""; }; 90FBA0431D573C86002E49ED /* HvHeavy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HvHeavy.cpp; path = ../ir2c/static/HvHeavy.cpp; sourceTree = ""; }; 90FBA0441D573C86002E49ED /* HvHeavy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvHeavy.h; path = ../ir2c/static/HvHeavy.h; sourceTree = ""; }; 90FBA0451D573C86002E49ED /* HeavyContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HeavyContext.cpp; path = ../ir2c/static/HeavyContext.cpp; sourceTree = ""; }; 90FBA04A1D573D0F002E49ED /* Heavy_heavy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Heavy_heavy.cpp; path = build/c/Heavy_heavy.cpp; sourceTree = ""; }; D827FD581DF5BBB300FFB63E /* AudioEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioEngine.m; sourceTree = ""; }; D84C614E19D1038F00D01F59 /* Heavy_OSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Heavy_OSX.app; sourceTree = BUILT_PRODUCTS_DIR; }; D84C615019D1038F00D01F59 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; D84C615319D1038F00D01F59 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; D84C615419D1038F00D01F59 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; D84C615519D1038F00D01F59 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; D84C615819D1038F00D01F59 /* Heavy_OSX-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Heavy_OSX-Info.plist"; sourceTree = ""; }; D84C615A19D1038F00D01F59 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; D84C615C19D1038F00D01F59 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; D84C615E19D1038F00D01F59 /* Heavy_OSX-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Heavy_OSX-Prefix.pch"; sourceTree = ""; }; D84C616019D1038F00D01F59 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; D84C616219D1038F00D01F59 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; D84C616319D1038F00D01F59 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; D84C616619D1038F00D01F59 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; D84C616819D1038F00D01F59 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; D84C616F19D1038F00D01F59 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; D84C618219D1042000D01F59 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = ""; }; D84C618319D1042000D01F59 /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = ""; }; D84C618419D1042000D01F59 /* MainViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainViewController.xib; sourceTree = ""; }; D84C618719D104F800D01F59 /* AudioEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioEngine.h; sourceTree = ""; }; D8500AD81BD9B9D400D12C3A /* HvSignalDel1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalDel1.c; path = ../ir2c/static/HvSignalDel1.c; sourceTree = ""; }; D8500AD91BD9B9D400D12C3A /* HvSignalDel1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalDel1.h; path = ../ir2c/static/HvSignalDel1.h; sourceTree = ""; }; D88AD8F91C5EEFEC000AC60F /* HvSignalLorenz.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalLorenz.c; path = ../ir2c/static/HvSignalLorenz.c; sourceTree = ""; }; D88AD8FA1C5EEFEC000AC60F /* HvSignalLorenz.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalLorenz.h; path = ../ir2c/static/HvSignalLorenz.h; sourceTree = ""; }; D89405DA1BE19A8300491551 /* HvSignalCPole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvSignalCPole.c; path = ../ir2c/static/HvSignalCPole.c; sourceTree = ""; }; D89405DB1BE19A8300491551 /* HvSignalCPole.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvSignalCPole.h; path = ../ir2c/static/HvSignalCPole.h; sourceTree = ""; }; D8A281EA1AEFC765004F8531 /* HvControlPack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = HvControlPack.c; path = ../ir2c/static/HvControlPack.c; sourceTree = ""; }; D8A281EB1AEFC765004F8531 /* HvControlPack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HvControlPack.h; path = ../ir2c/static/HvControlPack.h; sourceTree = ""; }; D8B4BE60198BC76B00987698 /* Heavy_CmdLine */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Heavy_CmdLine; sourceTree = BUILT_PRODUCTS_DIR; }; D8B4BE63198BC76B00987698 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; D8B4BE65198BC76B00987698 /* Heavy.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = Heavy.1; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 9036C1A81AD57CDF00C7B994 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 900D618C1AD9F2AE001BDB71 /* AVFoundation.framework in Frameworks */, 900D618A1AD9EFAD001BDB71 /* Accelerate.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; D84C614B19D1038F00D01F59 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 90B848C61D95C8EB0004BCE3 /* Accelerate.framework in Frameworks */, 90B848C41D95C8E60004BCE3 /* AudioUnit.framework in Frameworks */, D84C615119D1038F00D01F59 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; D8B4BE5D198BC76B00987698 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 9036C1AC1AD57CDF00C7B994 /* Heavy_iOS */ = { isa = PBXGroup; children = ( 9036C1B11AD57CDF00C7B994 /* AppDelegate.h */, 9036C1B21AD57CDF00C7B994 /* AppDelegate.m */, 9036C1B41AD57CDF00C7B994 /* ViewController.h */, 9036C1B51AD57CDF00C7B994 /* ViewController.m */, 9036C1D11AD58B3A00C7B994 /* TPCircularBuffer.c */, 9036C1D21AD58B3A00C7B994 /* TPCircularBuffer.h */, 9036C1D71AD58B9B00C7B994 /* HeavyAudio.h */, 9036C1D81AD58B9B00C7B994 /* HeavyAudio.m */, 9036C1B71AD57CDF00C7B994 /* Main.storyboard */, 9036C1BA1AD57CDF00C7B994 /* Images.xcassets */, 9036C1BC1AD57CDF00C7B994 /* LaunchScreen.xib */, 9036C1AD1AD57CDF00C7B994 /* Supporting Files */, ); path = Heavy_iOS; sourceTree = ""; }; 9036C1AD1AD57CDF00C7B994 /* Supporting Files */ = { isa = PBXGroup; children = ( 9036C1AE1AD57CDF00C7B994 /* Info.plist */, 9036C1AF1AD57CDF00C7B994 /* main.m */, ); name = "Supporting Files"; sourceTree = ""; }; 9059F9211BECD62F00589DE5 /* tinywav */ = { isa = PBXGroup; children = ( 9059F9251BECEE5100589DE5 /* tinywav.c */, 9059F9261BECEE5100589DE5 /* tinywav.h */, ); name = tinywav; sourceTree = ""; }; D84C614F19D1038F00D01F59 /* Frameworks */ = { isa = PBXGroup; children = ( 90B848C51D95C8EB0004BCE3 /* Accelerate.framework */, 90B848C31D95C8E60004BCE3 /* AudioUnit.framework */, 900D618B1AD9F2AE001BDB71 /* AVFoundation.framework */, 900D61891AD9EFAD001BDB71 /* Accelerate.framework */, D84C615019D1038F00D01F59 /* Cocoa.framework */, D84C616F19D1038F00D01F59 /* XCTest.framework */, D84C615219D1038F00D01F59 /* Other Frameworks */, ); name = Frameworks; sourceTree = ""; }; D84C615219D1038F00D01F59 /* Other Frameworks */ = { isa = PBXGroup; children = ( D84C615319D1038F00D01F59 /* AppKit.framework */, D84C615419D1038F00D01F59 /* CoreData.framework */, D84C615519D1038F00D01F59 /* Foundation.framework */, ); name = "Other Frameworks"; sourceTree = ""; }; D84C615619D1038F00D01F59 /* Heavy_OSX */ = { isa = PBXGroup; children = ( 9059F9211BECD62F00589DE5 /* tinywav */, D84C616219D1038F00D01F59 /* AppDelegate.h */, D84C616319D1038F00D01F59 /* AppDelegate.m */, D84C616519D1038F00D01F59 /* MainMenu.xib */, D84C618219D1042000D01F59 /* MainViewController.h */, D84C618319D1042000D01F59 /* MainViewController.m */, D84C618419D1042000D01F59 /* MainViewController.xib */, D84C618719D104F800D01F59 /* AudioEngine.h */, D827FD581DF5BBB300FFB63E /* AudioEngine.m */, D84C616819D1038F00D01F59 /* Images.xcassets */, D84C615719D1038F00D01F59 /* Supporting Files */, ); path = Heavy_OSX; sourceTree = ""; }; D84C615719D1038F00D01F59 /* Supporting Files */ = { isa = PBXGroup; children = ( D84C615819D1038F00D01F59 /* Heavy_OSX-Info.plist */, D84C615919D1038F00D01F59 /* InfoPlist.strings */, D84C615C19D1038F00D01F59 /* main.m */, D84C615E19D1038F00D01F59 /* Heavy_OSX-Prefix.pch */, D84C615F19D1038F00D01F59 /* Credits.rtf */, ); name = "Supporting Files"; sourceTree = ""; }; D861EF351990F95300F7C7A7 /* generated */ = { isa = PBXGroup; children = ( 9053E1181D95519300D3B881 /* Heavy_heavy.h */, 9053E1191D95519300D3B881 /* Heavy_heavy.hpp */, 90FBA04A1D573D0F002E49ED /* Heavy_heavy.cpp */, ); name = generated; sourceTree = ""; }; D881D57319915025009CAC78 /* templates */ = { isa = PBXGroup; children = ( 9053E11D1D95565000D3B881 /* Heavy_NAME.hpp */, 90FBA03E1D573C63002E49ED /* Heavy_NAME.cpp */, 90FBA03F1D573C63002E49ED /* Heavy_NAME.h */, ); name = templates; path = ../ir2c/templates; sourceTree = ""; }; D8B4BE57198BC76B00987698 = { isa = PBXGroup; children = ( D8B4BE62198BC76B00987698 /* Heavy_CmdLine */, D84C615619D1038F00D01F59 /* Heavy_OSX */, 9036C1AC1AD57CDF00C7B994 /* Heavy_iOS */, D8B4BE6C198BC84600987698 /* Heavy */, D84C614F19D1038F00D01F59 /* Frameworks */, D8B4BE61198BC76B00987698 /* Products */, ); sourceTree = ""; }; D8B4BE61198BC76B00987698 /* Products */ = { isa = PBXGroup; children = ( D8B4BE60198BC76B00987698 /* Heavy_CmdLine */, D84C614E19D1038F00D01F59 /* Heavy_OSX.app */, 9036C1AB1AD57CDF00C7B994 /* Heavy_iOS.app */, ); name = Products; sourceTree = ""; }; D8B4BE62198BC76B00987698 /* Heavy_CmdLine */ = { isa = PBXGroup; children = ( D8B4BE63198BC76B00987698 /* main.c */, D8B4BE65198BC76B00987698 /* Heavy.1 */, ); name = Heavy_CmdLine; path = Heavy; sourceTree = ""; }; D8B4BE6C198BC84600987698 /* Heavy */ = { isa = PBXGroup; children = ( D881D57319915025009CAC78 /* templates */, D861EF351990F95300F7C7A7 /* generated */, D8B4BE6D198BC85D00987698 /* static */, ); name = Heavy; sourceTree = ""; }; D8B4BE6D198BC85D00987698 /* static */ = { isa = PBXGroup; children = ( 905185D51D9E5BF20001CB5F /* HeavyContextInterface.hpp */, 9053E11C1D9555C600D3B881 /* HvHeavyInternal.h */, 90FBA0431D573C86002E49ED /* HvHeavy.cpp */, 90FBA0441D573C86002E49ED /* HvHeavy.h */, 90FBA0451D573C86002E49ED /* HeavyContext.cpp */, 9053E11A1D95531C00D3B881 /* HeavyContext.hpp */, 90AA58F71A63407400F3B66E /* HvControlBinop.c */, 90AA58F81A63407400F3B66E /* HvControlBinop.h */, 90AA58F91A63407400F3B66E /* HvControlCast.c */, 90AA58FA1A63407400F3B66E /* HvControlCast.h */, 90AA58FB1A63407400F3B66E /* HvControlDelay.c */, 90AA58FC1A63407400F3B66E /* HvControlDelay.h */, 90AA58FD1A63407400F3B66E /* HvControlIf.c */, 90AA58FE1A63407400F3B66E /* HvControlIf.h */, D8A281EA1AEFC765004F8531 /* HvControlPack.c */, D8A281EB1AEFC765004F8531 /* HvControlPack.h */, 90AA58FF1A63407400F3B66E /* HvControlPrint.c */, 90AA59001A63407400F3B66E /* HvControlPrint.h */, 90AA59011A63407400F3B66E /* HvControlRandom.c */, 90AA59021A63407400F3B66E /* HvControlRandom.h */, 90AA59031A63407400F3B66E /* HvControlSlice.c */, 90AA59041A63407400F3B66E /* HvControlSlice.h */, 90AA59051A63407400F3B66E /* HvControlSystem.c */, 90AA59061A63407400F3B66E /* HvControlSystem.h */, 90226C171A9F8DAD005D8253 /* HvControlTabhead.c */, 90226C181A9F8DAD005D8253 /* HvControlTabhead.h */, 906FAB781AEF85C000B9F165 /* HvControlTabread.c */, 906FAB791AEF85C000B9F165 /* HvControlTabread.h */, 906FAB7D1AEF895E00B9F165 /* HvControlTabwrite.c */, 906FAB7E1AEF895E00B9F165 /* HvControlTabwrite.h */, 90AA59071A63407400F3B66E /* HvControlUnop.c */, 90AA59081A63407400F3B66E /* HvControlUnop.h */, 90AA59091A63407400F3B66E /* HvControlVar.c */, 90AA590A1A63407400F3B66E /* HvControlVar.h */, 90AA590B1A63407400F3B66E /* cpuid.c */, 90AA590C1A63407400F3B66E /* cpuid.h */, 90AA590E1A63407400F3B66E /* HvMath.h */, 9088F1B81CB36DA600569945 /* HvLightPipe.c */, 9088F1B91CB36DA600569945 /* HvLightPipe.h */, 90AA59111A63407400F3B66E /* HvMessage.c */, 90AA59121A63407400F3B66E /* HvMessage.h */, 90AA59131A63407400F3B66E /* HvTable.c */, 90AA59141A63407400F3B66E /* HvTable.h */, 90AA59151A63407400F3B66E /* HvMessagePool.c */, 90AA59161A63407400F3B66E /* HvMessagePool.h */, 90AA59171A63407400F3B66E /* HvMessageQueue.c */, 90AA59181A63407400F3B66E /* HvMessageQueue.h */, 90AA59191A63407400F3B66E /* HvSignalBiquad.c */, 90AA591A1A63407400F3B66E /* HvSignalBiquad.h */, 90D200C01BC2AB6400E45A9D /* HvSignalConvolution.c */, 90D200C11BC2AB6400E45A9D /* HvSignalConvolution.h */, D89405DA1BE19A8300491551 /* HvSignalCPole.c */, D89405DB1BE19A8300491551 /* HvSignalCPole.h */, D8500AD81BD9B9D400D12C3A /* HvSignalDel1.c */, D8500AD91BD9B9D400D12C3A /* HvSignalDel1.h */, 90AA591B1A63407400F3B66E /* HvSignalEnvelope.c */, 90AA591C1A63407400F3B66E /* HvSignalEnvelope.h */, 90AA591D1A63407400F3B66E /* HvSignalLine.c */, 90AA591E1A63407400F3B66E /* HvSignalLine.h */, D88AD8F91C5EEFEC000AC60F /* HvSignalLorenz.c */, D88AD8FA1C5EEFEC000AC60F /* HvSignalLorenz.h */, 90AA591F1A63407400F3B66E /* HvSignalPhasor.c */, 90AA59201A63407400F3B66E /* HvSignalPhasor.h */, 9015F0C51BDDB25300070222 /* HvSignalRPole.c */, 9015F0C61BDDB25300070222 /* HvSignalRPole.h */, 90AC14541BD51F67006C126E /* HvSignalSamphold.c */, 90AC14551BD51F67006C126E /* HvSignalSamphold.h */, 90AA59211A63407400F3B66E /* HvSignalSample.c */, 90AA59221A63407400F3B66E /* HvSignalSample.h */, 90AA59231A63407400F3B66E /* HvSignalTabread.c */, 90AA59241A63407400F3B66E /* HvSignalTabread.h */, 90AA59251A63407400F3B66E /* HvSignalTabwrite.c */, 90AA59261A63407400F3B66E /* HvSignalTabwrite.h */, 90AA59271A63407400F3B66E /* HvSignalVar.c */, 90AA59281A63407400F3B66E /* HvSignalVar.h */, 90AA592F1A63407400F3B66E /* HvUtils.h */, 906644F51E5E43F7007F4762 /* HvUtils.c */, ); name = static; path = ../static; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 9036C1AA1AD57CDF00C7B994 /* Heavy_iOS */ = { isa = PBXNativeTarget; buildConfigurationList = 9036C1CF1AD57CDF00C7B994 /* Build configuration list for PBXNativeTarget "Heavy_iOS" */; buildPhases = ( 900D616D1AD9ED8E001BDB71 /* ShellScript */, 9036C1A71AD57CDF00C7B994 /* Sources */, 9036C1A81AD57CDF00C7B994 /* Frameworks */, 9036C1A91AD57CDF00C7B994 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Heavy_iOS; productName = Heavy_iOS; productReference = 9036C1AB1AD57CDF00C7B994 /* Heavy_iOS.app */; productType = "com.apple.product-type.application"; }; D84C614D19D1038F00D01F59 /* Heavy_OSX */ = { isa = PBXNativeTarget; buildConfigurationList = D84C617C19D1038F00D01F59 /* Build configuration list for PBXNativeTarget "Heavy_OSX" */; buildPhases = ( D84C619B19D1087100D01F59 /* Run Script */, D84C614A19D1038F00D01F59 /* Sources */, D84C614B19D1038F00D01F59 /* Frameworks */, D84C614C19D1038F00D01F59 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Heavy_OSX; productName = Heavy_OSX; productReference = D84C614E19D1038F00D01F59 /* Heavy_OSX.app */; productType = "com.apple.product-type.application"; }; D8B4BE5F198BC76B00987698 /* Heavy_CmdLine */ = { isa = PBXNativeTarget; buildConfigurationList = D8B4BE69198BC76B00987698 /* Build configuration list for PBXNativeTarget "Heavy_CmdLine" */; buildPhases = ( D8B4BE8F198BD4EA00987698 /* Run Script */, D8B4BE5C198BC76B00987698 /* Sources */, D8B4BE5D198BC76B00987698 /* Frameworks */, D8B4BE5E198BC76B00987698 /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = Heavy_CmdLine; productName = Heavy; productReference = D8B4BE60198BC76B00987698 /* Heavy_CmdLine */; productType = "com.apple.product-type.tool"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ D8B4BE58198BC76B00987698 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0800; ORGANIZATIONNAME = section6; TargetAttributes = { 9036C1AA1AD57CDF00C7B994 = { CreatedOnToolsVersion = 6.2; }; }; }; buildConfigurationList = D8B4BE5B198BC76B00987698 /* Build configuration list for PBXProject "Heavy" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = D8B4BE57198BC76B00987698; productRefGroup = D8B4BE61198BC76B00987698 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( D8B4BE5F198BC76B00987698 /* Heavy_CmdLine */, D84C614D19D1038F00D01F59 /* Heavy_OSX */, 9036C1AA1AD57CDF00C7B994 /* Heavy_iOS */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 9036C1A91AD57CDF00C7B994 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 9036C1B91AD57CDF00C7B994 /* Main.storyboard in Resources */, 9036C1BE1AD57CDF00C7B994 /* LaunchScreen.xib in Resources */, 9036C1BB1AD57CDF00C7B994 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; D84C614C19D1038F00D01F59 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( D84C615B19D1038F00D01F59 /* InfoPlist.strings in Resources */, D84C616919D1038F00D01F59 /* Images.xcassets in Resources */, D84C618619D1042000D01F59 /* MainViewController.xib in Resources */, D84C616119D1038F00D01F59 /* Credits.rtf in Resources */, D84C616719D1038F00D01F59 /* MainMenu.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 900D616D1AD9ED8E001BDB71 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /usr/bin/python; shellScript = "#!/usr/bin/python\n\nimport os\nimport sys\n\n_PROJ_ROOT = os.environ[\"SRCROOT\"]\nsys.path.append(os.path.join(_PROJ_ROOT, \"../../\"))\nimport hvcc\n\ndef main():\n pd_path = \"/Users/mhroth/Desktop/test_osc.pd\"\n output_dir = os.path.join(_PROJ_ROOT, \"build\")\n hvcc_results = hvcc.compile_dataflow(in_path=pd_path, out_dir=output_dir, generators=[\"c\"], verbose=False)\n for r in hvcc_results.values():\n if r[\"notifs\"].get(\"has_error\", False):\n print r[\"stage\"], \"returned error:\"\n for error in hvcc_results[\"pd2hv\"][\"notifs\"][\"errors\"]:\n print \"\\t\", error[\"message\"]\n sys.exit(1)\n\nif __name__ == \"__main__\":\n main()\n"; }; D84C619B19D1087100D01F59 /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Run Script"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /usr/bin/python; shellScript = "#!/usr/bin/python\n\nimport os\nimport sys\n\n_PROJ_ROOT = os.environ[\"SRCROOT\"]\nsys.path.append(os.path.join(_PROJ_ROOT, \"../../\"))\nimport hvcc\n\ndef main():\n pd_path = \"/Users/joe/Desktop/Unity Project/Assets/Patches/sine/_main.pd\"\n output_dir = os.path.join(_PROJ_ROOT, \"build\")\n hvcc_results = hvcc.compile_dataflow(in_path=pd_path, out_dir=output_dir, generators=[\"c\"], verbose=False)\n for r in hvcc_results.values():\n if r[\"notifs\"].get(\"has_error\", False):\n print r[\"stage\"], \"returned error:\"\n for error in hvcc_results[\"pd2hv\"][\"notifs\"][\"errors\"]:\n print \"\\t\", error[\"message\"]\n sys.exit(1)\n\nif __name__ == \"__main__\":\n main()\n"; }; D8B4BE8F198BD4EA00987698 /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Run Script"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /usr/bin/python; shellScript = "#!/usr/bin/python\n\nimport os\nimport sys\n\n_PROJ_ROOT = os.environ[\"SRCROOT\"]\nsys.path.append(os.path.join(_PROJ_ROOT, \"../../\"))\nimport hvcc\n\ndef main():\n pd_path = \"/Users/mhroth/Desktop/e_cos.pd\"\n output_dir = os.path.join(_PROJ_ROOT, \"build\")\n hvcc_results = hvcc.compile_dataflow(in_path=pd_path, out_dir=output_dir, generators=[\"c\"], verbose=False)\n for r in hvcc_results.values():\n if r[\"notifs\"].get(\"has_error\", False):\n print r[\"stage\"], \"returned error:\"\n for error in hvcc_results[\"pd2hv\"][\"notifs\"][\"errors\"]:\n print \"\\t\", error[\"message\"]\n sys.exit(1)\n\nif __name__ == \"__main__\":\n main()\n # pass"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 9036C1A71AD57CDF00C7B994 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 90B849351D95CA320004BCE3 /* HvSignalSample.c in Sources */, 90B8493A1D95CAA90004BCE3 /* Heavy_heavy.cpp in Sources */, 90B849211D95CA320004BCE3 /* HvControlTabhead.c in Sources */, 90B8492E1D95CA320004BCE3 /* HvSignalDel1.c in Sources */, 90B849381D95CA320004BCE3 /* HvSignalVar.c in Sources */, 90B849241D95CA320004BCE3 /* HvControlUnop.c in Sources */, 90B849301D95CA320004BCE3 /* HvSignalLine.c in Sources */, 90B849181D95CA320004BCE3 /* HvControlBinop.c in Sources */, 9036C1B61AD57CDF00C7B994 /* ViewController.m in Sources */, 90B8491C1D95CA320004BCE3 /* HvControlPack.c in Sources */, 90B849341D95CA320004BCE3 /* HvSignalSamphold.c in Sources */, 90B8491B1D95CA320004BCE3 /* HvControlIf.c in Sources */, 90B849321D95CA320004BCE3 /* HvSignalPhasor.c in Sources */, 90B8492C1D95CA320004BCE3 /* HvSignalConvolution.c in Sources */, 90B8492F1D95CA320004BCE3 /* HvSignalEnvelope.c in Sources */, 9036C1B31AD57CDF00C7B994 /* AppDelegate.m in Sources */, 9036C1D91AD58B9B00C7B994 /* HeavyAudio.m in Sources */, 90B849281D95CA320004BCE3 /* HvTable.c in Sources */, 90B8492A1D95CA320004BCE3 /* HvMessageQueue.c in Sources */, 90B849261D95CA320004BCE3 /* HvLightPipe.c in Sources */, 90B849201D95CA320004BCE3 /* HvControlSystem.c in Sources */, 90B8492B1D95CA320004BCE3 /* HvSignalBiquad.c in Sources */, 90B8491D1D95CA320004BCE3 /* HvControlPrint.c in Sources */, 906644F81E5E43F7007F4762 /* HvUtils.c in Sources */, 90B849171D95CA320004BCE3 /* HeavyContext.cpp in Sources */, 90B849331D95CA320004BCE3 /* HvSignalRPole.c in Sources */, 90B8491E1D95CA320004BCE3 /* HvControlRandom.c in Sources */, 90B849291D95CA320004BCE3 /* HvMessagePool.c in Sources */, 90B849221D95CA320004BCE3 /* HvControlTabread.c in Sources */, 90B849271D95CA320004BCE3 /* HvMessage.c in Sources */, 90B849251D95CA320004BCE3 /* HvControlVar.c in Sources */, 90B8491F1D95CA320004BCE3 /* HvControlSlice.c in Sources */, 90B849311D95CA320004BCE3 /* HvSignalLorenz.c in Sources */, 90B8492D1D95CA320004BCE3 /* HvSignalCPole.c in Sources */, 9036C1D51AD58B3A00C7B994 /* TPCircularBuffer.c in Sources */, 90B849371D95CA320004BCE3 /* HvSignalTabwrite.c in Sources */, 9036C1B01AD57CDF00C7B994 /* main.m in Sources */, 90B849231D95CA320004BCE3 /* HvControlTabwrite.c in Sources */, 90B8491A1D95CA320004BCE3 /* HvControlDelay.c in Sources */, 90B849361D95CA320004BCE3 /* HvSignalTabread.c in Sources */, 90B849161D95CA320004BCE3 /* HvHeavy.cpp in Sources */, 90B849191D95CA320004BCE3 /* HvControlCast.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; D84C614A19D1038F00D01F59 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 90B848FC1D95CA320004BCE3 /* HvControlSlice.c in Sources */, 90B849391D95CAA80004BCE3 /* Heavy_heavy.cpp in Sources */, 90B848F81D95CA320004BCE3 /* HvControlIf.c in Sources */, 90B849101D95CA320004BCE3 /* HvSignalRPole.c in Sources */, 90B848FB1D95CA320004BCE3 /* HvControlRandom.c in Sources */, 90B8490F1D95CA320004BCE3 /* HvSignalPhasor.c in Sources */, 90B849081D95CA320004BCE3 /* HvSignalBiquad.c in Sources */, 90B8490E1D95CA320004BCE3 /* HvSignalLorenz.c in Sources */, D84C616419D1038F00D01F59 /* AppDelegate.m in Sources */, 90B848F71D95CA320004BCE3 /* HvControlDelay.c in Sources */, 90B848F61D95CA320004BCE3 /* HvControlCast.c in Sources */, 90B848FE1D95CA320004BCE3 /* HvControlTabhead.c in Sources */, D84C618519D1042000D01F59 /* MainViewController.m in Sources */, 90B849001D95CA320004BCE3 /* HvControlTabwrite.c in Sources */, 90B849111D95CA320004BCE3 /* HvSignalSamphold.c in Sources */, 90B848F41D95CA320004BCE3 /* HeavyContext.cpp in Sources */, 90B8490D1D95CA320004BCE3 /* HvSignalLine.c in Sources */, 90B849031D95CA320004BCE3 /* HvLightPipe.c in Sources */, 90B8490A1D95CA320004BCE3 /* HvSignalCPole.c in Sources */, 90B848F51D95CA320004BCE3 /* HvControlBinop.c in Sources */, 90B848F91D95CA320004BCE3 /* HvControlPack.c in Sources */, 90B849151D95CA320004BCE3 /* HvSignalVar.c in Sources */, 90B849021D95CA320004BCE3 /* HvControlVar.c in Sources */, 906644F71E5E43F7007F4762 /* HvUtils.c in Sources */, 90B849041D95CA320004BCE3 /* HvMessage.c in Sources */, 90B849121D95CA320004BCE3 /* HvSignalSample.c in Sources */, 90B848FD1D95CA320004BCE3 /* HvControlSystem.c in Sources */, 90B849011D95CA320004BCE3 /* HvControlUnop.c in Sources */, 90B848FA1D95CA320004BCE3 /* HvControlPrint.c in Sources */, 90B849091D95CA320004BCE3 /* HvSignalConvolution.c in Sources */, 90B849131D95CA320004BCE3 /* HvSignalTabread.c in Sources */, 9059F9271BECEE5100589DE5 /* tinywav.c in Sources */, 90B849051D95CA320004BCE3 /* HvTable.c in Sources */, 90B849061D95CA320004BCE3 /* HvMessagePool.c in Sources */, D827FD591DF5BBB300FFB63E /* AudioEngine.m in Sources */, 90B849071D95CA320004BCE3 /* HvMessageQueue.c in Sources */, 90B849141D95CA320004BCE3 /* HvSignalTabwrite.c in Sources */, 90B848F31D95CA320004BCE3 /* HvHeavy.cpp in Sources */, 90B8490B1D95CA320004BCE3 /* HvSignalDel1.c in Sources */, 90B8490C1D95CA320004BCE3 /* HvSignalEnvelope.c in Sources */, 90B848FF1D95CA320004BCE3 /* HvControlTabread.c in Sources */, D84C615D19D1038F00D01F59 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; D8B4BE5C198BC76B00987698 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 90B848E61D95CA310004BCE3 /* HvSignalConvolution.c in Sources */, 90B848DD1D95CA310004BCE3 /* HvControlTabwrite.c in Sources */, 90B848E41D95CA310004BCE3 /* HvMessageQueue.c in Sources */, 90B848D61D95CA310004BCE3 /* HvControlPack.c in Sources */, D8B4BE64198BC76B00987698 /* main.c in Sources */, 90B848D11D95CA310004BCE3 /* HeavyContext.cpp in Sources */, 90B848EB1D95CA310004BCE3 /* HvSignalLorenz.c in Sources */, 90B848D91D95CA310004BCE3 /* HvControlSlice.c in Sources */, 90AA59441A63407400F3B66E /* cpuid.c in Sources */, 90B848E31D95CA310004BCE3 /* HvMessagePool.c in Sources */, 90B848EC1D95CA310004BCE3 /* HvSignalPhasor.c in Sources */, 90B848DC1D95CA310004BCE3 /* HvControlTabread.c in Sources */, 90B848D51D95CA310004BCE3 /* HvControlIf.c in Sources */, 90B848F01D95CA310004BCE3 /* HvSignalTabread.c in Sources */, 90B848F11D95CA310004BCE3 /* HvSignalTabwrite.c in Sources */, 90B848E91D95CA310004BCE3 /* HvSignalEnvelope.c in Sources */, 90FBA04E1D573DD3002E49ED /* Heavy_heavy.cpp in Sources */, 90B848D31D95CA310004BCE3 /* HvControlCast.c in Sources */, 90B848DA1D95CA310004BCE3 /* HvControlSystem.c in Sources */, 90B848D21D95CA310004BCE3 /* HvControlBinop.c in Sources */, 90B848E11D95CA310004BCE3 /* HvMessage.c in Sources */, 90B848F21D95CA310004BCE3 /* HvSignalVar.c in Sources */, 90B848DB1D95CA310004BCE3 /* HvControlTabhead.c in Sources */, 90B848D71D95CA310004BCE3 /* HvControlPrint.c in Sources */, 90B848E01D95CA310004BCE3 /* HvLightPipe.c in Sources */, 90B848E71D95CA310004BCE3 /* HvSignalCPole.c in Sources */, 906644F61E5E43F7007F4762 /* HvUtils.c in Sources */, 90B848EA1D95CA310004BCE3 /* HvSignalLine.c in Sources */, 90B848D01D95CA310004BCE3 /* HvHeavy.cpp in Sources */, 90B848D81D95CA310004BCE3 /* HvControlRandom.c in Sources */, 90B848D41D95CA310004BCE3 /* HvControlDelay.c in Sources */, 90B848E51D95CA310004BCE3 /* HvSignalBiquad.c in Sources */, 90B848DE1D95CA310004BCE3 /* HvControlUnop.c in Sources */, 90B848ED1D95CA310004BCE3 /* HvSignalRPole.c in Sources */, 90B848EF1D95CA310004BCE3 /* HvSignalSample.c in Sources */, 90B848E81D95CA310004BCE3 /* HvSignalDel1.c in Sources */, 90B848E21D95CA310004BCE3 /* HvTable.c in Sources */, 90B848DF1D95CA310004BCE3 /* HvControlVar.c in Sources */, 90B848EE1D95CA310004BCE3 /* HvSignalSamphold.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 9036C1B71AD57CDF00C7B994 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 9036C1B81AD57CDF00C7B994 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 9036C1BC1AD57CDF00C7B994 /* LaunchScreen.xib */ = { isa = PBXVariantGroup; children = ( 9036C1BD1AD57CDF00C7B994 /* Base */, ); name = LaunchScreen.xib; sourceTree = ""; }; D84C615919D1038F00D01F59 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( D84C615A19D1038F00D01F59 /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; D84C615F19D1038F00D01F59 /* Credits.rtf */ = { isa = PBXVariantGroup; children = ( D84C616019D1038F00D01F59 /* en */, ); name = Credits.rtf; sourceTree = ""; }; D84C616519D1038F00D01F59 /* MainMenu.xib */ = { isa = PBXVariantGroup; children = ( D84C616619D1038F00D01F59 /* Base */, ); name = MainMenu.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 9036C1CB1AD57CDF00C7B994 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_WARN_UNREACHABLE_CODE = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = Heavy_iOS/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.enzienaudio.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 9036C1CC1AD57CDF00C7B994 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_WARN_UNREACHABLE_CODE = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_OPTIMIZATION_LEVEL = 3; INFOPLIST_FILE = Heavy_iOS/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; OTHER_CFLAGS = ( "-ffast-math", "-DNDEBUG", ); PRODUCT_BUNDLE_IDENTIFIER = "com.enzienaudio.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; D84C617D19D1038F00D01F59 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; COMBINE_HIDPI_IMAGES = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Heavy_OSX/Heavy_OSX-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = "Heavy_OSX/Heavy_OSX-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "com.section6.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Debug; }; D84C617E19D1038F00D01F59 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; COMBINE_HIDPI_IMAGES = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Heavy_OSX/Heavy_OSX-Prefix.pch"; INFOPLIST_FILE = "Heavy_OSX/Heavy_OSX-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "com.section6.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Release; }; D8B4BE67198BC76B00987698 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c11; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.9; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "-Wno-unused-function", "-Wno-#warnings", ); SDKROOT = macosx; SUPPORTED_PLATFORMS = macosx; }; name = Debug; }; D8B4BE68198BC76B00987698 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c11; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 3; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.9; OTHER_CFLAGS = ( "-ffast-math", "-msse4.1", "-DNDEBUG", "-Wno-#warnings", "-Wno-unused-function", ); SDKROOT = macosx; SUPPORTED_PLATFORMS = macosx; }; name = Release; }; D8B4BE6A198BC76B00987698 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; D8B4BE6B198BC76B00987698 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 9036C1CF1AD57CDF00C7B994 /* Build configuration list for PBXNativeTarget "Heavy_iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( 9036C1CB1AD57CDF00C7B994 /* Debug */, 9036C1CC1AD57CDF00C7B994 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; D84C617C19D1038F00D01F59 /* Build configuration list for PBXNativeTarget "Heavy_OSX" */ = { isa = XCConfigurationList; buildConfigurations = ( D84C617D19D1038F00D01F59 /* Debug */, D84C617E19D1038F00D01F59 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; D8B4BE5B198BC76B00987698 /* Build configuration list for PBXProject "Heavy" */ = { isa = XCConfigurationList; buildConfigurations = ( D8B4BE67198BC76B00987698 /* Debug */, D8B4BE68198BC76B00987698 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; D8B4BE69198BC76B00987698 /* Build configuration list for PBXNativeTarget "Heavy_CmdLine" */ = { isa = XCConfigurationList; buildConfigurations = ( D8B4BE6A198BC76B00987698 /* Debug */, D8B4BE6B198BC76B00987698 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = D8B4BE58198BC76B00987698 /* Project object */; } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/AppDelegate.h0000644000000000000000000000164614435670357020023 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import @class MainViewController; @interface AppDelegate : NSObject @property (assign) IBOutlet NSWindow *window; @property (nonatomic, strong) MainViewController *mainViewController; @end ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/AppDelegate.m0000644000000000000000000000216514435670357020025 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import "AppDelegate.h" #import "MainViewController.h" @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { self.mainViewController = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil]; [self.window setContentView:[self.mainViewController view]]; } - (void)applicationWillTerminate:(NSNotification *)notification { [self.mainViewController destroy]; } @end ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/AudioEngine.h0000644000000000000000000000313214435670357020027 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import #include #include "tinywav.h" struct HeavyContextInterface; @class MainViewController; @interface AudioEngine : NSObject { double _sampleRate; int _blockSize; int _numOutputChannels; @public TinyWav tinywav; MainViewController *viewController; NSLock *lock; } @property (readonly) AudioUnit outputUnit; @property (assign) double startingFrameCount; @property (assign) int counter; @property (nonatomic) struct HeavyContextInterface *context; @property (atomic) bool keepRunning; + (void)update:(AudioEngine *)engine; - (id)initWithView:(MainViewController *)viewController; - (void)start; - (void)stop; - (void)destroy; - (void)sendFloat:(float)value toReceiver:(NSString *)receiverName; - (void)printStreamDescription:(const AudioStreamBasicDescription)asbd; - (void)recordAudioToFile:(NSString *)filepath; - (void)stopRecordingAudio; @end ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/AudioEngine.m0000644000000000000000000002310514435670357020036 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import #import "AudioEngine.h" #import "Heavy_heavy.h" #import "MainViewController.h" static void printHook(HeavyContextInterface *c, const char *name, const char *s, const HvMessage *m) { double timestampMs = 1000.0 * ((double) hv_msg_getTimestamp(m)) / hv_getSampleRate(c); NSLog(@"[%0.3fms] %s: %s", timestampMs, name, s); } static void checkError(OSStatus error, const char *operation) { if (error == noErr) return; char errorString[20] = {}; // See if it appears to be a 4-char code *(UInt32 *)(errorString+1) = CFSwapInt32HostToBig(error); if (isprint(errorString[1]) && isprint(errorString[2]) && isprint(errorString[3]) && isprint(errorString[4])) { errorString[0] = errorString[5] = '\''; errorString[6] = '\0'; } else { sprintf(errorString, "%d", (int)error); } fprintf(stderr, "Error: %s (%s)\n", operation, errorString); exit(1); } OSStatus AudioEngineRenderProc(void *inRefCon, AudioUnitRenderActionFlags *ioActionsFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { // const double tick_rc = CFAbsoluteTimeGetCurrent(); AudioEngine *audioEngine = (__bridge AudioEngine *) inRefCon; [audioEngine->lock lock]; int n = 0; double tock = 0.0; switch (hv_getNumOutputChannels(audioEngine.context)) { case 2: { const double tick = CFAbsoluteTimeGetCurrent(); float *outputBuffers[2] = { (float *) ioData->mBuffers[0].mData, (float *) ioData->mBuffers[1].mData }; n = hv_process(audioEngine.context, NULL, outputBuffers, inNumberFrames); tock = CFAbsoluteTimeGetCurrent() - tick; if (tinywav_isOpen(&audioEngine->tinywav)) { tinywav_write_f(&audioEngine->tinywav, outputBuffers, inNumberFrames); } break; } case 1: { const double tick = CFAbsoluteTimeGetCurrent(); float *b = (float *) ioData->mBuffers[0].mData; n = hv_process(audioEngine.context, NULL, &b, inNumberFrames); tock = CFAbsoluteTimeGetCurrent() - tick; if (tinywav_isOpen(&audioEngine->tinywav)) { tinywav_write_f(&audioEngine->tinywav, &b, inNumberFrames); } break; } default: break; } // const double tock_rc = CFAbsoluteTimeGetCurrent() - tick_rc; // NSLog(@"%iµs (%iµs) @ %i/%gHz (%0.3f%% CPU)", // (int) (1000000.0 * tock), // execution time of heavy callback // (int) (1000000.0 * tock_rc), // execution time of entire render callback // (int) inNumberFrames, // hv_getSampleRate(audioEngine.context), // 100.0*(tock/(inNumberFrames/hv_getSampleRate(audioEngine.context)))); [audioEngine->lock unlock]; dispatch_async(dispatch_get_main_queue(), ^{ [audioEngine->viewController updateCpuWithDuration:tock andFraction:tock/(inNumberFrames/hv_getSampleRate(audioEngine.context))]; }); if (n != inNumberFrames) { NSLog(@"WARNING: Heavy did not process the full frame: %i/%i", n, inNumberFrames); } return noErr; } @implementation AudioEngine + (void)update:(AudioEngine *)engine { while (engine.keepRunning) { unsigned int sendHash = 0; HvMessage *msg = (HvMessage *) malloc(hv_msg_getByteSize(100)); while (hv_getNextSentMessage(engine.context, &sendHash, msg, (hv_uint32_t) hv_msg_getByteSize(100))) { if (sendHash == hv_stringToHash("hello")) { if (hv_msg_hasFormat(msg, "f")) { NSLog(@"hello: %f", hv_msg_getFloat(msg, 0)); } } if (sendHash == hv_stringToHash("finished")) { if (hv_msg_hasFormat(msg, "b")) { NSLog(@"finished"); } } } [NSThread sleepForTimeInterval:0.0001f]; } } - (id)initWithView:(MainViewController *)view { self = [super init]; if (self) { _sampleRate = 48000.0; _context = hv_heavy_new_with_options(_sampleRate, 10, 2, 2); hv_setPrintHook(_context, &printHook); _blockSize = 512; _counter = 0; _numOutputChannels = hv_getNumOutputChannels(_context); lock = [[NSLock alloc] init]; self->viewController = view; memset(&tinywav, 0, sizeof(TinyWav)); [self initialiseAudioUnit]; } return self; } - (void)initialiseAudioUnit { // Generate output audio unit AudioComponentDescription outputcd = {0}; outputcd.componentType = kAudioUnitType_Output; outputcd.componentSubType = kAudioUnitSubType_DefaultOutput; outputcd.componentManufacturer = kAudioUnitManufacturer_Apple; AudioComponent comp = AudioComponentFindNext(NULL, &outputcd); if (comp == NULL) { NSLog(@"Can't get output unit"); exit(-1); } checkError(AudioComponentInstanceNew(comp, &_outputUnit), "Couldn't open component for outputUnit"); // Get stream format AudioStreamBasicDescription asbd = {0}; UInt32 size = sizeof(asbd); checkError(AudioUnitGetProperty(_outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &asbd, &size), "AudioUnitGetProperty (kAudioUnitProperty_StreamFormat) failed"); // Set stream format asbd.mBytesPerPacket = 4; asbd.mFramesPerPacket = 1; asbd.mChannelsPerFrame = _numOutputChannels; asbd.mBitsPerChannel = 32; asbd.mFormatID = kAudioFormatLinearPCM; asbd.mFormatFlags = kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked; asbd.mSampleRate = _sampleRate; [self printStreamDescription:asbd]; checkError(AudioUnitSetProperty(_outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &asbd, size), "AudioUnitSetProperty (kAudioUnitProperty_StreamFormat) failed"); // Register the render callback AURenderCallbackStruct input; input.inputProc = AudioEngineRenderProc; input.inputProcRefCon = (__bridge void *)(self); checkError(AudioUnitSetProperty(_outputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(input)), "AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback) failed"); // Initialise the unit checkError(AudioUnitInitialize(_outputUnit), "Couldn't initialise outut unit"); // Make sure samplerate is correctly set after initialisation _sampleRate = asbd.mSampleRate; } - (void)start { checkError(AudioOutputUnitStart(_outputUnit), "Couldn't start output unit"); _keepRunning = true; // [NSThread detachNewThreadSelector:@selector(update:) toTarget:[AudioEngine class] withObject:self]; } - (void)stop { _keepRunning = false; checkError(AudioOutputUnitStop(_outputUnit), "Couldn't stop output unit"); } - (void)sendFloat:(float)value toReceiver:(NSString *)receiverName { if (self.context != NULL) { [lock lock]; hv_sendFloatToReceiver(self.context, hv_stringToHash([receiverName cStringUsingEncoding:NSASCIIStringEncoding]), value); [lock unlock]; } } - (void)destroy { AudioOutputUnitStop(_outputUnit); AudioUnitUninitialize(_outputUnit); AudioComponentInstanceDispose(_outputUnit); _keepRunning = false; } - (void)printStreamDescription:(const AudioStreamBasicDescription)asbd { NSLog(@"AudioStreamBasicDescription:"); NSLog(@"\t Sample Rate:\t\t %g", asbd.mSampleRate); NSLog(@"\t Bytes Per Packet:\t %d", asbd.mBytesPerPacket); NSLog(@"\t Frames Per Packet:\t %d", asbd.mFramesPerPacket); NSLog(@"\t Channels Per Frame: %d", asbd.mChannelsPerFrame); NSLog(@"\t Bits Per Channel:\t %d", asbd.mBitsPerChannel); char formatID[20] = {}; *(UInt32 *)(formatID+1) = CFSwapInt32HostToBig(asbd.mFormatID); if (isprint(formatID[1]) && isprint(formatID[2]) && isprint(formatID[3]) && isprint(formatID[4])) { formatID[0] = formatID[5] = '\''; formatID[6] = '\0'; NSLog(@"\t Format ID:\t\t\t %s", formatID); } else { NSLog(@"\t Format ID:\t\t\t unknown"); } NSLog(@"\t Format Flags:"); if (asbd.mFormatFlags & kAudioFormatFlagIsFloat) NSLog(@"\t\t kAudioFormatFlagIsFloat"); if (asbd.mFormatFlags & kAudioFormatFlagIsBigEndian) NSLog(@"\t\t kAudioFormatFlagIsBigEndian"); if (asbd.mFormatFlags & kAudioFormatFlagIsSignedInteger) NSLog(@"\t\t kAudioFormatFlagIsSignedInteger"); if (asbd.mFormatFlags & kAudioFormatFlagIsPacked) NSLog(@"\t\t kAudioFormatFlagIsPacked"); if (asbd.mFormatFlags & kAudioFormatFlagIsAlignedHigh) NSLog(@"\t\t kAudioFormatFlagIsAlignedHigh"); if (asbd.mFormatFlags & kAudioFormatFlagIsNonInterleaved) NSLog(@"\t\t kAudioFormatFlagIsNonInterleaved"); if (asbd.mFormatFlags & kAudioFormatFlagIsNonMixable) NSLog(@"\t\t kAudioFormatFlagIsNonMixable"); if (asbd.mFormatFlags & kAudioFormatFlagIsNonMixable) NSLog(@"\t\t kAudioFormatFlagsAreAllClear"); } - (void)recordAudioToFile:(NSString *)filepath { [lock lock]; tinywav_new(&tinywav, (int16_t) hv_getNumOutputChannels(_context), (int32_t) _sampleRate, TW_FLOAT32, TW_SPLIT, [filepath cStringUsingEncoding:NSASCIIStringEncoding]); [lock unlock]; } - (void)stopRecordingAudio { [lock lock]; tinywav_close(&tinywav); [lock unlock]; } @end ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/Base.lproj/MainMenu.xib0000644000000000000000000014077714435670357021724 0ustar00 Default Left to Right Right to Left Default Left to Right Right to Left ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/Heavy_OSX-Info.plist0000644000000000000000000000207014435670357021242 0ustar00 CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} NSHumanReadableCopyright Copyright © 2014 section6. All rights reserved. NSMainNibFile MainMenu NSPrincipalClass NSApplication ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.766207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/Heavy_OSX-Prefix.pch0000644000000000000000000000025214435670357021223 0ustar00// // Prefix header // // The contents of this file are implicitly included at the beginning of every source file. // #ifdef __OBJC__ #import #endif ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/Images.xcassets/AppIcon.appiconset/Contents.json0000644000000000000000000000160714435670357026722 0ustar00{ "images" : [ { "idiom" : "mac", "size" : "16x16", "scale" : "1x" }, { "idiom" : "mac", "size" : "16x16", "scale" : "2x" }, { "idiom" : "mac", "size" : "32x32", "scale" : "1x" }, { "idiom" : "mac", "size" : "32x32", "scale" : "2x" }, { "idiom" : "mac", "size" : "128x128", "scale" : "1x" }, { "idiom" : "mac", "size" : "128x128", "scale" : "2x" }, { "idiom" : "mac", "size" : "256x256", "scale" : "1x" }, { "idiom" : "mac", "size" : "256x256", "scale" : "2x" }, { "idiom" : "mac", "size" : "512x512", "scale" : "1x" }, { "idiom" : "mac", "size" : "512x512", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } }././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/MainViewController.h0000644000000000000000000000317614435670357021433 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import @class AudioEngine; @interface MainViewController : NSViewController @property (weak) IBOutlet NSButton *startAudioButton; @property (weak) IBOutlet NSButton *recordAudioButton; @property (weak) IBOutlet NSLevelIndicator *cpuIndicator; @property (nonatomic, strong) AudioEngine *audioEngine; @property (weak) IBOutlet NSTextField *paramOneValue; @property (weak) IBOutlet NSTextField *paramTwoValue; @property (weak) IBOutlet NSTextField *paramThreeValue; @property (weak) IBOutlet NSTextField *paramFourValue; @property (weak) IBOutlet NSSlider *paramOneSlider; @property (weak) IBOutlet NSSlider *paramTwoSlider; @property (weak) IBOutlet NSSlider *paramThreeSlider; @property (weak) IBOutlet NSSlider *paramFourSlider; - (void)destroy; - (IBAction)onStartAudio:(id)sender; - (IBAction)onRecordAudio:(id)sender; - (IBAction)onSliderDidChange:(id)sender; - (void)updateCpuWithDuration:(NSTimeInterval)i andFraction:(double)p; @end ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/MainViewController.m0000644000000000000000000000552614435670357021441 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import "MainViewController.h" #import "AudioEngine.h" @interface MainViewController () @end @implementation MainViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.audioEngine = [[AudioEngine alloc] initWithView:self]; } return self; } - (void)loadView { [super loadView]; [self.paramOneValue setStringValue:[self.paramOneSlider stringValue]]; [self.paramTwoValue setStringValue:[self.paramTwoSlider stringValue]]; [self.paramThreeValue setStringValue:[self.paramThreeSlider stringValue]]; [self.paramFourValue setStringValue:[self.paramFourSlider stringValue]]; } - (void)destroy { [self.audioEngine destroy]; } - (IBAction)onStartAudio:(id)sender { if ([self.startAudioButton state] == 1) { [self.audioEngine start]; } else { [self.audioEngine stop]; } } - (IBAction)onRecordAudio:(id)sender { if ([self.recordAudioButton state] == 1) { [self.audioEngine recordAudioToFile:@"~/Desktop/Heavy_OSX.wav".stringByStandardizingPath]; } else { [self.audioEngine stopRecordingAudio]; } } - (IBAction)onSliderDidChange:(id)sender { float sliderValue = [sender floatValue]; NSString *valueString = [NSString stringWithFormat:@"%.2f", sliderValue]; if ([sender isEqualTo:self.paramOneSlider]) { [self.paramOneValue setStringValue:valueString]; [self.audioEngine sendFloat:sliderValue toReceiver:@"Channel-A"]; } else if ([sender isEqualTo:self.paramTwoSlider]) { [self.paramTwoValue setStringValue:valueString]; [self.audioEngine sendFloat:sliderValue toReceiver:@"Channel-B"]; } else if ([sender isEqualTo:self.paramThreeSlider]) { [self.paramThreeValue setStringValue:valueString]; [self.audioEngine sendFloat:sliderValue toReceiver:@"Channel-C"]; } else if ([sender isEqualTo:self.paramFourSlider]) { [self.paramFourValue setStringValue:valueString]; [self.audioEngine sendFloat:sliderValue toReceiver:@"Channel-D"]; } } - (void)updateCpuWithDuration:(NSTimeInterval)i andFraction:(double)p { [self.cpuIndicator setDoubleValue:10.0*log10(p) + 40.0]; } @end ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/MainViewController.xib0000644000000000000000000003753014435670357021767 0ustar00 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/Views/nuklear/nuklear_glfw_gl3.h0000644000000000000000000004341014435670357023626 0ustar00/* * Nuklear - 1.32.0 - public domain * no warrenty implied; use at your own risk. * authored from 2015-2016 by Micha Mettke */ /* * ============================================================== * * API * * =============================================================== */ #ifndef NK_GLFW_GL3_H_ #define NK_GLFW_GL3_H_ #include enum nk_glfw_init_state{ NK_GLFW3_DEFAULT=0, NK_GLFW3_INSTALL_CALLBACKS }; NK_API struct nk_context* nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state); NK_API void nk_glfw3_shutdown(void); NK_API void nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas); NK_API void nk_glfw3_font_stash_end(void); NK_API void nk_glfw3_new_frame(void); NK_API void nk_glfw3_render(enum nk_anti_aliasing, int max_vertex_buffer, int max_element_buffer); NK_API void nk_glfw3_device_destroy(void); NK_API void nk_glfw3_device_create(void); NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint); NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff); NK_API void nk_glfw3_mouse_button_callback(GLFWwindow *win, int button, int action, int mods); #endif /* * ============================================================== * * IMPLEMENTATION * * =============================================================== */ #ifdef NK_GLFW_GL3_IMPLEMENTATION #ifndef NK_GLFW_TEXT_MAX #define NK_GLFW_TEXT_MAX 256 #endif #ifndef NK_GLFW_DOUBLE_CLICK_LO #define NK_GLFW_DOUBLE_CLICK_LO 0.02 #endif #ifndef NK_GLFW_DOUBLE_CLICK_HI #define NK_GLFW_DOUBLE_CLICK_HI 0.2 #endif struct nk_glfw_device { struct nk_buffer cmds; struct nk_draw_null_texture null; GLuint vbo, vao, ebo; GLuint prog; GLuint vert_shdr; GLuint frag_shdr; GLint attrib_pos; GLint attrib_uv; GLint attrib_col; GLint uniform_tex; GLint uniform_proj; GLuint font_tex; }; struct nk_glfw_vertex { float position[2]; float uv[2]; nk_byte col[4]; }; static struct nk_glfw { GLFWwindow *win; int width, height; int display_width, display_height; struct nk_glfw_device ogl; struct nk_context ctx; struct nk_font_atlas atlas; struct nk_vec2 fb_scale; unsigned int text[NK_GLFW_TEXT_MAX]; int text_len; struct nk_vec2 scroll; double last_button_click; int is_double_click_down; struct nk_vec2 double_click_pos; } glfw; #ifdef __APPLE__ #define NK_SHADER_VERSION "#version 150\n" #else #define NK_SHADER_VERSION "#version 300 es\n" #endif NK_API void nk_glfw3_device_create(void) { GLint status; static const GLchar *vertex_shader = NK_SHADER_VERSION "uniform mat4 ProjMtx;\n" "in vec2 Position;\n" "in vec2 TexCoord;\n" "in vec4 Color;\n" "out vec2 Frag_UV;\n" "out vec4 Frag_Color;\n" "void main() {\n" " Frag_UV = TexCoord;\n" " Frag_Color = Color;\n" " gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n" "}\n"; static const GLchar *fragment_shader = NK_SHADER_VERSION "precision mediump float;\n" "uniform sampler2D Texture;\n" "in vec2 Frag_UV;\n" "in vec4 Frag_Color;\n" "out vec4 Out_Color;\n" "void main(){\n" " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" "}\n"; struct nk_glfw_device *dev = &glfw.ogl; nk_buffer_init_default(&dev->cmds); dev->prog = glCreateProgram(); dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0); glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0); glCompileShader(dev->vert_shdr); glCompileShader(dev->frag_shdr); glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status); assert(status == GL_TRUE); glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status); assert(status == GL_TRUE); glAttachShader(dev->prog, dev->vert_shdr); glAttachShader(dev->prog, dev->frag_shdr); glLinkProgram(dev->prog); glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); assert(status == GL_TRUE); dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); { /* buffer setup */ GLsizei vs = sizeof(struct nk_glfw_vertex); size_t vp = offsetof(struct nk_glfw_vertex, position); size_t vt = offsetof(struct nk_glfw_vertex, uv); size_t vc = offsetof(struct nk_glfw_vertex, col); glGenBuffers(1, &dev->vbo); glGenBuffers(1, &dev->ebo); glGenVertexArrays(1, &dev->vao); glBindVertexArray(dev->vao); glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); glEnableVertexAttribArray((GLuint)dev->attrib_pos); glEnableVertexAttribArray((GLuint)dev->attrib_uv); glEnableVertexAttribArray((GLuint)dev->attrib_col); glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); } glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindVertexArray(0); } NK_INTERN void nk_glfw3_device_upload_atlas(const void *image, int width, int height) { struct nk_glfw_device *dev = &glfw.ogl; glGenTextures(1, &dev->font_tex); glBindTexture(GL_TEXTURE_2D, dev->font_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); } NK_API void nk_glfw3_device_destroy(void) { struct nk_glfw_device *dev = &glfw.ogl; glDetachShader(dev->prog, dev->vert_shdr); glDetachShader(dev->prog, dev->frag_shdr); glDeleteShader(dev->vert_shdr); glDeleteShader(dev->frag_shdr); glDeleteProgram(dev->prog); glDeleteTextures(1, &dev->font_tex); glDeleteBuffers(1, &dev->vbo); glDeleteBuffers(1, &dev->ebo); nk_buffer_free(&dev->cmds); } NK_API void nk_glfw3_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer) { struct nk_glfw_device *dev = &glfw.ogl; struct nk_buffer vbuf, ebuf; GLfloat ortho[4][4] = { {2.0f, 0.0f, 0.0f, 0.0f}, {0.0f,-2.0f, 0.0f, 0.0f}, {0.0f, 0.0f,-1.0f, 0.0f}, {-1.0f,1.0f, 0.0f, 1.0f}, }; ortho[0][0] /= (GLfloat)glfw.width; ortho[1][1] /= (GLfloat)glfw.height; /* setup global state */ glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glActiveTexture(GL_TEXTURE0); /* setup program */ glUseProgram(dev->prog); glUniform1i(dev->uniform_tex, 0); glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); glViewport(0,0,(GLsizei)glfw.display_width,(GLsizei)glfw.display_height); { /* convert from command queue into draw list and draw to screen */ const struct nk_draw_command *cmd; void *vertices, *elements; const nk_draw_index *offset = NULL; /* allocate vertex and element buffer */ glBindVertexArray(dev->vao); glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); glBufferData(GL_ARRAY_BUFFER, max_vertex_buffer, NULL, GL_STREAM_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW); /* load draw vertices & elements directly into vertex + element buffer */ vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); { /* fill convert configuration */ struct nk_convert_config config; static const struct nk_draw_vertex_layout_element vertex_layout[] = { {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)}, {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)}, {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)}, {NK_VERTEX_LAYOUT_END} }; NK_MEMSET(&config, 0, sizeof(config)); config.vertex_layout = vertex_layout; config.vertex_size = sizeof(struct nk_glfw_vertex); config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex); config.null = dev->null; config.circle_segment_count = 22; config.curve_segment_count = 22; config.arc_segment_count = 22; config.global_alpha = 1.0f; config.shape_AA = AA; config.line_AA = AA; /* setup buffers to load vertices and elements */ nk_buffer_init_fixed(&vbuf, vertices, (size_t)max_vertex_buffer); nk_buffer_init_fixed(&ebuf, elements, (size_t)max_element_buffer); nk_convert(&glfw.ctx, &dev->cmds, &vbuf, &ebuf, &config); } glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); /* iterate over and execute each draw command */ nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds) { if (!cmd->elem_count) continue; glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); glScissor( (GLint)(cmd->clip_rect.x * glfw.fb_scale.x), (GLint)((glfw.height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw.fb_scale.y), (GLint)(cmd->clip_rect.w * glfw.fb_scale.x), (GLint)(cmd->clip_rect.h * glfw.fb_scale.y)); glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); offset += cmd->elem_count; } nk_clear(&glfw.ctx); } /* default OpenGL state */ glUseProgram(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindVertexArray(0); glDisable(GL_BLEND); glDisable(GL_SCISSOR_TEST); } NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint) { (void)win; if (glfw.text_len < NK_GLFW_TEXT_MAX) glfw.text[glfw.text_len++] = codepoint; } NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff) { (void)win; (void)xoff; glfw.scroll.x += (float)xoff; glfw.scroll.y += (float)yoff; } NK_API void nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int mods) { double x, y; if (button != GLFW_MOUSE_BUTTON_LEFT) return; glfwGetCursorPos(window, &x, &y); if (action == GLFW_PRESS) { double dt = glfwGetTime() - glfw.last_button_click; if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI) { glfw.is_double_click_down = nk_true; glfw.double_click_pos = nk_vec2((float)x, (float)y); } glfw.last_button_click = glfwGetTime(); } else glfw.is_double_click_down = nk_false; } NK_INTERN void nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) { const char *text = glfwGetClipboardString(glfw.win); if (text) nk_textedit_paste(edit, text, nk_strlen(text)); (void)usr; } NK_INTERN void nk_glfw3_clipbard_copy(nk_handle usr, const char *text, int len) { char *str = 0; (void)usr; if (!len) return; str = (char*)malloc((size_t)len+1); if (!str) return; memcpy(str, text, (size_t)len); str[len] = '\0'; glfwSetClipboardString(glfw.win, str); free(str); } NK_API struct nk_context* nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state) { glfw.win = win; if (init_state == NK_GLFW3_INSTALL_CALLBACKS) { glfwSetScrollCallback(win, nk_gflw3_scroll_callback); glfwSetCharCallback(win, nk_glfw3_char_callback); glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback); } nk_init_default(&glfw.ctx, 0); glfw.ctx.clip.copy = nk_glfw3_clipbard_copy; glfw.ctx.clip.paste = nk_glfw3_clipbard_paste; glfw.ctx.clip.userdata = nk_handle_ptr(0); glfw.last_button_click = 0; nk_glfw3_device_create(); glfw.is_double_click_down = nk_false; glfw.double_click_pos = nk_vec2(0, 0); return &glfw.ctx; } NK_API void nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas) { nk_font_atlas_init_default(&glfw.atlas); nk_font_atlas_begin(&glfw.atlas); *atlas = &glfw.atlas; } NK_API void nk_glfw3_font_stash_end(void) { const void *image; int w, h; image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32); nk_glfw3_device_upload_atlas(image, w, h); nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.null); if (glfw.atlas.default_font) nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle); } NK_API void nk_glfw3_new_frame(void) { int i; double x, y; struct nk_context *ctx = &glfw.ctx; struct GLFWwindow *win = glfw.win; glfwGetWindowSize(win, &glfw.width, &glfw.height); glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height); glfw.fb_scale.x = (float)glfw.display_width/(float)glfw.width; glfw.fb_scale.y = (float)glfw.display_height/(float)glfw.height; nk_input_begin(ctx); for (i = 0; i < glfw.text_len; ++i) nk_input_unicode(ctx, glfw.text[i]); #ifdef NK_GLFW_GL3_MOUSE_GRABBING /* optional grabbing behavior */ if (ctx->input.mouse.grab) glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); else if (ctx->input.mouse.ungrab) glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_NORMAL); #endif nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS|| glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS); if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) { nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS); } else { nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS); nk_input_key(ctx, NK_KEY_COPY, 0); nk_input_key(ctx, NK_KEY_PASTE, 0); nk_input_key(ctx, NK_KEY_CUT, 0); nk_input_key(ctx, NK_KEY_SHIFT, 0); } glfwGetCursorPos(win, &x, &y); nk_input_motion(ctx, (int)x, (int)y); #ifdef NK_GLFW_GL3_MOUSE_GRABBING if (ctx->input.mouse.grabbed) { glfwSetCursorPos(glfw.win, ctx->input.mouse.prev.x, ctx->input.mouse.prev.y); ctx->input.mouse.pos.x = ctx->input.mouse.prev.x; ctx->input.mouse.pos.y = ctx->input.mouse.prev.y; } #endif nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS); nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS); nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS); nk_input_button(ctx, NK_BUTTON_DOUBLE, (int)glfw.double_click_pos.x, (int)glfw.double_click_pos.y, glfw.is_double_click_down); nk_input_scroll(ctx, glfw.scroll); nk_input_end(&glfw.ctx); glfw.text_len = 0; glfw.scroll = nk_vec2(0,0); } NK_API void nk_glfw3_shutdown(void) { nk_font_atlas_clear(&glfw.atlas); nk_free(&glfw.ctx); nk_glfw3_device_destroy(); memset(&glfw, 0, sizeof(glfw)); } #endif ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/en.lproj/Credits.rtf0000644000000000000000000000066414435670357021337 0ustar00{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} {\colortbl;\red255\green255\blue255;} \paperw9840\paperh8400 \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\b\fs24 \cf0 Engineering: \b0 \ Some people\ \ \b Human Interface Design: \b0 \ Some other people\ \ \b Testing: \b0 \ Hopefully not nobody\ \ \b Documentation: \b0 \ Whoever\ \ \b With special thanks to: \b0 \ Mom\ } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/en.lproj/InfoPlist.strings0000644000000000000000000000005514435670357022541 0ustar00/* Localized versions of Info.plist keys */ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/main.m0000644000000000000000000000145114435670357016573 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import int main(int argc, const char * argv[]) { return NSApplicationMain(argc, argv); } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/tinywav/tinywav.c0000644000000000000000000001061514435670357021041 0ustar00/** * Copyright (c) 2015, Martin Roth (mhroth@gmail.com) * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include #include "tinywav.h" typedef struct TinyWavHeader { uint32_t ChunkID; uint32_t ChunkSize; uint32_t Format; uint32_t Subchunk1ID; uint32_t Subchunk1Size; uint16_t AudioFormat; uint16_t NumChannels; uint32_t SampleRate; uint32_t ByteRate; uint16_t BlockAlign; uint16_t BitsPerSample; uint32_t Subchunk2ID; uint32_t Subchunk2Size; } TinyWavHeader; int tinywav_new(TinyWav *tw, int16_t numChannels, int32_t samplerate, TinyWavSampleFormat sampFmt, TinyWavChannelFormat chanFmt, const char *path) { tw->f = fopen(path, "w"); tw->numChannels = numChannels; tw->totalFramesWritten = 0; tw->sampFmt = sampFmt; tw->chanFmt = chanFmt; // prepare WAV header TinyWavHeader h; h.ChunkID = htonl(0x52494646); // "RIFF" h.ChunkSize = 0; // fill this in on file-close h.Format = htonl(0x57415645); // "WAVE" h.Subchunk1ID = htonl(0x666d7420); // "fmt " h.Subchunk1Size = 16; // PCM h.AudioFormat = (tw->sampFmt-1); // 1 PCM, 3 IEEE float h.NumChannels = numChannels; h.SampleRate = samplerate; h.ByteRate = samplerate * numChannels * tw->sampFmt; h.BlockAlign = numChannels * tw->sampFmt; h.BitsPerSample = 8*tw->sampFmt; h.Subchunk2ID = htonl(0x64617461); // "data" h.Subchunk2Size = 0; // fill this in on file-close // write WAV header fwrite(&h, sizeof(TinyWavHeader), 1, tw->f); return 0; } size_t tinywav_write_f(TinyWav *tw, void *f, int len) { switch (tw->sampFmt) { case TW_INT16: { int16_t z[tw->numChannels*len]; switch (tw->chanFmt) { case TW_INTERLEAVED: { return 0; } case TW_INLINE: { const float *const x = (const float *const) f; for (int i = 0, k = 0; i < len; ++i) { for (int j = 0; j < tw->numChannels; ++j) { z[k++] = (int16_t) (x[j*len+i] * 32767.0f); } } break; } case TW_SPLIT: { const float **const x = (const float **const) f; for (int i = 0, k = 0; i < len; ++i) { for (int j = 0; j < tw->numChannels; ++j) { z[k++] = (int16_t) (x[j][i] * 32767.0f); } } break; } default: return 0; } tw->totalFramesWritten += len; return fwrite(z, sizeof(int16_t), tw->numChannels*len, tw->f); break; } case TW_FLOAT32: { float z[tw->numChannels*len]; switch (tw->chanFmt) { case TW_INTERLEAVED: { return 0; } case TW_INLINE: { const float *const x = (const float *const) f; for (int i = 0, k = 0; i < len; ++i) { for (int j = 0; j < tw->numChannels; ++j) { z[k++] = x[j*len+i]; } } break; } case TW_SPLIT: { const float **const x = (const float **const) f; for (int i = 0, k = 0; i < len; ++i) { for (int j = 0; j < tw->numChannels; ++j) { z[k++] = x[j][i]; } } break; } default: return 0; } tw->totalFramesWritten += len; return fwrite(z, sizeof(float), tw->numChannels*len, tw->f); } default: return 0; } } void tinywav_close(TinyWav *tw) { uint32_t data_len = tw->totalFramesWritten * tw->numChannels * tw->sampFmt; // set length of data fseek(tw->f, 4, SEEK_SET); uint32_t chunkSize_len = 36 + data_len; fwrite(&chunkSize_len, sizeof(uint32_t), 1, tw->f); fseek(tw->f, 40, SEEK_SET); fwrite(&data_len, sizeof(uint32_t), 1, tw->f); fclose(tw->f); tw->f = NULL; } bool tinywav_isOpen(TinyWav *tw) { return (tw->f != NULL); } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_OSX/tinywav/tinywav.h0000644000000000000000000000364414435670357021052 0ustar00/** * Copyright (c) 2015, Martin Roth (mhroth@gmail.com) * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _TINY_WAV_ #define _TINY_WAV_ #include #include #include #ifdef __cplusplus extern "C" { #endif // http://soundfile.sapp.org/doc/WaveFormat/ // http://www-mmsp.ece.mcgill.ca/documents/AudioFormats/WAVE/WAVE.html typedef enum TinyWavChannelFormat { TW_INTERLEAVED, // channel buffer is interleaved e.g. [LRLRLRLR] TW_INLINE, // channel buffer is inlined e.g. [LLLLRRRR] TW_SPLIT // channel buffer is split e.g. [[LLLL],[RRRR]] } TinyWavChannelFormat; typedef enum TinyWavSampleFormat { TW_INT16 = 2, // two byte signed integer TW_FLOAT32 = 4 // four byte IEEE float } TinyWavSampleFormat; typedef struct TinyWav { FILE *f; int16_t numChannels; uint32_t totalFramesWritten; TinyWavChannelFormat chanFmt; TinyWavSampleFormat sampFmt; } TinyWav; int tinywav_new(TinyWav *tw, int16_t numChannels, int32_t samplerate, TinyWavSampleFormat sampFmt, TinyWavChannelFormat chanFmt, const char *path); size_t tinywav_write_f(TinyWav *tw, void *f, int len); void tinywav_close(TinyWav *tw); bool tinywav_isOpen(TinyWav *tw); #ifdef __cplusplus } #endif #endif // _TINY_WAV_ ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/AppDelegate.h0000644000000000000000000000151214435670357020034 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/AppDelegate.m0000644000000000000000000000531114435670357020042 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import "AppDelegate.h" #import "HeavyAudio.h" @interface AppDelegate() { HeavyAudio *heavyAudio; } @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { heavyAudio = [[HeavyAudio alloc] init]; [heavyAudio initialiseAudioSession]; [heavyAudio initialiseAudioUnit]; dispatch_async(dispatch_get_main_queue(), ^{ [heavyAudio play]; }); return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/Base.lproj/LaunchScreen.xib0000644000000000000000000000716614435670357022600 0ustar00 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/Base.lproj/Main.storyboard0000644000000000000000000000304714435670357022512 0ustar00 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/HeavyAudio.h0000644000000000000000000000163114435670357017721 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import @interface HeavyAudio : NSObject - (void)initialiseAudioSession; - (void)initialiseAudioUnit; - (void)play; - (void)pause; - (void)overrideOutputToSpeaker:(BOOL)shouldOverride; @end ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/HeavyAudio.m0000644000000000000000000003250314435670357017730 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import #import #import "HeavyAudio.h" #include "TPCircularBuffer.h" #import "Heavy_heavy.h" #define SAMPLE_RATE 44100.0 #define BLOCK_SIZE 1024 @interface HeavyAudio() { @public @private AudioUnit audioUnit; TPCircularBuffer inputQueue; HeavyContextInterface *hv; } @end @implementation HeavyAudio static void printHook(HeavyContextInterface *context, const char *printName, const char *str, const HvMessage *msg) { NSLog(@"> [%s@%0.3fms] %s", printName, hv_getCurrentTime(context), str); } static void sendHook(HeavyContextInterface *context, const char *sendName, hv_uint32_t sendHash, const HvMessage *msg) { NSLog(@"> [%s@%0.3fms] received message via sendhook", sendName, hv_getCurrentTime(context)); } - (HeavyAudio *)init { self = [super init]; if (self != nil) { hv = hv_heavy_new(SAMPLE_RATE); // assert that the patch isn't claiming more input or output channels than we care to support assert(hv_getNumInputChannels(hv) < 2); // 0 or 1 if (hv_getNumInputChannels(hv) >= 2) { NSLog(@"WARNING: Heavy requires more than one channel of input. " "This is NOT supported by this code. Undefined behaviour will result."); } assert(hv_getNumOutputChannels(hv) <= 2); // 0, 1, or 2 // make input queue 4 times larger than necessary to protect against IO jitter // NOTE(mhroth): buffer length should never be zero TPCircularBufferInit( &inputQueue, MAX(1,hv_getNumInputChannels(hv)) * BLOCK_SIZE * 4 * sizeof(Float32)); hv_setPrintHook(hv, printHook); // hv_setSendHook(hv, sendHook); hv_setUserData(hv, (__bridge void *) self); } return self; } - (void)dealloc { hv_delete(hv); TPCircularBufferCleanup(&inputQueue); } - (void)initialiseAudioSession { NSError *error = nil; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:&error]; [[AVAudioSession sharedInstance] setMode:AVAudioSessionModeMeasurement error:&error]; // set the preferred sample rate [[AVAudioSession sharedInstance] setPreferredSampleRate:SAMPLE_RATE error:&error]; // set the preferred block size const NSTimeInterval bufferDuration = BLOCK_SIZE / SAMPLE_RATE; // buffer duration in seconds [[AVAudioSession sharedInstance] setPreferredIOBufferDuration:bufferDuration error:&error]; // register route change and interruption listeners [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionRouteChangeListener:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionInterruptionListener:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]]; [[AVAudioSession sharedInstance] setActive:YES error:&error]; if (error == nil) { NSLog(@"++++ Audio Session successfully initialised."); } else { NSLog(@"There was an error initialising the Audio Session: %@", error.localizedDescription); } } // the interrupt listener for when the audio route changes (e.g., headphones are added or removed) // this will be preceeded by a (begin) interruption, and proceeded by an (end) interruption - (void)audioSessionRouteChangeListener:(NSNotification *)notification { NSLog(@"audioSessionRouteChangeListener: %@", notification.userInfo); } - (void)audioSessionInterruptionListener:(NSNotification *)notification { // get the interruption type NSNumber *type = [notification.userInfo objectForKey:AVAudioSessionInterruptionTypeKey]; switch (type.intValue) { case kAudioSessionEndInterruption: { NSLog(@"kAudioSessionEndInterruption: %@", notification.userInfo); break; } case kAudioSessionBeginInterruption: { NSLog(@"kAudioSessionBeginInterruption: %@", notification.userInfo); break; } default: break; } } - (void)initialiseAudioUnit { AudioComponentDescription desc; desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_RemoteIO; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; AudioComponent comp = AudioComponentFindNext(NULL, &desc); OSStatus status = AudioComponentInstanceNew(comp, &audioUnit); const UInt32 setProperty = 1; const UInt32 unsetProperty = 0; // https://developer.apple.com/library/ios/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/AudioUnitHostingFundamentals/AudioUnitHostingFundamentals.html // Enable mic status = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &setProperty, sizeof(setProperty)); // Add an output to the speaker status = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &setProperty, sizeof(setProperty)); // Set the input format to 32-bit, single channel, float, linear PCM const Float64 kSampleRate = SAMPLE_RATE; // set the sample rate on the input bus AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 1, &kSampleRate, sizeof(kSampleRate)); // set the sample rate on the output bus AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, 0, &kSampleRate, sizeof(kSampleRate)); // mono input stream from the microphone AudioStreamBasicDescription inputStreamFormat; inputStreamFormat.mSampleRate = kSampleRate; inputStreamFormat.mFormatID = kAudioFormatLinearPCM; inputStreamFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; inputStreamFormat.mBytesPerPacket = hv_getNumInputChannels(hv) * sizeof(Float32); inputStreamFormat.mFramesPerPacket = 1; inputStreamFormat.mBytesPerFrame = hv_getNumInputChannels(hv) * sizeof(Float32); inputStreamFormat.mChannelsPerFrame = hv_getNumInputChannels(hv); inputStreamFormat.mBitsPerChannel = sizeof(Float32) * 8; // Set the output format to the same as above AudioStreamBasicDescription outputStreamFormat; outputStreamFormat.mSampleRate = kSampleRate; outputStreamFormat.mFormatID = kAudioFormatLinearPCM; outputStreamFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; outputStreamFormat.mBytesPerPacket = hv_getNumOutputChannels(hv) * sizeof(Float32); outputStreamFormat.mFramesPerPacket = 1; outputStreamFormat.mBytesPerFrame = hv_getNumOutputChannels(hv) * sizeof(Float32); outputStreamFormat.mChannelsPerFrame = hv_getNumOutputChannels(hv); outputStreamFormat.mBitsPerChannel = sizeof(Float32) * 8; if (hv_getNumInputChannels(hv) > 0) { // set the input stream format status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &inputStreamFormat, sizeof(AudioStreamBasicDescription)); // Add a render callback to get input from the microphone AURenderCallbackStruct renderCallbackStructInput; renderCallbackStructInput.inputProc = inputCallback; renderCallbackStructInput.inputProcRefCon = (__bridge void *) self; status = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &renderCallbackStructInput, sizeof(renderCallbackStructInput)); } if (hv_getNumOutputChannels(hv) > 0) { // set the output stream format status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &outputStreamFormat, sizeof(AudioStreamBasicDescription)); // Add a render callback to send the output to the speaker AURenderCallbackStruct renderCallbackStructOutput; renderCallbackStructOutput.inputProc = renderCallback; renderCallbackStructOutput.inputProcRefCon = (__bridge void *) self; status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, &renderCallbackStructOutput, sizeof(renderCallbackStructOutput)); } // no need to allocate an additional AU buffer (slight increase in efficiency) status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_ShouldAllocateBuffer, kAudioUnitScope_Output, 1, &unsetProperty, sizeof(unsetProperty)); status = AudioUnitInitialize(audioUnit); } OSStatus inputCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { HeavyAudio *const heavyAudio = (__bridge HeavyAudio *) inRefCon; // get a buffer to render the input audio into const int32_t required = hv_getNumInputChannels(heavyAudio->hv) * inNumberFrames * sizeof(Float32); int32_t available = 0; Float32 *const inputBuffers = (Float32 *) TPCircularBufferHead(&heavyAudio->inputQueue, &available); if (available < required) { NSLog(@"inputCallback: available %i < required %i", available, required); return noErr; } // prepare a buffer to render the microphone data into AudioBuffer ab; ab.mNumberChannels = hv_getNumInputChannels(heavyAudio->hv); ab.mDataByteSize = hv_getNumInputChannels(heavyAudio->hv) * inNumberFrames * sizeof(Float32); ab.mData = inputBuffers; AudioBufferList list; list.mNumberBuffers = 1; list.mBuffers[0] = ab; // render the microphone data into the buffer AudioUnitRender(heavyAudio->audioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, &list); TPCircularBufferProduce(&heavyAudio->inputQueue, required); return noErr; } OSStatus renderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { // counters for average CPU usage static double frameCount = 0.0; static double tickCount = 0.0; const double tick_rc = CFAbsoluteTimeGetCurrent(); HeavyAudio *const heavyAudio = (__bridge HeavyAudio *) inRefCon; // consume the input in the circular buffer and render the output int32_t available = 0; Float32 *inputBuffers = TPCircularBufferTail(&heavyAudio->inputQueue, &available); const int32_t required = hv_getNumInputChannels(heavyAudio->hv) * inNumberFrames * sizeof(Float32); if (available < required) { NSLog(@"renderCallback: available %i < required %i", available, required); return noErr; } double tock = 0.0; switch (hv_getNumOutputChannels(heavyAudio->hv)) { case 1: { const double tick = CFAbsoluteTimeGetCurrent(); hv_process(heavyAudio->hv, &inputBuffers, (Float32 **) &(ioData->mBuffers[0].mData), inNumberFrames); tock = CFAbsoluteTimeGetCurrent() - tick; break; } case 2: { Float32 *outputBuffers[2] = { (Float32 *) alloca(inNumberFrames * sizeof(Float32)), (Float32 *) alloca(inNumberFrames * sizeof(Float32)) }; // process Heavy const double tick = CFAbsoluteTimeGetCurrent(); hv_process(heavyAudio->hv, &inputBuffers, outputBuffers, inNumberFrames); tock = CFAbsoluteTimeGetCurrent() - tick; vDSP_ztoc((DSPSplitComplex *) outputBuffers, 1, (DSPComplex *) ioData->mBuffers[0].mData, 2, inNumberFrames); break; } default: break; } TPCircularBufferConsume(&heavyAudio->inputQueue, required); tickCount += tock; frameCount += (double) inNumberFrames; const double tock_rc = CFAbsoluteTimeGetCurrent() - tick_rc; NSLog(@"%iµs (%iµs) @ %i/%gHz (%0.3f%% CPU) [%0.3f%% avgCPU]", (int) (1000000.0 * tock), // execution time of heavy callback (int) (1000000.0 * tock_rc), // execution time of entire render callback (int) inNumberFrames, hv_getSampleRate(heavyAudio->hv), 100.0*(tock/(inNumberFrames/hv_getSampleRate(heavyAudio->hv))), 100.0*(tickCount/(frameCount/hv_getSampleRate(heavyAudio->hv)))); return noErr; } - (void)play { AudioOutputUnitStart(audioUnit); } - (void)pause { AudioOutputUnitStop(audioUnit); } - (void)overrideOutputToSpeaker:(BOOL)shouldOverride { NSError *error = nil; AVAudioSessionPortOverride portOverride = shouldOverride ? AVAudioSessionPortOverrideSpeaker : AVAudioSessionPortOverrideNone; [[AVAudioSession sharedInstance] overrideOutputAudioPort:portOverride error:&error]; if (error != nil) { NSLog(@"Error while overriding the AudioSession route: %@", error.localizedDescription); } } @end ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/Images.xcassets/AppIcon.appiconset/Contents.json0000644000000000000000000000206514435670357026742 0ustar00{ "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } }././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/Info.plist0000644000000000000000000000305014435670357017457 0ustar00 NSMicrophoneUsageDescription Need mic for testing! CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/TPCircularBuffer.c0000644000000000000000000001355314435670357021026 0ustar00// // TPCircularBuffer.c // Circular/Ring buffer implementation // // https://github.com/michaeltyson/TPCircularBuffer // // Created by Michael Tyson on 10/12/2011. // // Copyright (C) 2012-2013 A Tasty Pixel // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would be // appreciated but is not required. // // 2. Altered source versions must be plainly marked as such, and must not be // misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source distribution. // #include "TPCircularBuffer.h" #include #include #include #define reportResult(result,operation) (_reportResult((result),(operation),strrchr(__FILE__, '/')+1,__LINE__)) static inline bool _reportResult(kern_return_t result, const char *operation, const char* file, int line) { if ( result != ERR_SUCCESS ) { printf("%s:%d: %s: %s\n", file, line, operation, mach_error_string(result)); return false; } return true; } bool _TPCircularBufferInit(TPCircularBuffer *buffer, int32_t length, size_t structSize) { assert(length > 0); if ( structSize != sizeof(TPCircularBuffer) ) { fprintf(stderr, "TPCircularBuffer: Header version mismatch. Check for old versions of TPCircularBuffer in your project\n"); abort(); } // Keep trying until we get our buffer, needed to handle race conditions int retries = 3; while ( true ) { buffer->length = (int32_t)round_page(length); // We need whole page sizes // Temporarily allocate twice the length, so we have the contiguous address space to // support a second instance of the buffer directly after vm_address_t bufferAddress; kern_return_t result = vm_allocate(mach_task_self(), &bufferAddress, buffer->length * 2, VM_FLAGS_ANYWHERE); // allocate anywhere it'll fit if ( result != ERR_SUCCESS ) { if ( retries-- == 0 ) { reportResult(result, "Buffer allocation"); return false; } // Try again if we fail continue; } // Now replace the second half of the allocation with a virtual copy of the first half. Deallocate the second half... result = vm_deallocate(mach_task_self(), bufferAddress + buffer->length, buffer->length); if ( result != ERR_SUCCESS ) { if ( retries-- == 0 ) { reportResult(result, "Buffer deallocation"); return false; } // If this fails somehow, deallocate the whole region and try again vm_deallocate(mach_task_self(), bufferAddress, buffer->length); continue; } // Re-map the buffer to the address space immediately after the buffer vm_address_t virtualAddress = bufferAddress + buffer->length; vm_prot_t cur_prot, max_prot; result = vm_remap(mach_task_self(), &virtualAddress, // mirror target buffer->length, // size of mirror 0, // auto alignment 0, // force remapping to virtualAddress mach_task_self(), // same task bufferAddress, // mirror source 0, // MAP READ-WRITE, NOT COPY &cur_prot, // unused protection struct &max_prot, // unused protection struct VM_INHERIT_DEFAULT); if ( result != ERR_SUCCESS ) { if ( retries-- == 0 ) { reportResult(result, "Remap buffer memory"); return false; } // If this remap failed, we hit a race condition, so deallocate and try again vm_deallocate(mach_task_self(), bufferAddress, buffer->length); continue; } if ( virtualAddress != bufferAddress+buffer->length ) { // If the memory is not contiguous, clean up both allocated buffers and try again if ( retries-- == 0 ) { printf("Couldn't map buffer memory to end of buffer\n"); return false; } vm_deallocate(mach_task_self(), virtualAddress, buffer->length); vm_deallocate(mach_task_self(), bufferAddress, buffer->length); continue; } buffer->buffer = (void*)bufferAddress; buffer->fillCount = 0; buffer->head = buffer->tail = 0; buffer->atomic = true; return true; } return false; } void TPCircularBufferCleanup(TPCircularBuffer *buffer) { vm_deallocate(mach_task_self(), (vm_address_t)buffer->buffer, buffer->length * 2); memset(buffer, 0, sizeof(TPCircularBuffer)); } void TPCircularBufferClear(TPCircularBuffer *buffer) { int32_t fillCount; if ( TPCircularBufferTail(buffer, &fillCount) ) { TPCircularBufferConsume(buffer, fillCount); } } void TPCircularBufferSetAtomic(TPCircularBuffer *buffer, bool atomic) { buffer->atomic = atomic; } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/TPCircularBuffer.h0000644000000000000000000001640414435670357021031 0ustar00// // TPCircularBuffer.h // Circular/Ring buffer implementation // // https://github.com/michaeltyson/TPCircularBuffer // // Created by Michael Tyson on 10/12/2011. // // // This implementation makes use of a virtual memory mapping technique that inserts a virtual copy // of the buffer memory directly after the buffer's end, negating the need for any buffer wrap-around // logic. Clients can simply use the returned memory address as if it were contiguous space. // // The implementation is thread-safe in the case of a single producer and single consumer. // // Virtual memory technique originally proposed by Philip Howard (http://vrb.slashusr.org/), and // adapted to Darwin by Kurt Revis (http://www.snoize.com, // http://www.snoize.com/Code/PlayBufferedSoundFile.tar.gz) // // // Copyright (C) 2012-2013 A Tasty Pixel // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would be // appreciated but is not required. // // 2. Altered source versions must be plainly marked as such, and must not be // misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source distribution. // #ifndef TPCircularBuffer_h #define TPCircularBuffer_h #include #include #include #ifdef __cplusplus extern "C" { #endif typedef struct { void *buffer; int32_t length; int32_t tail; int32_t head; volatile int32_t fillCount; bool atomic; } TPCircularBuffer; /*! * Initialise buffer * * Note that the length is advisory only: Because of the way the * memory mirroring technique works, the true buffer length will * be multiples of the device page size (e.g. 4096 bytes) * * @param buffer Circular buffer * @param length Length of buffer */ #define TPCircularBufferInit(buffer, length) \ _TPCircularBufferInit(buffer, length, sizeof(*buffer)) bool _TPCircularBufferInit(TPCircularBuffer *buffer, int32_t length, size_t structSize); /*! * Cleanup buffer * * Releases buffer resources. */ void TPCircularBufferCleanup(TPCircularBuffer *buffer); /*! * Clear buffer * * Resets buffer to original, empty state. * * This is safe for use by consumer while producer is accessing * buffer. */ void TPCircularBufferClear(TPCircularBuffer *buffer); /*! * Set the atomicity * * If you set the atomiticy to false using this method, the buffer will * not use atomic operations. This can be used to give the compiler a little * more optimisation opportunities when the buffer is only used on one thread. * * Important note: Only set this to false if you know what you're doing! * * The default value is true (the buffer will use atomic operations) * * @param buffer Circular buffer * @param atomic Whether the buffer is atomic (default true) */ void TPCircularBufferSetAtomic(TPCircularBuffer *buffer, bool atomic); // Reading (consuming) /*! * Access end of buffer * * This gives you a pointer to the end of the buffer, ready * for reading, and the number of available bytes to read. * * @param buffer Circular buffer * @param availableBytes On output, the number of bytes ready for reading * @return Pointer to the first bytes ready for reading, or NULL if buffer is empty */ static __inline__ __attribute__((always_inline)) void* TPCircularBufferTail(TPCircularBuffer *buffer, int32_t* availableBytes) { *availableBytes = buffer->fillCount; if ( *availableBytes == 0 ) return NULL; return (void*)((char*)buffer->buffer + buffer->tail); } /*! * Consume bytes in buffer * * This frees up the just-read bytes, ready for writing again. * * @param buffer Circular buffer * @param amount Number of bytes to consume */ static __inline__ __attribute__((always_inline)) void TPCircularBufferConsume(TPCircularBuffer *buffer, int32_t amount) { buffer->tail = (buffer->tail + amount) % buffer->length; if ( buffer->atomic ) { OSAtomicAdd32Barrier(-amount, &buffer->fillCount); } else { buffer->fillCount -= amount; } assert(buffer->fillCount >= 0); } /*! * Access front of buffer * * This gives you a pointer to the front of the buffer, ready * for writing, and the number of available bytes to write. * * @param buffer Circular buffer * @param availableBytes On output, the number of bytes ready for writing * @return Pointer to the first bytes ready for writing, or NULL if buffer is full */ static __inline__ __attribute__((always_inline)) void* TPCircularBufferHead(TPCircularBuffer *buffer, int32_t* availableBytes) { *availableBytes = (buffer->length - buffer->fillCount); if ( *availableBytes == 0 ) return NULL; return (void*)((char*)buffer->buffer + buffer->head); } // Writing (producing) /*! * Produce bytes in buffer * * This marks the given section of the buffer ready for reading. * * @param buffer Circular buffer * @param amount Number of bytes to produce */ static __inline__ __attribute__((always_inline)) void TPCircularBufferProduce(TPCircularBuffer *buffer, int32_t amount) { buffer->head = (buffer->head + amount) % buffer->length; if ( buffer->atomic ) { OSAtomicAdd32Barrier(amount, &buffer->fillCount); } else { buffer->fillCount += amount; } assert(buffer->fillCount <= buffer->length); } /*! * Helper routine to copy bytes to buffer * * This copies the given bytes to the buffer, and marks them ready for reading. * * @param buffer Circular buffer * @param src Source buffer * @param len Number of bytes in source buffer * @return true if bytes copied, false if there was insufficient space */ static __inline__ __attribute__((always_inline)) bool TPCircularBufferProduceBytes(TPCircularBuffer *buffer, const void* src, int32_t len) { int32_t space; void *ptr = TPCircularBufferHead(buffer, &space); if ( space < len ) return false; memcpy(ptr, src, len); TPCircularBufferProduce(buffer, len); return true; } /*! * Deprecated method */ static __inline__ __attribute__((always_inline)) __deprecated_msg("use TPCircularBufferSetAtomic(false) and TPCircularBufferConsume instead") void TPCircularBufferConsumeNoBarrier(TPCircularBuffer *buffer, int32_t amount) { buffer->tail = (buffer->tail + amount) % buffer->length; buffer->fillCount -= amount; assert(buffer->fillCount >= 0); } /*! * Deprecated method */ static __inline__ __attribute__((always_inline)) __deprecated_msg("use TPCircularBufferSetAtomic(false) and TPCircularBufferProduce instead") void TPCircularBufferProduceNoBarrier(TPCircularBuffer *buffer, int32_t amount) { buffer->head = (buffer->head + amount) % buffer->length; buffer->fillCount += amount; assert(buffer->fillCount <= buffer->length); } #ifdef __cplusplus } #endif #endif ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.767207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/ViewController.h0000644000000000000000000000141114435670357020635 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import @interface ViewController : UIViewController @end ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.768207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/ViewController.m0000644000000000000000000000203114435670357020641 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.768207 hvcc-0.13.3/hvcc/generators/xcode/Heavy_iOS/main.m0000644000000000000000000000160514435670357016615 0ustar00/** * Copyright (C) 2014-2018 Enzien Audio, Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.768207 hvcc-0.13.3/hvcc/interpreters/__init__.py0000644000000000000000000000000014435670357015235 0ustar00././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.270823 hvcc-0.13.3/hvcc/interpreters/pd2hv/Connection.py0000644000000000000000000000464614735300474016635 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Dict, Optional, TYPE_CHECKING if TYPE_CHECKING: from .PdObject import PdObject class Connection: def __init__( self, from_obj: 'PdObject', outlet_index: int, to_obj: 'PdObject', inlet_index: int, conn_type: Optional[str] # not actually Optional. This is due to the requirement in HeavyObject. ) -> None: assert from_obj is not None assert to_obj is not None assert conn_type is not None self.__from_obj = from_obj self.__to_obj = to_obj self.__hv_json: Dict = { "from": { "id": from_obj.obj_id, "outlet": outlet_index }, "to": { "id": to_obj.obj_id, "inlet": inlet_index }, "type": conn_type } @property def from_obj(self) -> 'PdObject': return self.__from_obj @property def from_id(self) -> str: return self.__hv_json["from"]["id"] @property def outlet_index(self) -> int: return self.__hv_json["from"]["outlet"] @property def to_obj(self) -> 'PdObject': return self.__to_obj @property def to_id(self) -> str: return self.__hv_json["to"]["id"] @property def inlet_index(self) -> int: return self.__hv_json["to"]["inlet"] @property def conn_type(self) -> str: return self.__hv_json["type"] def to_hv(self) -> Dict: return self.__hv_json def __repr__(self) -> str: return "{0}:{1} {4} {2}:{3}".format( self.from_id, self.outlet_index, self.to_id, self.inlet_index, self.conn_type) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2765517 hvcc-0.13.3/hvcc/interpreters/pd2hv/HeavyGraph.py0000644000000000000000000000564114677551203016573 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import json import os from typing import Optional, List, Dict from .PdObject import PdObject from .HeavyObject import HeavyObject class HeavyGraph(PdObject): def __init__( self, hv_path: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: super().__init__(os.path.basename(hv_path).split(".")[0], obj_args, pos_x, pos_y) # read the heavy graph with open(hv_path, "r") as f: self.hv_json = json.load(f) # parse the heavy data structure to determine the outlet connection type outlets = [o for o in self.hv_json["objects"].values() if o["type"] == "outlet"] sorted(outlets, key=lambda o: o["args"]["index"]) self.__outlet_connection_types = [o["args"]["type"] for o in outlets] # resolve the arguments for i, a in enumerate(self.hv_json["args"]): if i < len(self.obj_args): arg_value = self.obj_args[i] elif a["required"]: self.add_error(f"Required argument \"{a['name']}\" not found.") continue else: arg_value = a["default"] try: arg_value = HeavyObject.force_arg_type(arg_value, a["value_type"]) except Exception as e: self.add_error( f"Heavy {self.obj_type} cannot convert argument \"{a['name']}\"" f" with value \"{arg_value}\" to type {a['value_type']}: {e}") # resolve all arguments for each object in the graph for o in self.hv_json["objects"].values(): for k, v in o["args"].items(): # TODO(mhroth): make resolution more robust if v == "$" + a["name"]: o["args"][k] = arg_value # reset all arguments, as they have all been resolved # any required arguments would break hv2ir as they will no longer # be supplied (because they are resolved) self.hv_json["args"] = [] def get_outlet_connection_type(self, outlet_index: int) -> str: return self.__outlet_connection_types[outlet_index] def to_hv(self) -> Dict: return self.hv_json ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.270823 hvcc-0.13.3/hvcc/interpreters/pd2hv/HeavyObject.py0000644000000000000000000002126314735300474016733 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import decimal import json import importlib_resources from typing import Optional, List, Dict, Any, Union, cast from .Connection import Connection from .NotificationEnum import NotificationEnum from .PdObject import PdObject from hvcc.types.IR import HeavyIRType, IRNode, IRArg from hvcc.types.Lang import HeavyLangType, LangNode, LangArg class HeavyObject(PdObject): heavy_lang_json = importlib_resources.files('hvcc') / 'core/json/heavy.lang.json' with open(heavy_lang_json, "r") as f: __HEAVY_LANG_OBJS = HeavyLangType(**json.load(f)).root heavy_ir_json = importlib_resources.files('hvcc') / 'core/json/heavy.ir.json' with open(heavy_ir_json, "r") as f: __HEAVY_IR_OBJS = HeavyIRType(**json.load(f)).root def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: super().__init__(obj_type, obj_args, pos_x, pos_y) self.__obj_dict: Union[IRNode, LangNode] # get the object dictionary (note that it is NOT a copy) if self.is_hvlang: self.__obj_dict = self.__HEAVY_LANG_OBJS[obj_type] elif self.is_hvir: self.__obj_dict = self.__HEAVY_IR_OBJS[obj_type] else: assert False, f"{obj_type} is not a Heavy Lang or IR object." # resolve arguments obj_args = obj_args or [] self.obj_dict = {} for i, a in enumerate(self.__obj_dict.args): arg = cast(Union[IRArg, LangArg], a) # if the argument exists (and has been correctly resolved) if i < len(obj_args) and obj_args[i] is not None: # force the Heavy argument type # Catch type errors as early as possible try: self.obj_dict[arg.name] = self.force_arg_type( obj_args[i], arg.value_type) except Exception as e: self.add_error( f"Heavy {obj_type} cannot convert argument \"{arg.name}\"" f" with value \"{obj_args[i]}\" to type {arg.value_type}: {e}") else: # the default argument is required if arg.required: self.add_error( f"Required argument \"{arg.name}\" to object {obj_type} not present: {obj_args}") else: # don't worry about supplying a default, # let hv2ir take care of it. pd2hv only passes on the # provided parameters. # self.obj_args[a["name"]] = a["default"] pass self.__annotations = {} # send/receive, table, etc. must have public scope # TODO(mhroth): dirty if obj_type in ["table", "__table", "send", "__send", "receive", "__receive"]: self.__annotations["scope"] = "public" @classmethod def force_arg_type( cls, value: str, value_type: Optional[str] = None ) -> Any: # TODO(mhroth): add support for mixedarray? if value_type == "auto": try: return float(value) except Exception: return str(value) elif value_type == "float": return float(value) elif value_type == "int": return int(decimal.Decimal(value)) elif value_type == "string": return str(value) elif value_type == "boolean": if isinstance(value, str): return value.strip().lower() not in {"false", "f", "0"} else: return bool(value) elif value_type == "floatarray": if isinstance(value, list): return [float(v) for v in value] if isinstance(value, str): return [float(v) for v in value.split()] else: raise Exception(f"Cannot convert value to type floatarray: {value}") elif value_type == "intarray": if isinstance(value, list): return [int(v) for v in value] if isinstance(value, str): return [int(v) for v in value.split()] else: raise Exception(f"Cannot convert value to type intarray: {value}") elif value_type == "stringarray": if isinstance(value, list): return [str(v) for v in value] if isinstance(value, str): return [str(v) for v in value.split()] else: raise Exception(f"Cannot convert value to type stringarray: {value}") else: # NOTE(mhroth): if value_type is not a known type or None, that is # not necessarily an error. It may simply be that the value should # not be resolved to anything other than what it already is. # This happens most often with message objects. return value @property def is_hvlang(self) -> bool: return self.obj_type in self.__HEAVY_LANG_OBJS.keys() @property def is_hvir(self) -> bool: return self.obj_type in self.__HEAVY_IR_OBJS.keys() def get_inlet_connection_type(self, inlet_index: int) -> Optional[str]: """ Returns the inlet connection type, None if the inlet does not exist. """ # TODO(mhroth): it's stupid that hvlang and hvir json have different data formats here if self.is_hvlang and isinstance(self.__obj_dict, LangNode): if len(self.__obj_dict.inlets) > inlet_index: return self.__obj_dict.inlets[inlet_index].connectionType else: return None elif self.is_hvir and isinstance(self.__obj_dict, IRNode): if len(self.__obj_dict.inlets) > inlet_index: return self.__obj_dict.inlets[inlet_index] else: return None else: return None def get_outlet_connection_type(self, outlet_index: int) -> Optional[str]: """ Returns the outlet connection type, None if the inlet does not exist. """ # TODO(mhroth): it's stupid that hvlang and hvir json have different data formats here if self.is_hvlang and isinstance(self.__obj_dict, LangNode): if len(self.__obj_dict.outlets) > outlet_index: return self.__obj_dict.outlets[outlet_index].connectionType else: return None elif self.is_hvir and isinstance(self.__obj_dict, IRNode): if len(self.__obj_dict.outlets) > outlet_index: return self.__obj_dict.outlets[outlet_index] else: return None else: return None def add_connection(self, c: Connection) -> None: """ Adds a connection, either inlet or outlet, to this object. """ if c.from_id == self.obj_id: if self.get_outlet_connection_type(c.outlet_index) is not None: self._outlet_connections[str(c.outlet_index)].append(c) else: self.add_error( f"Connection made from non-existent outlet at {self.obj_type}:{c.outlet_index}.", enum=NotificationEnum.ERROR_UNABLE_TO_CONNECT_OBJECTS) elif c.to_id == self.obj_id: if self.get_inlet_connection_type(c.inlet_index) is not None: self._inlet_connections[str(c.inlet_index)].append(c) else: self.add_error( f"Connection made to non-existent inlet at [{self.obj_type} {self.obj_dict}]:{c.inlet_index}.", enum=NotificationEnum.ERROR_UNABLE_TO_CONNECT_OBJECTS) else: raise Exception("Adding a connection to the wrong object!") def to_hv(self) -> Dict: return { "type": self.obj_type, "args": self.obj_dict, "properties": { "x": self.pos_x, "y": self.pos_y }, "annotations": self.__annotations } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2765517 hvcc-0.13.3/hvcc/interpreters/pd2hv/HvSwitchcase.py0000644000000000000000000000320014677551203017115 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, List, Dict from .PdObject import PdObject class HvSwitchcase(PdObject): def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert obj_type == "__switchcase" super().__init__(obj_type, obj_args, pos_x, pos_y) # ensure that correct case hashes are generated for i, a in enumerate(self.obj_args): try: self.obj_args[i] = float(a) except Exception: pass def get_outlet_connection_type(self, outlet_index: int = 0) -> str: return "-->" def to_hv(self) -> Dict: return { "type": "__switchcase", "args": { "cases": self.obj_args }, "properties": { "x": self.pos_x, "y": self.pos_y } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2718232 hvcc-0.13.3/hvcc/interpreters/pd2hv/NotificationEnum.py0000644000000000000000000000451114735300474020000 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from enum import Enum # http://stackoverflow.com/questions/36932/how-can-i-represent-an-enum-in-python class NotificationEnum(Enum): """ These enumerations refer to all possible warnings and errors produced by pd2hv. """ EMPTY = -1 # Warnings # an unspecified generic warning WARNING_GENERIC = 1000 # an empty object has been added to a Pd graph WARNING_EMPTY_OBJECT = 1001 # heavy only supports the -path flag to the Pd declare object WARNING_DECLARE_PATH = 1002 # the object does nothing (and will likely be removed) WARNING_USELESS_OBJECT = 1003 # the message box is empty and does nothing WARNING_EMPTY_MESSAGE = 1004 # Errors # an unspecified generic error ERROR_GENERIC = 2000 # the parser doesn't know how to handle the object ERROR_UNKNOWN_OBJECT = 2001 # top-level graphs may not contain inlet~ or outlet~ objects ERROR_NO_TOPLEVEL_SIGNAL_LETS = 2002 # only arguments 'a', 'f', 's', and 'b' are supported for trigger object ERROR_TRIGGER_ABFS = 2003 # only arguments 'f', 'float' and numeric values are supported for pack object ERROR_PACK_FLOAT_ARGUMENTS = 2003 # a value cannot be resolved because the required argument is missing ERROR_MISSING_REQUIRED_ARGUMENT = 2004 # unique arguments are required for this object ERROR_UNIQUE_ARGUMENTS_REQUIRED = 2005 # two objects cannot be connected ERROR_UNABLE_TO_CONNECT_OBJECTS = 2006 # a particular connection (type?) is not supported ERROR_UNSUPPORTED_CONNECTION = 2007 # Exception # the exception that was raised ERROR_EXCEPTION = 3000 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2765517 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdAudioIoObject.py0000644000000000000000000000361114677551203017474 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, List, Dict from .NotificationEnum import NotificationEnum from .PdObject import PdObject class PdAudioIoObject(PdObject): def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert obj_type in {"adc~", "dac~"} super().__init__(obj_type, obj_args, pos_x, pos_y) def validate_configuration(self) -> None: # ensure that only signal connections are made to the dac for i, connections in self._inlet_connections.items(): if any(c.conn_type == "-->" for c in connections): self.add_error( f"{self.obj_type} does not support control connections (inlet {i}). They should be removed.", NotificationEnum.ERROR_UNSUPPORTED_CONNECTION) def to_hv(self) -> Dict: return { "type": self.obj_type.strip("~"), "args": { "channels": [1, 2] if len(self.obj_args) == 0 else [int(a) for a in self.obj_args] }, "properties": { "x": self.pos_x, "y": self.pos_y } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2765517 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdBinopObject.py0000644000000000000000000001305414677551203017214 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, List, Dict from .Connection import Connection from .HeavyObject import HeavyObject from .PdObject import PdObject class PdBinopObject(PdObject): # a translation dictionary from a Pd object to corresponding heavy object __PD_HEAVY_DICT = { "+": "+", "+~": "+", "-": "-", "-~": "-", "*": "*", "*~": "*", "/": "/", "/~": "/", "mod": "mod", "%": "%", "max": "max", "max~": "max", "min": "min", "min~": "min", "&": "&", "&&": "&&", "|": "|", "||": "||", "==": "==", "!=": "!=", "<": "<", "<=": "<=", ">": ">", ">=": ">=", "pow": "pow", "pow~": "pow", ">>": ">>", "<<": "<<" } def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert self.is_binop(obj_type) super().__init__(obj_type, obj_args, pos_x, pos_y) @classmethod def is_binop(cls, obj_type: str) -> bool: return obj_type in cls.__PD_HEAVY_DICT @classmethod def get_supported_objects(cls) -> set: return set(cls.__PD_HEAVY_DICT.keys()) def validate_configuration(self) -> None: # check signal objects for control connections and auto insert # heavy var objects where necessary if self.obj_type.endswith("~"): # left inlet check conns_left = self._inlet_connections.get("0", []) if len(conns_left) == 0: # no left inlet connections self.convert_ctrl_to_sig_connections_at_inlet([], 0) elif (len([c for c in conns_left if c.conn_type == "~f>"]) == 0) and len(conns_left) > 0: # control connection and no sig connection self.convert_ctrl_to_sig_connections_at_inlet(conns_left, 0) # right inlet check conns_right = self._inlet_connections.get("1", []) num_signal_conns = len([c for c in conns_right if c.conn_type == "~f>"]) if len(self.obj_args) > 0 and num_signal_conns > 0: # TODO(joe): removing this connection instead of throwing an error # would be compatible with Pd's behaviour self.add_error("signal outlet connected to nonsignal inlet") if len(self.obj_args) == 0 and num_signal_conns == 0 and len(conns_right) > 0: # any arguments present will create a control type right inlet self.convert_ctrl_to_sig_connections_at_inlet(conns_right, 1) if len(self.obj_args) > 0: try: self.__k = float(self.obj_args[0]) except Exception: self.add_warning(f"\"{self.obj_args[0]}\" cannot be resolved to a number. Defaulting to zero.") self.__k = 0.0 else: self.__k = 0.0 def convert_ctrl_to_sig_connections_at_inlet(self, connection_list: List, inlet_index: int) -> None: """ Auto insert heavy var object inbetween control connections. """ sig_obj = HeavyObject(obj_type="var", obj_args=[0], pos_x=int(self.pos_x), pos_y=int(self.pos_y - 5)) # shift upwards a few points # add sig~ object to parent graph if self.parent_graph is not None: self.parent_graph.add_object(sig_obj) # add connection from sig~ to this object c = Connection(sig_obj, 0, self, inlet_index, "~f>") self.parent_graph._PdGraph__connections.append(c) # update the local connections list sig_obj.add_connection(c) self.add_connection(c) # retrieve all control connections control_conns = [c for c in connection_list if c.conn_type == "-->"] for old_conn in control_conns: # get from obj from_obj = old_conn.from_obj # add connection from fromobj to new sig new_conn = Connection(from_obj, old_conn.outlet_index, sig_obj, 0, "-->") self.parent_graph._PdGraph__connections.append(new_conn) sig_obj.add_connection(new_conn) from_obj.add_connection(new_conn) # remove connection from fromobj self.parent_graph._PdGraph__connections.remove(old_conn) from_obj.remove_connection(old_conn) self.remove_connection(old_conn) def to_hv(self) -> Dict: return { "type": self.__PD_HEAVY_DICT[self.obj_type], "args": { "k": self.__k }, "properties": { "x": self.pos_x, "y": self.pos_y } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2718232 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdGraph.py0000644000000000000000000002236114735300474016055 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os from typing import Optional, List, Dict, Any from .Connection import Connection from .NotificationEnum import NotificationEnum from .PdObject import PdObject from hvcc.types.compiler import CompilerNotif class PdGraph(PdObject): def __init__( self, obj_args: List, pd_path: str, pos_x: int = 0, pos_y: int = 0 ) -> None: assert len(obj_args) > 0, "PdGraph arguments must contain at least dollar zero." super().__init__("graph", obj_args, pos_x, pos_y) # file location of this graph self.__pd_path = pd_path self.__objs: List[PdObject] = [] self.__connections: List[Connection] = [] self.__inlet_objects: List = [] self.__outlet_objects: List = [] # the first search path is always the directory of this graph self.__declared_paths: List = [os.path.dirname(pd_path)] # heavy graph arguments (added via @hv_arg flag in #X text) self.hv_args: List = [] # the subpatch name of this graph # only used is this graph is actually a subpatch self.subpatch_name: Optional[str] = None # TODO(dromer) these are virtual attributes that are only instantiated with internal representation self._PdGraph__connections: List[Connection] = [] self._PdGraph__pd_path: str = "" @property def dollar_zero(self) -> str: return self.obj_args[0] @property def is_root(self) -> bool: return self.parent_graph is None @property def is_subpatch(self) -> bool: if self.parent_graph is None: return False else: return self.parent_graph.__pd_path == self.__pd_path if not self.is_root else False def add_object(self, obj: PdObject) -> int: obj.parent_graph = self self.__objs.append(obj) if obj.obj_type in ["inlet", "inlet~"]: self.__inlet_objects.append(obj) # set correct let index by sorting on x position self.__inlet_objects.sort(key=lambda o: o.pos_x) for i, o in enumerate(self.__inlet_objects): o.let_index = i elif obj.obj_type in ["outlet", "outlet~"]: self.__outlet_objects.append(obj) self.__outlet_objects.sort(key=lambda o: o.pos_x) for i, o in enumerate(self.__outlet_objects): o.let_index = i return (len(self.__objs) - 1) def add_parsed_connection(self, from_index: int, from_outlet: int, to_index: int, to_inlet: int) -> None: """ Add a connection to the graph which has been parsed externally. """ try: # when connecting a Heavy object that allows mixed connection types, # try to immediately resolve to a non-mixed type based on the # object that it is connected to. connection_type = self.__objs[from_index].get_outlet_connection_type(from_outlet) if connection_type == "-~>": connection_type = self.__objs[to_index].get_inlet_connection_type(to_inlet) # make the connection c = Connection( self.__objs[from_index], from_outlet, self.__objs[to_index], to_inlet, connection_type) self.__connections.append(c) # update the local connections list # allow the connected objects to keep track of their own connections # (generally used for reporting and validation purposes) self.__objs[from_index].add_connection(c) self.__objs[to_index].add_connection(c) except Exception: self.add_error("There was an error while connecting two objects. " "Have all objects been correctly instantiated? " "Have all inlets and outlets been declared?", NotificationEnum.ERROR_UNABLE_TO_CONNECT_OBJECTS) def add_hv_arg( self, arg_index: int, name: str, value_type: str, default_value: Optional[Any], required: bool ) -> None: """ Add a Heavy argument to the graph. Indicies are from zero (not one, like Pd). """ # ensure that self.hv_args is big enough, as heavy arguments are not # necessarily added in the natural order while arg_index >= len(self.hv_args): self.hv_args.append(None) self.hv_args[arg_index] = { "name": name, "description": "", "value_type": value_type, "default": default_value, "required": required } def get_object(self, obj_index: int) -> PdObject: return self.__objs[obj_index] def get_objects(self) -> List[PdObject]: return self.__objs def get_inlet_connection_type(self, inlet_index: int) -> str: return self.__inlet_objects[inlet_index].get_inlet_connection_type(inlet_index) def get_outlet_connection_type(self, outlet_index: int) -> str: return self.__outlet_objects[outlet_index].get_outlet_connection_type(outlet_index) def validate_configuration(self) -> None: if self.is_root: if any((o.obj_type in {"inlet~", "outlet~"}) for o in self.__objs): self.add_error( "Top-level graphs may not contain inlet~ or outlet~ objects. " "Use adc~ and dac~.", NotificationEnum.ERROR_NO_TOPLEVEL_SIGNAL_LETS) if any((o.obj_type in {"inlet", "outlet"}) for o in self.__objs): self.add_warning( "Control inlets and outlets in top-level graphs don't do " "anything. Use receive and send objects.") # validate all object recursively for o in self.__objs: o.validate_configuration() def is_abstraction_on_call_stack(self, abs_path: str) -> bool: """ Returns True if the given abstraction name is already on the call stack (i.e. it is currently being parsed). This function is used to detect recursion within abstractions. """ if self.__pd_path == abs_path: return True elif not self.is_root and self.parent_graph: return self.parent_graph.is_abstraction_on_call_stack(abs_path) else: return False def get_notices(self) -> CompilerNotif: notices = PdObject.get_notices(self) for o in self.__objs: n = o.get_notices() notices.warnings.extend(n.warnings) notices.errors.extend(n.errors) # remove ERROR_EXCEPTION if there are already other errors. # The exception is always a result of some other error if any((n.enum != NotificationEnum.ERROR_EXCEPTION) for n in notices.errors): notices.errors = [n for n in notices.errors if n.enum != NotificationEnum.ERROR_EXCEPTION] return notices def get_graph_heirarchy(self) -> List: """ Returns the "path" of this graph, indicating where it is in the graph heirarchy (i.e. with file names, etc.) """ if self.is_root: return [str(self)] elif self.parent_graph is not None: return self.parent_graph.get_graph_heirarchy() + [str(self)] else: # NOTE(dromer): we should never get here raise Exception("parent_graph argument is None") def get_depth(self) -> int: """ Returns the depth of this graph, with the root being at 1. """ if self.is_root: return 1 elif self.parent_graph is not None: return 1 + self.parent_graph.get_depth() else: # NOTE(dromer): we should never get here raise Exception("parent_graph argument is None") def to_hv(self, export_args: bool = False) -> Dict: # NOTE(mhroth): hv_args are not returned. Because all arguments have # been resolved, no arguments are otherwise passed. hv2ir would break # on required arguments that are not passed to the graph assert all(a is not None for a in self.hv_args), "Graph is missing a @hv_arg." return { "type": "graph", "imports": [], "args": self.hv_args if export_args else [], "objects": {o.obj_id: o.to_hv() for o in self.__objs}, "connections": [c.to_hv() for c in self.__connections], "properties": { "x": self.pos_x, "y": self.pos_y } } def __repr__(self) -> str: return self.subpatch_name or os.path.basename(self.__pd_path) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2775517 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdLetObject.py0000644000000000000000000000345614677551203016676 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, List, Dict from .PdObject import PdObject class PdLetObject(PdObject): def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert obj_type in {"inlet", "inlet~", "outlet", "outlet~"} super().__init__(obj_type, obj_args, pos_x, pos_y) self.let_index = 0 def get_outlet_connection_type(self, outlet_index: int) -> Optional[str]: if len(self.obj_args) > 0 and self.obj_args[0] in {"-->", "~f>", "~i>", "-~>"}: return self.obj_args[0] else: return super().get_outlet_connection_type(outlet_index) def to_hv(self) -> Dict: return { "type": self.obj_type.strip("~"), "args": { "name": "", # Pd does not give an inlet name "index": self.let_index, "type": self.get_outlet_connection_type(self.let_index) }, "properties": { "x": self.pos_x, "y": self.pos_y } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2775517 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdLibSignalGraph.py0000644000000000000000000000660514677551203017650 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os from typing import List from .Connection import Connection from .HeavyObject import HeavyObject from .PdGraph import PdGraph class PdLibSignalGraph(PdGraph): def __init__( self, obj_args: List, pd_path: str, pos_x: int = 0, pos_y: int = 0 ) -> None: super().__init__(obj_args, pd_path, pos_x, pos_y) def validate_configuration(self) -> None: """ Auto-detect control only connections to expected signal inlets and insert a sig~ (var) object inbetween to ensure it doesn't break. """ # Note(joe): only checking first inlet, should we check all inlets by # default? i.e. samphold~ has a 2nd inlet that requires checking conns = self._inlet_connections.get("0", []) # only do this if no signal connections are present if (len([c for c in conns if c.conn_type == "~f>"]) == 0) and len(conns) > 0: # add sig~ object to parent graph if self.parent_graph is not None: sig_obj = HeavyObject( obj_type="var", obj_args=[0], pos_x=int(self.pos_x), pos_y=int(self.pos_y - 5)) # shift upwards a few points self.parent_graph.add_object(sig_obj) # add connection from sig~ to this abstraction c = Connection(sig_obj, 0, self, 0, "~f>") self.parent_graph._PdGraph__connections.append(c) # update the local connections list sig_obj.add_connection(c) self.add_connection(c) # retrieve all control connections control_conns = [c for c in conns if c.conn_type == "-->"] for old_conn in control_conns: # get from obj from_obj = old_conn.from_obj # add connection from fromobj to new sig new_conn = Connection(from_obj, old_conn.outlet_index, sig_obj, 0, "-->") self.parent_graph._PdGraph__connections.append(new_conn) sig_obj.add_connection(new_conn) from_obj.add_connection(new_conn) # remove connection from fromobj self.parent_graph._PdGraph__connections.remove(old_conn) from_obj.remove_connection(old_conn) self.remove_connection(old_conn) # make sure to call parent validate_configuration() super().validate_configuration() def __repr__(self) -> str: return "[{0} {1}]".format( os.path.splitext(os.path.basename(self._PdGraph__pd_path))[0], " ".join(self.obj_args[1:])) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5981824 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdMessageObject.py0000644000000000000000000000554114735300037017523 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import re from typing import Optional, List, Dict from .NotificationEnum import NotificationEnum from .PdObject import PdObject class PdMessageObject(PdObject): # only allow dollar argumnets if they are alone __RE_DOLLAR = re.compile(r"\$(\d+)") def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert obj_type == "msg" super().__init__("msg", obj_args, pos_x, pos_y) self.obj_dict: Dict = {} semi_split: List = [] # parse messages # remove prepended slash from $. Heavy does not use that. if obj_args is not None: semi_split = obj_args[0].replace(r"\$", "$").split(r"\;") semi_split = [x for x in semi_split if x] # remove empty strings # parse local messages # ensure that empty message are not passed on if len(semi_split) > 0: self.obj_dict["local"] = [li.strip().split() for li in semi_split[0].split(r"\,") if len(li.strip()) > 0] else: self.obj_dict["local"] = [] self.add_warning( "Message object is empty. Can it be removed?", NotificationEnum.WARNING_EMPTY_MESSAGE) # heavy does not support messages such as "$1-$2" for li in self.obj_dict["local"]: for m in li: x = self.__RE_DOLLAR.search(m) if x and len(x.group(0)) < len(m): self.add_error( "Heavy does not yet support message concatenation. " "Dollar arguments must be alone: " + m) # parse remote messages self.obj_dict["remote"] = [] for li in semi_split[1:]: l_split = li.strip().split() self.obj_dict["remote"].append({ "receiver": l_split[0], "message": l_split[1:] }) def to_hv(self) -> Dict: return { "type": "message", "args": self.obj_dict, "properties": { "x": self.pos_x, "y": self.pos_y } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2718232 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdObject.py0000644000000000000000000001570414735300474016225 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from collections import defaultdict import random import string from typing import Optional, List, Dict, TYPE_CHECKING from .Connection import Connection from .NotificationEnum import NotificationEnum from hvcc.types.compiler import CompilerMsg, CompilerNotif if TYPE_CHECKING: from .PdGraph import PdGraph class PdObject: __RANDOM = random.Random() __ID_CHARS = string.ascii_letters + string.digits def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: self.obj_type = obj_type # all arguments should be resolved when passed to a PdObject self.obj_args = obj_args or [] self.obj_id = "{0}_{1}".format( obj_type, "".join(self.__RANDOM.choice(self.__ID_CHARS) for _ in range(8))) self.pos_x = pos_x self.pos_y = pos_y # this is set when the object is added to a graph self.parent_graph: Optional['PdGraph'] = None self._inlet_connections: Dict = defaultdict(list) self._outlet_connections: Dict = defaultdict(list) self._warnings: List[CompilerMsg] = [] self._errors: List[CompilerMsg] = [] def add_warning(self, warning: str, enum: NotificationEnum = NotificationEnum.WARNING_GENERIC) -> None: """ Add a warning regarding this object. """ self._warnings.append(CompilerMsg(enum=enum, message=warning)) def add_error(self, error: str, enum: NotificationEnum = NotificationEnum.ERROR_GENERIC) -> None: """ Add an error regarding this object. """ self._errors.append(CompilerMsg(enum=enum, message=error)) def get_notices(self) -> CompilerNotif: """ Returns a dictionary of all warnings and errors at this object. """ # TODO(mhroth): we might want to consider moving to a more expressive format. # { # "objectType": "trigger", # "objectString": "t l l", # "graphs": ["_main", "hello"], # "rawText": "Heavy only supports arguments 'a', 'f', 's', and 'b'.", # "humanText": "[t l l] in "_main/osc~" @ (x:452, y:273): Heavy only supports # arguments 'a', 'f', 's', and 'b'.", # "position": { # "x": 452, # "y": 273 # } # } """ { "warnings": [{ "enum": 1000, "message": "this is a warning" }], "errors": [{ "enum": 2000, "message": "this is an error" }] } """ return CompilerNotif( has_error=len(self._errors) > 0, warnings=[ CompilerMsg(enum=n.enum, message="{0} in \"{1}\" @ (x:{2}, y:{3}): {4}".format( self, "/".join(self.get_graph_heirarchy()), self.pos_x, self.pos_y, n.message )) for n in self._warnings ], errors=[ CompilerMsg(enum=n.enum, message="{0} in \"{1}\" @ (x:{2}, y:{3}): {4}".format( self, "/".join(self.get_graph_heirarchy()), self.pos_x, self.pos_y, n.message )) for n in self._errors ] ) def get_inlet_connections(self) -> Dict: return self._inlet_connections def get_inlet_connection_type(self, inlet_index: int) -> Optional[str]: """ Returns the inlet connection type of this Pd object. For the sake of convenience, the connection type is reported in Heavy's format. """ return "~f>" if self.obj_type.endswith("~") else "-->" def get_outlet_connection_type(self, outlet_index: int) -> Optional[str]: """ Returns the outlet connection type of this Pd object. For the sake of convenience, the connection type is reported in Heavy's format. """ return "~f>" if self.obj_type.endswith("~") else "-->" def add_connection(self, c: Connection) -> None: """ Adds a connection, either inlet or outlet, to this object. """ if c.from_id == self.obj_id: self._outlet_connections[str(c.outlet_index)].append(c) elif c.to_id == self.obj_id: self._inlet_connections[str(c.inlet_index)].append(c) else: raise Exception("Adding a connection to the wrong object!") def remove_connection(self, c: Connection) -> None: """ Remove a connection to this object. """ if c.to_obj is self: self._inlet_connections[str(c.inlet_index)].remove(c) elif c.from_obj is self: self._outlet_connections[str(c.outlet_index)].remove(c) else: raise Exception(f"Connection {c} does not connect to this object {self}.") def get_graph_heirarchy(self) -> List: """ Returns an indication of the graph "path" of this object. It only includes unique graphs (not subpatches) E.g. _main/tabosc4~ The check for None is in case the object is somehow not yet attached. """ return self.parent_graph.get_graph_heirarchy() \ if self.parent_graph is not None else ["unattached"] def validate_configuration(self) -> None: """ Called when all graphs are finished parsing, from the root. Gives each object the chance to validate it's configuration, including connections. In general this function does nothing, though it may add warnings and errors. Note that object validation occurs when the entire patch is finished parsing and before it is returned to the user. The program may assume that all parameters and variables have been set. """ pass @classmethod def get_supported_objects(cls) -> set: """ Returns a list of Pd objects that this class can parse. """ raise NotImplementedError() def to_hv(self) -> Dict: """ Returns the HeavyLang JSON representation of this object. """ raise NotImplementedError() def __repr__(self) -> str: if len(self.obj_args) == 0: return f"[{self.obj_type}]" else: return f"[{self.obj_type} {' '.join([str(o) for o in self.obj_args])}]" ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2775517 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdPackObject.py0000644000000000000000000000355414677551203017027 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, List, Dict from .NotificationEnum import NotificationEnum from .PdObject import PdObject class PdPackObject(PdObject): def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert obj_type == "pack" super().__init__(obj_type, obj_args, pos_x, pos_y) self.values = [] if len(self.obj_args) == 0: self.values = [0.0, 0.0] for x in self.obj_args: try: self.values.append(float(x)) except Exception: if x in {"f", "float"}: self.values.append(0.0) else: self.add_error( f"\"{x}\" argument to [pack] object not supported.", NotificationEnum.ERROR_PACK_FLOAT_ARGUMENTS) def to_hv(self) -> Dict: return { "type": "__pack", "args": { "values": self.values }, "properties": { "x": self.pos_x, "y": self.pos_y } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2718232 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdParser.py0000644000000000000000000007740714735300474016263 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import decimal import os import re from collections import Counter from collections import OrderedDict from pathlib import Path from typing import List, Dict, Optional, Type, Any, Generator from .HeavyObject import HeavyObject from .HeavyGraph import HeavyGraph # pre-converted Heavy graphs from .HvSwitchcase import HvSwitchcase # __switchcase from .PdAudioIoObject import PdAudioIoObject # adc~/dac~ from .PdBinopObject import PdBinopObject # binary arithmatic operators from .PdGraph import PdGraph # canvas from .PdLetObject import PdLetObject # inlet/inlet~/outlet/outlet~ from .PdMessageObject import PdMessageObject # msg from .PdPackObject import PdPackObject # pack from .PdReceiveObject import PdReceiveObject # r/r~/receive/receive~/catch~ from .PdRouteObject import PdRouteObject # route from .PdSelectObject import PdSelectObject # select/sel from .PdSendObject import PdSendObject # s/s~/send/send~/throw~ from .PdTriggerObject import PdTriggerObject # trigger/t from .PdTableObject import PdTableObject # table from .PdUnpackObject import PdUnpackObject # unpack from .PdLibSignalGraph import PdLibSignalGraph # pd/lib abstraction connection checks from .NotificationEnum import NotificationEnum class PdParser: # library search paths __LIB_DIR = os.path.join(os.path.dirname(__file__), "libs") __HVLIB_DIR = os.path.join(os.path.dirname(__file__), "libs", "heavy") __HVLIB_CONVERTED_DIR = os.path.join(os.path.dirname(__file__), "libs", "heavy_converted") __PDLIB_DIR = os.path.join(os.path.dirname(__file__), "libs", "pd") __ELSELIB_DIR = os.path.join(os.path.dirname(__file__), "libs", "else") __PDLIB_CONVERTED_DIR = os.path.join(os.path.dirname(__file__), "libs", "pd_converted") # detect a dollar argument in a string __RE_DOLLAR = re.compile(r"\$(\d+)") # detect width parameter e.g. "#X obj 172 79 t b b, f 22;" __RE_WIDTH = re.compile(r", f \d+$") def __init__(self) -> None: # the current global value of $0 # Note(joe): set a high starting value to avoid potential user naming conflicts self.__DOLLAR_ZERO = 1000 # a counter of all Pd objects in the graph self.obj_counter: Counter = Counter() # search paths at this graph level self.__search_paths: List = [] @classmethod def get_supported_objects(cls) -> List: """ Returns a set of all pd objects names supported by the parser. """ pd_objects = [os.path.splitext(f)[0] for f in os.listdir(cls.__PDLIB_DIR) if f.endswith(".pd")] pd_objects += [f"else/{os.path.splitext(f)[0]}" for f in os.listdir(cls.__ELSELIB_DIR) if f.endswith(".pd")] pd_objects.extend(cls.__PD_CLASSES.keys()) return pd_objects @classmethod def __get_hv_args(cls, pd_path: str) -> OrderedDict: """ Pre-parse the file for Heavy arguments, such that they are available as soon as a graph is created. """ num_canvas = -1 hv_arg_dict = OrderedDict() hv_arg_list: Optional[List] = None with open(pd_path, "r") as f: for li in f: if li.startswith("#N canvas"): hv_arg_list = [] hv_arg_dict[li.rstrip(";\r\n")] = hv_arg_list num_canvas += 1 elif "@hv_arg" in li and hv_arg_list is not None: hv_arg_list.append(li.rstrip(";\r\n")) elif li.startswith("#X restore"): num_canvas -= 1 hv_arg_list = list(hv_arg_dict.values())[num_canvas] return hv_arg_dict @classmethod def __get_pd_line(cls, pd_path: str) -> Generator: concat = "" # concatination state with open(pd_path, "r") as f: for li in f: # concatenate split lines in the Pd file here li = li.rstrip("\r\n") # account for windows CRLF if li.endswith(";") and not li.endswith(r"\;"): out = li[:-1] # remove single ";" if len(concat) > 0: out = f'{concat} {out}' concat = "" # reset concatenation state yield out else: concat = (f'{concat} {li}') if len(concat) > 0 else f'{li}' def add_absolute_search_directory(self, search_dir: str) -> bool: if os.path.isdir(search_dir): self.__search_paths.append(search_dir) return True else: return False def add_relative_search_directory(self, search_dir: str) -> bool: search_dir = os.path.abspath(os.path.join( self.__search_paths[0], search_dir)) return self.add_absolute_search_directory(search_dir) def find_abstraction_path(self, local_dir: str, abs_name: str) -> Optional[str]: """ Finds the full path for an abstraction. Checks the local directory first, then all declared paths. """ abs_filename = f'{abs_name}.pd' # check local directory first abs_path = os.path.join(os.path.abspath(local_dir), abs_filename) if os.path.isfile(abs_path): return abs_path # check search paths in reverse order (last added search path first) for d in reversed(self.__search_paths): abs_path = os.path.join(d, abs_filename) if os.path.isfile(abs_path): return abs_path return None def graph_from_file( self, file_path: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0, is_root: bool = True, pd_graph_class: Type[PdGraph] = PdGraph ) -> Any: """ Instantiate a PdGraph from a file. Note that obj_args does not include $0. @param pd_graph_class The python class to handle specific graph types """ # add main patch directory. The first entry of self.__search_paths is # assumed to be the root path of the whole system if is_root: self.__search_paths.append(os.path.dirname(file_path)) file_hv_arg_dict = self.__get_hv_args(file_path) file_iterator = self.__get_pd_line(file_path) canvas_line = file_iterator.__next__() self.__DOLLAR_ZERO += 1 # increment $0 graph_args = [self.__DOLLAR_ZERO] + (obj_args or []) if not canvas_line.startswith("#N canvas"): g = pd_graph_class(graph_args, file_path, pos_x, pos_y) g.add_error(f"Pd files must begin with \"#N canvas\": {canvas_line}") return g g = self.graph_from_canvas( file_iterator, file_hv_arg_dict, canvas_line, graph_args, file_path, pos_x, pos_y, is_root, pd_graph_class) if is_root: if g.get_notices().has_error: # return the graph early here as there are already errors and it is # clearly invalid, avoids triggering unrelated errors in validation return g g.validate_configuration() return g def graph_from_canvas( self, file_iterator: Generator, file_hv_arg_dict: Dict, canvas_line: str, graph_args: List, pd_path: str, pos_x: int = 0, pos_y: int = 0, is_root: bool = False, pd_graph_class: Type[PdGraph] = PdGraph ) -> Any: """ Instantiate a PdGraph from an existing canvas. Note that graph_args includes $0. @param file_hv_arg_dict A dictionary containing all Heavy argument lines for each "#N canvas" in this file. @param canvas_line The "#N canvas" which initiates this canvas. @param pd_graph_class The python class to handle specific graph types """ obj_array: Optional[HeavyObject] = None # an #A (table) object which is currently being parsed g = pd_graph_class(graph_args, pd_path, pos_x, pos_y) remotes: Dict = {} # parse and add all Heavy arguments to the graph for li in file_hv_arg_dict[canvas_line]: line = li.split() assert line[4] == "@hv_arg" is_required = (line[9] == "true") default_value = HeavyObject.force_arg_type(line[8], line[7]) if not is_required else None g.add_hv_arg( arg_index=int(line[5][2:]) - 1, # strip off the leading "\$" and make index zero-based name=line[6], value_type=line[7], default_value=default_value, required=is_required) try: # this try will capture any critical errors for li in file_iterator: # remove width parameter line = self.__RE_WIDTH.sub("", li).split() if line[0] == "#N": if line[1] == "canvas": x = self.graph_from_canvas( file_iterator, file_hv_arg_dict, canvas_line=li, graph_args=graph_args, # subpatch inherits parent graph arguments, including $0 pd_path=pd_path, pos_x=int(line[2]), pos_y=int(line[3])) g.add_object(x) elif line[0] == "#X": if line[1] == "restore": if len(line) > 5 and line[5] == "@hv_obj": obj_args = self.__resolve_object_args( obj_type=line[6], obj_args=line[7:], graph=g, raise_on_failure=False, is_root=is_root) if line[6] == "__switchcase": x = HvSwitchcase( obj_type=line[6], obj_args=obj_args, pos_x=int(line[2]), pos_y=int(line[3])) else: x = HeavyObject( obj_type=line[6], obj_args=obj_args, pos_x=int(line[2]), pos_y=int(line[3])) return x # return a Heavy object instead of a graph else: # are we restoring an array object? # do some final sanity checks if obj_array is not None: declared_size = obj_array.obj_dict["size"] values_size = len(obj_array.obj_dict["values"]) if declared_size != values_size: new_size = max(declared_size, values_size) obj_array.add_warning( "Table \"{0}\" was declared as having {1} values, " "but {2} were supplied. It will be resized to {3} " "values (any unsupplied values will be zeroed).".format( obj_array.obj_dict["name"], declared_size, values_size, new_size)) obj_array.obj_dict["size"] = new_size if new_size < declared_size: obj_array.obj_dict["values"] = obj_args["values"][:new_size] else: obj_array.obj_dict["values"].extend([0.0 for _ in range(new_size - declared_size)]) obj_array = None # done parsing the array # set the subpatch name g.subpatch_name = " ".join(line[5:]) if len(line) > 5 else "subpatch" return g # pop the graph elif line[1] == "text": # @hv_arg arguments are pre-parsed # TODO(mhroth): is it necessary to split the entire line at once? # always add the comment to the graph, regardless self.obj_counter["text"] += 1 g.add_object(HeavyObject( obj_type="comment", obj_args=[" ".join(line[4:])], pos_x=int(line[2]), pos_y=int(line[3]))) elif line[1] == "obj": x = None # a PdObject if len(line) > 4: obj_type = line[4] # sometimes objects have $ arguments in them as well obj_type = self.__resolve_object_args( obj_type=obj_type, obj_args=[obj_type], graph=g, is_root=is_root)[0] obj_args = self.__resolve_object_args( obj_type=obj_type, obj_args=line[5:], graph=g, is_root=is_root) else: g.add_warning( "This graph contains an empty object. " "It should be removed or defined.", NotificationEnum.WARNING_EMPTY_OBJECT) g.add_object(HeavyObject( obj_type="comment", obj_args=["null object placeholder"], pos_x=int(line[2]), pos_y=int(line[3]))) continue # do we have an abstraction for this object? abs_path = self.find_abstraction_path(os.path.dirname(pd_path), obj_type) if abs_path is not None and not g.is_abstraction_on_call_stack(abs_path): # ensure that infinite recursion into abstractions is not possible x = self.graph_from_file( file_path=abs_path, obj_args=obj_args, pos_x=int(line[2]), pos_y=int(line[3]), is_root=False) # is this object in lib/pd_converted? elif os.path.isfile(os.path.join(self.__PDLIB_CONVERTED_DIR, f"{obj_type}.hv.json")): self.obj_counter[obj_type] += 1 hv_path = os.path.join(self.__PDLIB_CONVERTED_DIR, f"{obj_type}.hv.json") x = HeavyGraph( hv_path=hv_path, obj_args=obj_args, pos_x=int(line[2]), pos_y=int(line[3])) # is this object in lib/heavy_converted? elif os.path.isfile(os.path.join(self.__HVLIB_CONVERTED_DIR, f"{obj_type}.hv.json")): self.obj_counter[obj_type] += 1 hv_path = os.path.join(self.__HVLIB_CONVERTED_DIR, f"{obj_type}.hv.json") x = HeavyGraph( hv_path=hv_path, obj_args=obj_args, pos_x=int(line[2]), pos_y=int(line[3])) # is this object in lib/pd? elif os.path.isfile(os.path.join(self.__PDLIB_DIR, f"{obj_type}.pd")): self.obj_counter[obj_type] += 1 pdlib_path = os.path.join(self.__PDLIB_DIR, f"{obj_type}.pd") # mapping of pd/lib abstraction objects to classes # for checking connection validity pd_class = { "abs~": PdLibSignalGraph, "clip~": PdLibSignalGraph, "cos~": PdLibSignalGraph, "dbtopow~": PdLibSignalGraph, "dbtorms~": PdLibSignalGraph, "exp~": PdLibSignalGraph, "ftom~": PdLibSignalGraph, "hip~": PdLibSignalGraph, "lop~": PdLibSignalGraph, "mtof~": PdLibSignalGraph, "powtodb~": PdLibSignalGraph, "q8_rsqrt~": PdLibSignalGraph, "q8_sqrt~": PdLibSignalGraph, "rmstodb~": PdLibSignalGraph, "rsqrt~": PdLibSignalGraph, "sqrt~": PdLibSignalGraph, "wrap~": PdLibSignalGraph }.get(obj_type, PdGraph) x = self.graph_from_file( file_path=pdlib_path, obj_args=obj_args, pos_x=int(line[2]), pos_y=int(line[3]), is_root=False, pd_graph_class=pd_class) # register any object-specific warnings or errors if obj_type in {"rzero~", "rzero_rev~", "czero~", "czero_rev~"}: g.add_warning( f"[{obj_type}] accepts only signal input. " "Arguments and control connections are ignored.") # is this object in lib/heavy? elif os.path.isfile(os.path.join(self.__HVLIB_DIR, f"{obj_type}.pd")): self.obj_counter[obj_type] += 1 hvlib_path = os.path.join(self.__HVLIB_DIR, f"{obj_type}.pd") x = self.graph_from_file( file_path=hvlib_path, obj_args=obj_args, pos_x=int(line[2]), pos_y=int(line[3]), is_root=False) # is this object in lib/else? elif os.path.isfile(os.path.join(self.__ELSELIB_DIR, f"{obj_type}.pd")): self.obj_counter[obj_type] += 1 hvlib_path = os.path.join(self.__ELSELIB_DIR, f"{obj_type}.pd") x = self.graph_from_file( file_path=hvlib_path, obj_args=obj_args, pos_x=int(line[2]), pos_y=int(line[3]), is_root=False) # is this object in lib? (sub-directory) elif os.path.isfile(os.path.join(self.__LIB_DIR, f"{obj_type}.pd")): self.obj_counter[obj_type] += 1 hvlib_path = os.path.join(self.__LIB_DIR, f"{obj_type}.pd") x = self.graph_from_file( file_path=hvlib_path, obj_args=obj_args, pos_x=int(line[2]), pos_y=int(line[3]), is_root=False) # is this an object that must be programatically parsed? elif obj_type in self.__PD_CLASSES: self.obj_counter[obj_type] += 1 obj_class = self.__PD_CLASSES[obj_type] x = obj_class( obj_type, obj_args, pos_x=int(line[2]), pos_y=int(line[3])) elif self.__is_float(obj_type): # parse float literals self.obj_counter["float"] += 1 x = HeavyObject( obj_type="__var", obj_args=[float(obj_type)], pos_x=int(line[2]), pos_y=int(line[3])) else: g.add_error( f"Don't know how to parse object \"{obj_type}\". Is it an " "object supported by Heavy? Is it an abstraction? " "Have the search paths been correctly configured?", NotificationEnum.ERROR_UNKNOWN_OBJECT) x = HeavyObject( obj_type="comment", obj_args=[f"null object placeholder ({obj_type})"]) g.add_object(x) elif line[1] in {"floatatom", "symbolatom"}: self.obj_counter[line[1]] += 1 x = self.graph_from_file( file_path=os.path.join(self.__PDLIB_DIR, f"{line[1]}.pd"), obj_args=[], pos_x=int(line[2]), pos_y=int(line[3]), is_root=False) g.add_object(x) elif line[1] == "array": assert obj_array is None, "#X array object is already being parsed." # array names can have dollar arguments in them. # ensure that they are resolved table_name = self.__resolve_object_args( obj_type="array", obj_args=[line[2]], graph=g)[0] # Pd encodes arrays with length greater than 999,999 with # scientific notatation (e.g. 1e6) which Python's int() can't parse table_size = int(decimal.Decimal(line[3])) obj_array = HeavyObject( obj_type="table", # ensure that obj_array has its own values instance obj_args=[table_name, table_size, []]) # TODO(mhroth): position information g.add_object(obj_array) elif line[1] == "msg": self.obj_counter["msg"] += 1 msg = PdMessageObject( obj_type="msg", obj_args=[" ".join(line[4:])], pos_x=int(line[2]), pos_y=int(line[3])) index = g.add_object(msg) if len(msg.obj_dict) > 0: remotes[index] = [] for remote in msg.obj_dict['remote']: remotes[index].append(remote) elif line[1] == "connect": g.add_parsed_connection( from_index=int(line[2]), from_outlet=int(line[3]), to_index=int(line[4]), to_inlet=int(line[5])) elif line[1] == "declare": if not is_root: g.add_warning( "[declare] objects are not supported in abstractions. " "They can only be in the root canvas.") elif len(line) >= 4 and line[2] == "-path": pd_parent = Path(pd_path).parent pd_search = os.path.join(pd_parent, line[3]) did_add = self.add_relative_search_directory(pd_search) if not did_add: g.add_warning( f"\"{line[3]}\" is not a valid relative abstraction " "search path. It will be ignored.") else: g.add_warning( "Heavy only supports the -path flag for the " "declare object.", NotificationEnum.WARNING_DECLARE_PATH) elif line[1] == "coords": pass # don't do anything with this command elif line[1] == "f": # A line such as "#X f 123" # is found after a "#X restore" when the [pd afasdfasd] # object's box has been resized pass # don't do anything with this command else: g.add_error(f"Don't know how to parse line: {' '.join(line)}") elif line[0] == "#A" and obj_array is not None: obj_array.obj_dict["values"].extend([float(f) for f in line[2:]]) else: g.add_error(f"Don't know how to parse line: {' '.join(line)}") except Exception as e: # bubble the Exception back to the root graph where the graph # will be returned if not g.is_root: raise e else: # NOTE(mhroth): should the exception be added as an error? # Sometimes it's all that we have, so perhaps it's a good idea. g.add_error(str(e), NotificationEnum.ERROR_EXCEPTION) # parse remote messages for index in remotes.keys(): first_msg = g.get_object(index) conns = first_msg.get_inlet_connections() for remote in remotes[index]: self.obj_counter["msg"] += 1 msg = PdMessageObject('msg', [' '.join(msg for msg in remote['message'])]) msg_index = g.add_object(msg) self.obj_counter["send"] += 1 send = PdSendObject('send', [remote['receiver']]) send_index = g.add_object(send) # connect new message to upstream objects of first message for conn in conns['0']: up_obj = conn.from_obj up_index = g.get_objects().index(up_obj) g.add_parsed_connection(up_index, 0, msg_index, 0) g.add_parsed_connection(msg_index, 0, send_index, 0) return g @classmethod def __resolve_object_args( cls, obj_type: str, obj_args: List, graph: PdGraph, raise_on_failure: bool = True, is_root: bool = False ) -> Any: """ Resolve object arguments against the given graph arguments. By default this function raises an Exception if it cannot resolve an argument. This behaviour may be disabled, in which case the unresolved argument is replaced with None (which is an otherwise invalid value). A value of None typically indicates to a HeavyObject that the default value may be used. """ # TODO(mhroth): can this be done more elegantly? resolved_obj_args = list(obj_args) # make a copy of the original obj_args for i, a in enumerate(obj_args): for m in set(cls.__RE_DOLLAR.findall(a)): x = int(m) # the dollar index (i.e. $x) if len(graph.obj_args) > x: a = a.replace(fr"\${m}", str(graph.obj_args[x])) # check if hv_args can be used to supply a default value elif len(graph.hv_args) > (x - 1): # heavy args are zero-indexed if not graph.hv_args[x - 1]["required"]: a = a.replace(fr"\${m}", str(graph.hv_args[x - 1]["default"])) else: graph.add_error( f"There is a missing required argument named \"{graph.hv_args[x - 1]['name']}\".", NotificationEnum.ERROR_MISSING_REQUIRED_ARGUMENT) elif is_root: # NOTE(mhroth): this case is questionable, but since Pd # defaults to this behavior without warning, so will we. # graph.add_warning( # "${0} in \"{1}\" in the top-level graph is resolved to " # "\"0\". It is recommended that you remove $-arguments " # "from the top-level graph.".format(m, a)) a = a.replace(fr"\${m}", "0") else: if raise_on_failure: # NOTE(mhroth): this case is questionable, but since Pd # defaults to this behavior without warning, so will we. # graph.add_warning( # "Object [{0}] requires argument \"{1}\" but the parent " # "patch does not provide one ({2}). A default value of " # "\"0\" will be used.".format(obj_type, a, graph.obj_args)) a = a.replace(fr"\${m}", "0") else: a = None # indicate that this argument could not be resolved by replacing it with None resolved_obj_args[i] = a return resolved_obj_args # a mapping of Pd objects to the classes that will parse them __PD_CLASSES = { "adc~": PdAudioIoObject, "dac~": PdAudioIoObject, "inlet": PdLetObject, "inlet~": PdLetObject, "outlet": PdLetObject, "outlet~": PdLetObject, "pack": PdPackObject, "pd": PdGraph, "route": PdRouteObject, "sel": PdSelectObject, "select": PdSelectObject, "t": PdTriggerObject, "trigger": PdTriggerObject, "table": PdTableObject, "unpack": PdUnpackObject, "s": PdSendObject, "send": PdSendObject, "s~": PdSendObject, "send~": PdSendObject, "throw~": PdSendObject, "r": PdReceiveObject, "receive": PdReceiveObject, "r~": PdReceiveObject, "receive~": PdReceiveObject, "catch~": PdReceiveObject } # fill in as much of __PD_CLASSES programmatically as possible for o in PdBinopObject.get_supported_objects(): __PD_CLASSES[o] = PdBinopObject @classmethod def __is_float(cls, x: int) -> bool: """ Returns True if the input can be converted to a float. False otherwise. """ try: float(x) return True except Exception: return False ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2775517 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdRaw.py0000644000000000000000000000545014677551203015550 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import List, Dict class PdRawException(Exception): pass def replace_owl(args: List) -> List: new_args = [] for arg in args: new_arg = arg.replace('owl', 'raw') new_args.append(new_arg) return new_args def parse_pd_raw_args(args: List) -> Dict: """Parses a list of puredata send or receive objects looking for @raw and legacy @owl* annotations, parsing everything and throwing errors when syntax is not correct or values are of incorrect type""" attrdict = {} # define default values attrdict["min"] = 0.0 attrdict["max"] = 1.0 args = replace_owl(args) # TODO(dromer): deprecate @owl on next stable release for raw_param in {'@raw', '@raw_min', '@raw_max', '@raw_default', '@raw_param'}: if raw_param not in args: continue i = args.index(raw_param) if raw_param in {'@raw', '@raw_param'}: try: attrdict["raw"] = args[i + 1] except IndexError: raise PdRawException(f"{raw_param} annotation missing assigned parameter") if raw_param == '@raw': try: # expect the presence of up to 3 parameters which can be converted to float attrdict["min"] = float(args[i + 2]) attrdict["max"] = float(args[i + 3]) attrdict["default"] = float(args[i + 4]) except (IndexError, ValueError): # otherwise keep default pass elif raw_param in {'@raw_min', '@raw_max', '@raw_default'}: # make sure that it is a float value try: attrdict[raw_param.split('@raw_')[1]] = float(args[i + 1]) except ValueError: raise PdRawException(f"{raw_param} annotation value '{args[i + 1]}' is not numeric") except IndexError: raise PdRawException(f"{raw_param} annotation is missing its value") if attrdict.get("default") is None: attrdict["default"] = (attrdict["max"] - attrdict["min"]) / 2.0 return attrdict ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2775517 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdReceiveObject.py0000644000000000000000000001306614677551203017532 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, List, Dict from .PdObject import PdObject from .PdRaw import parse_pd_raw_args, PdRawException class PdReceiveObject(PdObject): __INSTANCE_COUNTER = 0 def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert obj_type in {"r", "r~", "receive", "receive~", "catch~"} super().__init__(obj_type, obj_args, pos_x, pos_y) self.__receiver_name = "" self.__extern_type = None self.__attributes: Dict = {} self.__priority = None # priority is not set PdReceiveObject.__INSTANCE_COUNTER += 1 self.__instance = PdReceiveObject.__INSTANCE_COUNTER try: # receive objects don't necessarily need to have a name self.__receiver_name = self.obj_args[0] # only extern control rate receivers if obj_type in {"r", "receive"}: # NOTE(mhroth): the second argument is _either_ externing the receiver or setting the priority # This means that right now priority cannot be set on externed receivers if self.obj_args[1] == "@hv_param": self.__extern_type = "param" elif self.obj_args[1] == "@hv_event": self.__extern_type = "event" elif int(self.obj_args[1]): self.__priority = int(self.obj_args[1]) except Exception: pass if self.__extern_type == "param": try: self.__attributes = { "min": 0.0, "max": 1.0, "default": 0.5, "type": "float" } self.__attributes["min"] = float(self.obj_args[2]) self.__attributes["max"] = float(self.obj_args[3]) self.__attributes["default"] = float(self.obj_args[4]) self.__attributes["type"] = str(self.obj_args[5]) except ValueError: self.add_warning( f"Minimum, maximum, and default values for Parameter {self.__receiver_name} must be numbers.") except Exception: pass if not (self.__attributes["min"] <= self.__attributes["default"]): self.add_error("Default parameter value is less than the minimum. " "Receiver will not be exported: {0:g} < {1:g}".format( self.__attributes["default"], self.__attributes["min"])) self.__extern_type = None if not (self.__attributes["default"] <= self.__attributes["max"]): self.add_error("Default parameter value is greater than the maximum. " "Receiver will not be exported: {0:g} > {1:g}".format( self.__attributes["default"], self.__attributes["max"])) self.__extern_type = None if '@raw' in self.obj_args or '@owl' in self.obj_args: # TODO(dromer): deprecate @owl on next stable release try: pd_raw_args = parse_pd_raw_args(self.obj_args) self.__attributes.update(pd_raw_args) self.__extern_type = "param" # make sure output code is generated except PdRawException as e: self.add_error(str(e)) def validate_configuration(self) -> None: if self.obj_type in {"r~", "receive~"}: if len(self._inlet_connections.get("0", [])) > 0: self.add_error("[receive~] inlet connections are not supported.") def to_hv(self) -> Dict: # note: control rate send objects should not modify their name argument names = { "r": "", "receive": "", "r~": "sndrcv_sig_", "receive~": "sndrcv_sig_", "catch~": "thrwctch_sig_" } # NOTE(mhroth): we follow Pd's execution rule: deeper receivers fire first. # Receivers on the same level fire in the order of instantiation. if self.parent_graph is not None and \ ((self.__priority is None) or (self.__receiver_name == "__hv_init" and self.__priority == 0)): self.__priority = (self.parent_graph.get_depth() * 1000) - self.__instance return { "type": "receive", "args": { "name": f"{names[self.obj_type]}{self.__receiver_name}", "extern": self.__extern_type, "attributes": self.__attributes, "priority": self.__priority }, "properties": { "x": self.pos_x, "y": self.pos_y }, "annotations": { "scope": "public" } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2775517 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdRouteObject.py0000644000000000000000000001423614677551203017246 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from collections import Counter from typing import Optional, List, Dict from .NotificationEnum import NotificationEnum from .PdObject import PdObject class PdRouteObject(PdObject): def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert obj_type == "route" super().__init__(obj_type, obj_args, pos_x, pos_y) if obj_args is not None: if len(obj_args) == 0: self.add_error("At least one argument is required.") # NOTE(joe): disabling this warning as it can be quite annoying. # if len(set(obj_args) & set(["bang", "list", "float", "symbol"])) > 0: # self.add_warning( # "Heavy interprets route arguments such as \"bang\", \"list\", \"float\", " # "and \"symbol\" literally. They cannot be used to filter generic " # "messages as in Pd.") if len(set(obj_args)) != len(obj_args): c = Counter(obj_args).most_common(1) self.add_error( f"All arguments to [route] must be unique. Argument \"{c[0][0]}\" is repeated {c[0][1]} times.", NotificationEnum.ERROR_UNIQUE_ARGUMENTS_REQUIRED) # convert to obj_args to mixedarray, such that correct switchcase hash # is generated for i, a in enumerate(self.obj_args): try: self.obj_args[i] = float(a) except Exception: pass def validate_configuration(self) -> None: if len(self._inlet_connections.get("1", [])) > 0: self.add_warning("The right inlet of route is not supported. It will not do anything.") def to_hv(self) -> Dict: """Creates a graph dynamically based on the number of arguments. An unconnected right inlet is added. [inlet] [inlet] | [@hv_obj switchcase [arg list (N elements)] ] | | | [@hv_obj __slice 1 -1] [@hv_obj __slice 1 -1] | | | | | | [outlet_0] [outlet_N-1] [outlet_right] """ route_graph: Dict = { "type": "graph", "imports": [], "args": [], "objects": { "inlet": { "type": "inlet", "args": { "type": "-->", "index": 0 }, "properties": {"x": 0, "y": 0} }, "inlet_right": { "type": "inlet", "args": { "type": "-->", "index": 1 }, "properties": {"x": 0, "y": 0} }, "switchcase": { "type": "__switchcase", "args": { "cases": self.obj_args }, "properties": {"x": 0, "y": 0} }, "outlet_right": { "type": "outlet", "args": { "type": "-->", "index": len(self.obj_args) }, "properties": {"x": 0, "y": 0} }, }, "connections": [ { "from": {"id": "inlet", "outlet": 0}, "to": {"id": "switchcase", "inlet": 0}, "type": "-->" }, { "from": {"id": "switchcase", "outlet": len(self.obj_args)}, "to": {"id": "outlet_right", "inlet": 0}, "type": "-->" } ], "properties": {"x": self.pos_x, "y": self.pos_y} } # add slices to graph for i, a in enumerate(self.obj_args): # add slices to graph route_graph["objects"][f"slice_{i}"] = { "type": "slice", "args": { "index": 1, "length": -1 }, "properties": {"x": 0, "y": 0} } # add outlets to graph route_graph["objects"][f"outlet_{i}"] = { "type": "outlet", "args": { "type": "-->", "index": i }, "properties": {"x": 0, "y": 0} } # add connection from switchcase to slice route_graph["connections"].append({ "from": {"id": "switchcase", "outlet": i}, "to": {"id": f"slice_{i}", "inlet": 0}, "type": "-->" }) # add connection from slice outlets 0 and 1 to outlet route_graph["connections"].append({ "from": {"id": f"slice_{i}", "outlet": 0}, "to": {"id": f"outlet_{i}", "inlet": 0}, "type": "-->" }) route_graph["connections"].append({ "from": {"id": f"slice_{i}", "outlet": 1}, "to": {"id": f"outlet_{i}", "inlet": 0}, "type": "-->" }) return route_graph ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2785518 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdSelectObject.py0000644000000000000000000001264114677551203017365 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from collections import Counter from typing import Optional, List, Dict from .NotificationEnum import NotificationEnum from .PdObject import PdObject class PdSelectObject(PdObject): def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert obj_type in {"select", "sel"} super().__init__(obj_type, obj_args, pos_x, pos_y) if not obj_args: obj_args = [] if len(self.obj_args) == 0: self.add_error("At least one argument is required.") if len(set(self.obj_args)) != len(obj_args): c = Counter(obj_args).most_common(1) self.add_error( f"All arguments to [select] must be unique. Argument \"{c[0][0]}\" is repeated {c[0][1]} times.", NotificationEnum.ERROR_UNIQUE_ARGUMENTS_REQUIRED) # convert to obj_args to mixedarray, such that correct switchcase hash # is generated for i, a in enumerate(self.obj_args): try: self.obj_args[i] = float(a) except Exception: pass def validate_configuration(self) -> None: if len(self._inlet_connections.get("1", [])) > 0: self.add_warning("The right inlet of select is not supported. It will not do anything.") def to_hv(self) -> Dict: """ Creates a graph dynamically based on the number of arguments. An unconnected right inlet is added. [inlet] [inlet] | [@hv_obj switchcase [arg list (N elements)] ] | | | [@hv_obj __cast_b] [@hv_obj __cast_b] | | | | [outlet_0] [outlet_N-1] [outlet_right] """ route_graph: Dict = { "type": "graph", "imports": [], "args": [], "objects": { "inlet": { "type": "inlet", "args": { "type": "-->", "index": 0 }, "properties": {"x": 0, "y": 0} }, "inlet_right": { "type": "inlet", "args": { "type": "-->", "index": 1 }, "properties": {"x": 0, "y": 0} }, "switchcase": { "type": "__switchcase", "args": { "cases": self.obj_args }, "properties": {"x": 0, "y": 0} }, "outlet_right": { "type": "outlet", "args": { "type": "-->", "index": len(self.obj_args) }, "properties": {"x": 0, "y": 0} }, }, "connections": [ { "from": {"id": "inlet", "outlet": 0}, "to": {"id": "switchcase", "inlet": 0}, "type": "-->" }, { "from": {"id": "switchcase", "outlet": len(self.obj_args)}, "to": {"id": "outlet_right", "inlet": 0}, "type": "-->" } ], "properties": {"x": self.pos_x, "y": self.pos_y} } for i in range(len(self.obj_args)): # add __cast_b to graph route_graph["objects"][f"__cast_b_{i}"] = { "type": "__cast_b", "args": {}, "properties": {"x": 0, "y": 0} } # add outlets to graph route_graph["objects"][f"outlet_{i}"] = { "type": "outlet", "args": { "type": "-->", "index": i }, "properties": {"x": 0, "y": 0} } # add connection from switchcase to slice route_graph["connections"].append({ "from": {"id": "switchcase", "outlet": i}, "to": {"id": f"__cast_b_{i}", "inlet": 0}, "type": "-->" }) # add connection from slice to outlet route_graph["connections"].append({ "from": {"id": f"__cast_b_{i}", "outlet": 0}, "to": {"id": f"outlet_{i}", "inlet": 0}, "type": "-->" }) return route_graph ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5981824 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdSendObject.py0000644000000000000000000001242214735300037017024 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, List, Dict from .NotificationEnum import NotificationEnum from .PdObject import PdObject from .PdRaw import parse_pd_raw_args, PdRawException class PdSendObject(PdObject): def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert obj_type in {"s", "send", "s~", "send~", "throw~"} PdObject.__init__(self, obj_type, obj_args, pos_x, pos_y) self.__send_name = "" self.__extern_type = None self.__attributes: Dict = {} try: # send objects don't necessarily need to have a name self.__send_name = self.obj_args[0] # only extern control rate sends if obj_type in {"s", "send"}: if self.obj_args[1] == "@hv_param": self.__extern_type = "param" elif self.obj_args[1] == "@hv_event": self.__extern_type = "event" except Exception: pass if self.__extern_type == "param": try: self.__attributes = { "min": 0.0, "max": 1.0, "default": 0.5, "type": "float" } self.__attributes["min"] = float(self.obj_args[2]) self.__attributes["max"] = float(self.obj_args[3]) self.__attributes["default"] = float(self.obj_args[4]) self.__attributes["type"] = str(self.obj_args[5]) except ValueError: self.add_warning( f"Minimum, maximum, and default values for Parameter {self.__send_name} must be numbers.") except Exception: pass if not (self.__attributes["min"] <= self.__attributes["default"]): self.add_error("Default parameter value is less than the minimum. " "Send will not be exported: {0:g} < {1:g}".format( self.__attributes["default"], self.__attributes["min"])) self.__extern_type = None if not (self.__attributes["default"] <= self.__attributes["max"]): self.add_error("Default parameter value is greater than the maximum. " "Send will not be exported: {0:g} > {1:g}".format( self.__attributes["default"], self.__attributes["max"])) self.__extern_type = None if '@raw' in self.obj_args or '@owl' in self.obj_args: # TODO(dromer): deprecate @owl on next stable release try: pd_raw_args = parse_pd_raw_args(self.obj_args) self.__attributes.update(pd_raw_args) self.__extern_type = "param" # make sure output code is generated except PdRawException as e: self.add_error(str(e)) def validate_configuration(self) -> None: if len(self.obj_args) == 0: self.add_warning( f"No name was given to this {self.obj_type} object. " "It should have a name to reduce the risk of errors.", NotificationEnum.WARNING_USELESS_OBJECT) if len(self._inlet_connections.get("0", [])) == 0: self.add_warning( "This object has no inlet connections. " "It does nothing and will be removed.", NotificationEnum.WARNING_USELESS_OBJECT) if self.obj_type in {"s", "send"} and len(self._inlet_connections.get("1", [])) > 0: self.add_error( "Connections to the right inlet of a send object " "are not supported. A name should be given.", NotificationEnum.ERROR_MISSING_REQUIRED_ARGUMENT) def to_hv(self) -> Dict: # note: control rate send/receive objects should not modify their name argument names = { "s": "", "send": "", "s~": "sndrcv_sig_", "send~": "sndrcv_sig_", "throw~": "thrwctch_sig_" } return { "type": "send", "args": { "name": names[self.obj_type] + self.__send_name, "extern": self.__extern_type, "attributes": self.__attributes, }, "properties": { "x": self.pos_x, "y": self.pos_y }, "annotations": { "scope": "public" } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2785518 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdTableObject.py0000644000000000000000000000420314677551203017170 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, List, Dict from .NotificationEnum import NotificationEnum from .PdObject import PdObject class PdTableObject(PdObject): def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert obj_type == "table" super().__init__(obj_type, obj_args, pos_x, pos_y) self.__table_name = "" self.__size = 0 self.__extern = False try: self.__table_name = self.obj_args[0] except Exception: self.add_error( "Missing \"name\" argument for table", NotificationEnum.ERROR_MISSING_REQUIRED_ARGUMENT) try: # optional arguments try: self.__size = int(self.obj_args[1]) self.__extern = (self.obj_args[2] == "@hv_table") except Exception: pass except Exception: pass def to_hv(self) -> Dict: return { "type": "table", "args": { "name": self.__table_name, "size": self.__size, "values": [], "extern": self.__extern }, "properties": { "x": self.pos_x, "y": self.pos_y }, "annotations": { "scope": "public" } } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2785518 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdTriggerObject.py0000644000000000000000000000426614677551203017555 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, List, Dict from .NotificationEnum import NotificationEnum from .PdObject import PdObject class PdTriggerObject(PdObject): def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert obj_type in {"trigger", "t"} super().__init__("trigger", obj_args, pos_x, pos_y) # convert all numeric casts to "f" for i, a in enumerate(self.obj_args): self.obj_args[i] = "f" if PdTriggerObject.__is_float(a) else a if len(self.obj_args) == 0: self.obj_args = ["b", "b"] self.add_warning("A trigger with no arguments defualts to [t b b].") if obj_args is not None and not (set(obj_args) <= set(["a", "f", "s", "b"])): self.add_error( "Heavy only supports arguments 'a', 'f', 's', and 'b'.", NotificationEnum.ERROR_TRIGGER_ABFS) def to_hv(self) -> Dict: return { "type": "sequence", "args": { "casts": self.obj_args }, "properties": { "x": self.pos_x, "y": self.pos_y } } @classmethod def __is_float(cls, x: int) -> bool: """ Returns True if the input can be converted to a float. False otherwise. """ try: float(x) return True except Exception: return False ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2785518 hvcc-0.13.3/hvcc/interpreters/pd2hv/PdUnpackObject.py0000644000000000000000000000666614677551203017401 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from typing import Optional, List, Dict from .PdObject import PdObject class PdUnpackObject(PdObject): def __init__( self, obj_type: str, obj_args: Optional[List] = None, pos_x: int = 0, pos_y: int = 0 ) -> None: assert obj_type == "unpack" super().__init__(obj_type, obj_args, pos_x, pos_y) if len(self.obj_args) == 0: self.add_error("Unpack requires at least one argument.") if not (set(self.obj_args) <= set(["f", "s"])): self.add_warning("Heavy only supports arguments 'f' and 's' to unpack.") def to_hv(self) -> Dict: """ Creates a graph dynamically based on the number of arguments. [inlet ] | | | [@hv_obj __slice 0 1] ... [@hv_obj __slice N-1 1] | | | [outlet_0] ... [outlet_N-1] """ hv_graph: Dict = { "type": "graph", "imports": [], "args": [], "objects": { "inlet": { "type": "inlet", "args": { "type": "-->", "index": 0 }, "properties": {"x": 0, "y": 0} } }, "connections": [], "properties": {"x": self.pos_x, "y": self.pos_y} } # NOTE(mhroth): reverse the iteration such that connections are # added in the correct order for i in reversed(range(len(self.obj_args))): # add slices to graph hv_graph["objects"][f"slice_{i}"] = { "type": "slice", "args": { "index": i, "length": 1 }, "properties": {"x": 0, "y": 0} } # add outlets to graph hv_graph["objects"][f"outlet_{i}"] = { "type": "outlet", "args": { "type": "-->", "index": i }, "properties": {"x": 0, "y": 0} } # add connection from inlet to slice hv_graph["connections"].append({ "from": {"id": "inlet", "outlet": 0}, "to": {"id": f"slice_{i}", "inlet": 0}, "type": "-->" }) # add connection from slice to outlet hv_graph["connections"].append({ "from": {"id": f"slice_{i}", "outlet": 0}, "to": {"id": f"outlet_{i}", "inlet": 0}, "type": "-->" }) return hv_graph ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/__init__.py0000644000000000000000000000000014435670357016260 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5981824 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/else/knob.pd0000644000000000000000000000020314735300037017277 0ustar00#N canvas 0 149 210 157 10; #X obj 24 35 inlet; #X obj 24 57 float 0; #X obj 24 79 outlet; #X connect 0 0 1 0; #X connect 1 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/heavy/conv~.pd0000644000000000000000000000143614435670357017722 0ustar00#N canvas 702 23 312 255 10; #N canvas 0 22 450 300 @hv_obj 0; #X obj 55 136 outlet~; #X obj 55 75 inlet~; #X obj 190 74 inlet; #X obj 139 74 inlet; #X restore 25 155 pd @hv_obj __conv~f \$1 \$2; #X text 24 232 @hv_arg \$2 size int 0 false; #X text 24 210 @hv_arg \$1 table string "" true; #X obj 25 15 inlet~; #X obj 172 65 loadbang; #X msg 172 110 table \$1 size; #N canvas 0 22 450 300 @hv_obj 0; #X obj 146 77 inlet; #X obj 147 120 outlet; #X restore 172 133 pd @hv_obj system; #X text 37 46 measured after initialisation; #X text 37 35 NOTE(mhroth): ensure that the table size is; #X obj 172 87 symbol \$1; #X obj 25 183 outlet~; #X obj 98 132 inlet; #X connect 0 0 10 0; #X connect 3 0 0 0; #X connect 4 0 9 0; #X connect 5 0 6 0; #X connect 6 0 0 2; #X connect 9 0 5 0; #X connect 11 0 0 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/heavy/lorenz~.pd0000644000000000000000000000137114435670357020264 0ustar00#N canvas 137 197 531 225 10; #N canvas 0 22 1061 416 @hv_obj 0; #X obj 200 60 inlet~; #X obj 140 50 inlet~; #X obj 338 65 inlet~; #X obj 278 55 inlet~; #X obj 288 147 outlet~; #X obj 146 146 outlet~; #X obj 210 147 outlet~; #X obj 415 71 inlet; #X restore 30 140 pd @hv_obj __lorenz~f; #X obj 30 29 inlet~; #X obj 60 50 inlet~; #X obj 91 70 inlet~; #X obj 122 90 inlet~; #X obj 30 170 outlet~ x; #X obj 91 170 outlet~ y; #X obj 153 170 outlet~ z; #X text 175 86 NOTE(joe): there is supposed to be a control; #X obj 153 117 route xyz; #X text 174 99 connection from the first [inlet~] to the [route]; #X connect 0 0 5 0; #X connect 0 1 6 0; #X connect 0 2 7 0; #X connect 1 0 0 0; #X connect 2 0 0 1; #X connect 3 0 0 2; #X connect 4 0 0 3; #X connect 9 0 0 4; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/heavy_converted/lorenz~.hv.json0000644000000000000000000001465114435670357023324 0ustar00{ "args": [], "connections": [ { "from": { "id": "__lorenz~f_7dUFW", "outlet": 0 }, "to": { "id": "outlet~_Lf24h", "inlet": 0 }, "type": "~f>" }, { "from": { "id": "__lorenz~f_7dUFW", "outlet": 1 }, "to": { "id": "outlet~_aCD1q", "inlet": 0 }, "type": "~f>" }, { "from": { "id": "__lorenz~f_7dUFW", "outlet": 2 }, "to": { "id": "outlet~_pOs6O", "inlet": 0 }, "type": "~f>" }, { "from": { "id": "inlet~_l0vgT", "outlet": 0 }, "to": { "id": "__lorenz~f_7dUFW", "inlet": 0 }, "type": "~f>" }, { "from": { "id": "inlet~_fGKSc", "outlet": 0 }, "to": { "id": "__lorenz~f_7dUFW", "inlet": 1 }, "type": "~f>" }, { "from": { "id": "inlet~_IdP6v", "outlet": 0 }, "to": { "id": "__lorenz~f_7dUFW", "inlet": 2 }, "type": "~f>" }, { "from": { "id": "inlet~_jm5dl", "outlet": 0 }, "to": { "id": "__lorenz~f_7dUFW", "inlet": 3 }, "type": "~f>" }, { "from": { "id": "inlet~_l0vgT", "outlet": 0 }, "to": { "id": "route_Ymaxs", "inlet": 0 }, "type": "-->" }, { "from": { "id": "route_Ymaxs", "outlet": 0 }, "to": { "id": "__lorenz~f_7dUFW", "inlet": 4 }, "type": "-->" } ], "imports": [], "objects": { "__lorenz~f_7dUFW": { "annotations": {}, "args": { "x": 0, "y": 0, "z": 0 }, "properties": { "x": 30, "y": 140 }, "type": "__lorenz~f" }, "comment_2QlQ0": { "annotations": {}, "args": { "mime": "text/plain", "text": "connection from the first [inlet~] to the [route]" }, "properties": { "x": "174", "y": "99" }, "type": "comment" }, "comment_JloHn": { "annotations": {}, "args": { "mime": "text/plain", "text": "NOTE(joe): there is supposed to be a control" }, "properties": { "x": "175", "y": "86" }, "type": "comment" }, "inlet~_IdP6v": { "annotations": {}, "args": { "index": 2, "name": "", "type": "~f>" }, "properties": { "x": 91, "y": 70 }, "type": "inlet" }, "inlet~_fGKSc": { "annotations": {}, "args": { "index": 1, "name": "", "type": "~f>" }, "properties": { "x": 60, "y": 50 }, "type": "inlet" }, "inlet~_jm5dl": { "annotations": {}, "args": { "index": 3, "name": "", "type": "~f>" }, "properties": { "x": 122, "y": 90 }, "type": "inlet" }, "inlet~_l0vgT": { "annotations": {}, "args": { "index": 0, "name": "", "type": "~f>" }, "properties": { "x": 30, "y": 29 }, "type": "inlet" }, "outlet~_Lf24h": { "annotations": {}, "args": { "index": 0, "name": "x", "type": "~f>" }, "properties": { "x": 30, "y": 170 }, "type": "outlet" }, "outlet~_aCD1q": { "annotations": {}, "args": { "index": 1, "name": "y", "type": "~f>" }, "properties": { "x": 91, "y": 170 }, "type": "outlet" }, "outlet~_pOs6O": { "annotations": {}, "args": { "index": 2, "name": "z", "type": "~f>" }, "properties": { "x": 153, "y": 170 }, "type": "outlet" }, "route_Ymaxs": { "args": {}, "connections": [ { "from": { "id": "inlet_ofY1a", "outlet": 0 }, "to": { "id": "__switchcase_PyIvC", "inlet": 0 }, "type": "-->" }, { "from": { "id": "__switchcase_PyIvC", "outlet": 0 }, "to": { "id": "__slice_1AcsG", "inlet": 0 }, "type": "-->" }, { "from": { "id": "__slice_1AcsG", "outlet": 0 }, "to": { "id": "outlet_EWlrg", "inlet": 0 }, "type": "-->" }, { "from": { "id": "__switchcase_PyIvC", "outlet": 1 }, "to": { "id": "outlet_zxBnk", "inlet": 0 }, "type": "-->" } ], "objects": { "__slice_1AcsG": { "annotations": {}, "args": { "index": 1, "length": -1 }, "properties": { "x": 10, "y": 50 }, "type": "__slice" }, "__switchcase_PyIvC": { "annotations": {}, "args": { "cases": [ "xyz" ] }, "properties": { "x": 10, "y": 50 }, "type": "__switchcase" }, "inlet_ofY1a": { "annotations": {}, "args": { "index": 0, "name": "", "type": "-->" }, "properties": { "x": 10, "y": 10 }, "type": "inlet" }, "outlet_EWlrg": { "annotations": {}, "args": { "index": 0, "name": "xyz", "type": "-->" }, "properties": { "x": 10, "y": 10 }, "type": "outlet" }, "outlet_zxBnk": { "annotations": {}, "args": { "index": 1, "name": "", "type": "-->" }, "properties": { "x": 10, "y": 10 }, "type": "outlet" } }, "type": "graph" } }, "properties": { "x": 0, "y": 0 }, "type": "graph" }././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/abs.pd0000644000000000000000000000033514435670357016610 0ustar00#N canvas 439 480 151 128 10; #X obj 13 20 inlet; #X obj 13 80 outlet; #N canvas 0 22 183 125 @hv_obj 0; #X obj 19 24 inlet; #X obj 19 66 outlet; #X restore 13 50 pd @hv_obj __abs; #X connect 0 0 2 0; #X connect 2 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/abs~.pd0000644000000000000000000000034314435670357017005 0ustar00#N canvas 439 480 165 137 10; #N canvas 0 22 183 125 @hv_obj 0; #X obj 19 24 inlet~; #X obj 19 66 outlet~; #X restore 13 50 pd @hv_obj __abs~f; #X obj 13 20 inlet~; #X obj 13 80 outlet~; #X connect 0 0 2 0; #X connect 1 0 0 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/atan.pd0000644000000000000000000000033614435670357016767 0ustar00#N canvas 439 480 151 128 10; #X obj 13 20 inlet; #X obj 13 80 outlet; #N canvas 0 22 183 125 @hv_obj 0; #X obj 19 24 inlet; #X obj 19 66 outlet; #X restore 13 50 pd @hv_obj __atan; #X connect 0 0 2 0; #X connect 2 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/atan2.pd0000644000000000000000000000043414435670357017050 0ustar00#N canvas 439 480 161 128 10; #X obj 13 19 inlet; #X obj 13 80 outlet; #N canvas 0 22 183 125 @hv_obj 0; #X obj 76 24 inlet; #X obj 19 66 outlet; #X obj 19 24 inlet; #X restore 13 50 pd @hv_obj __atan2; #X obj 118 18 inlet; #X connect 0 0 2 0; #X connect 2 0 1 0; #X connect 3 0 2 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/b.pd0000644000000000000000000000034514435670357016265 0ustar00#N canvas 638 45 161 94 10; #X obj 9 10 inlet -->; #N canvas 0 22 450 300 @hv_obj 0; #X obj 143 44 inlet; #X obj 146 94 outlet; #X restore 9 33 pd @hv_obj __cast_b; #X obj 9 57 outlet -->; #X connect 0 0 1 0; #X connect 1 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/bang.pd0000644000000000000000000000034514435670357016753 0ustar00#N canvas 638 45 161 94 10; #X obj 9 10 inlet -->; #N canvas 0 22 450 300 @hv_obj 0; #X obj 143 44 inlet; #X obj 146 94 outlet; #X restore 9 33 pd @hv_obj __cast_b; #X obj 9 57 outlet -->; #X connect 0 0 1 0; #X connect 1 0 2 0; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5981824 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/bang~.pd0000644000000000000000000000047614735300037017142 0ustar00#N canvas 320 37 549 254 12; #X obj 99 102 r __hv_bang~; #X obj 99 173 outlet; #X obj 99 71 inlet; #X text 151 69 inlet is inactive; #X text 255 111 because we only receive the first bang at the end of the first process() loop we first send a loadbang; #X obj 128 132 loadbang; #X connect 0 0 1 0; #X connect 5 0 1 0; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2785518 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/bendin.pd0000644000000000000000000000155014677551203017276 0ustar00#N canvas 114 229 459 438 10; #X obj 209 337 outlet; #X obj 152 76 unpack f f; #X obj 152 47 r __hv_bendin; #X obj 50 307 outlet; #X obj 83 104 loadbang; #X obj 83 174 == 0; #X obj 83 128 i \$1; #X obj 50 266 spigot; #X obj 209 101 + 1; #X obj 209 236 spigot; #X obj 215 175 ==; #X obj 152 237 spigot; #X obj 215 200 t f f; #X obj 209 313 max 1; #X text 226 78 bend value and channel/port; #X obj 83 197 t f f; #X obj 150 270 spigot; #X connect 1 0 11 0; #X connect 1 0 7 0; #X connect 1 1 8 0; #X connect 2 0 1 0; #X connect 4 0 6 0; #X connect 5 0 15 0; #X connect 6 0 5 0; #X connect 6 0 10 1; #X connect 7 0 3 0; #X connect 8 0 10 0; #X connect 8 0 16 0; #X connect 8 0 9 0; #X connect 9 0 13 0; #X connect 10 0 12 0; #X connect 11 0 3 0; #X connect 12 0 11 1; #X connect 12 1 9 1; #X connect 13 0 0 0; #X connect 15 0 7 1; #X connect 15 1 16 1; #X connect 16 0 13 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/bendout.pd0000644000000000000000000000063514435670357017506 0ustar00#N canvas 735 166 248 326 10; #X obj 46 232 pack f f; #X obj 91 104 inlet channel; #X obj 91 155 f \$1; #X obj 108 129 loadbang; #X obj 46 262 s __hv_bendout @hv_param; #X obj 46 40 inlet bend; #X obj 46 72 + 8192; #X obj 91 181 - 1; #X obj 91 204 max; #X connect 0 0 4 0; #X connect 1 0 2 0; #X connect 2 0 7 0; #X connect 3 0 2 0; #X connect 5 0 6 0; #X connect 6 0 0 0; #X connect 7 0 8 0; #X connect 8 0 0 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/biquad~.pd0000644000000000000000000000407314435670357017511 0ustar00#N canvas 846 105 451 381 10; #X obj 25 355 outlet~; #X obj 166 303 * -1; #X obj 202 303 * -1; #X text 95 15 NOTE(mhroth): there is supposed to be a control; #N canvas 0 22 450 300 @hv_obj 0; #X obj 78 79 inlet~; #X obj 86 146 outlet~; #X obj 184 76 inlet; #X obj 144 76 inlet; #X obj 302 76 inlet; #X obj 223 76 inlet; #X obj 263 76 inlet; #X restore 25 332 pd @hv_obj biquad \$3 \$4 \$5 0 0; #X text 262 62 @hv_arg \$3 x0 float 1 false; #X text 262 80 @hv_arg \$4 x1 float 0 false; #X text 262 100 @hv_arg \$5 x2 float 0 false; #X text 262 119 @hv_arg \$1 y0 float 0 false; #X text 262 139 @hv_arg \$2 y1 float 0 false; #N canvas 0 22 450 300 @hv_obj 0; #X obj 165 61 inlet; #X obj 169 116 outlet; #X restore 62 110 pd @hv_obj __slice 0 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 165 61 inlet; #X obj 169 116 outlet; #X restore 86 133 pd @hv_obj __slice 1 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 165 61 inlet; #X obj 169 116 outlet; #X restore 109 156 pd @hv_obj __slice 2 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 165 61 inlet; #X obj 169 116 outlet; #X restore 134 179 pd @hv_obj __slice 3 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 165 61 inlet; #X obj 169 116 outlet; #X restore 162 202 pd @hv_obj __slice 4 1; #X obj 166 226 loadbang; #X text 94 28 connection from the left inlet to the trigger; #N canvas 0 22 450 300 @hv_obj 0; #X obj 179 57 inlet; #X obj 169 117 outlet; #X restore 166 255 pd @hv_obj __var \$1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 179 57 inlet; #X obj 169 117 outlet; #X restore 202 276 pd @hv_obj __var \$2; #X obj 25 23 inlet~ -~>; #N canvas 0 22 162 66 to_control 0; #X obj 17 10 inlet; #X obj 17 32 outlet; #X connect 0 0 1 0; #X restore 62 67 pd to_control; #X connect 1 0 4 4; #X connect 2 0 4 5; #X connect 4 0 0 0; #X connect 10 0 1 0; #X connect 11 0 2 0; #X connect 12 0 4 1; #X connect 13 0 4 2; #X connect 14 0 4 3; #X connect 15 0 17 0; #X connect 15 0 18 0; #X connect 17 0 1 0; #X connect 18 0 2 0; #X connect 19 0 20 0; #X connect 19 0 4 0; #X connect 20 0 10 0; #X connect 20 0 11 0; #X connect 20 0 12 0; #X connect 20 0 13 0; #X connect 20 0 14 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/bng.pd0000644000000000000000000000034514435670357016612 0ustar00#N canvas 638 45 161 94 10; #X obj 9 10 inlet -->; #N canvas 0 22 450 300 @hv_obj 0; #X obj 143 44 inlet; #X obj 146 94 outlet; #X restore 9 33 pd @hv_obj __cast_b; #X obj 9 57 outlet -->; #X connect 0 0 1 0; #X connect 1 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/bp~.pd0000644000000000000000000000400414435670357016637 0ustar00#N canvas 742 22 339 614 10; #X obj 18 21 inlet~; #X obj 108 21 inlet fc; #X obj 18 538 outlet~; #X obj 108 179 /; #X obj 186 128 samplerate~; #X obj 167 77 loadbang; #X obj 108 123 f \$1; #N canvas 0 22 324 130 @hv_obj 0; #X obj 75 4 inlet; #X obj 229 4 inlet; #X obj 113 4 inlet; #X obj 152 4 inlet; #X obj 30 37 outlet~; #X obj 192 4 inlet; #X obj 30 4 inlet~, f 19; #X restore 18 513 pd @hv_obj biquad; #X obj 108 153 * 6.28319; #X text 13 584 @hv_arg \$2 q float 1 false; #X text 13 566 @hv_arg \$1 fc float 22050 false; #X obj 176 21 inlet q; #X obj 206 153 f \$2; #X obj 167 100 t a a a; #X obj 108 230 /; #X obj 147 310 * -1; #X obj 147 332 + 1; #X text 70 179 omega; #X text 46 233 oneminusr; #X text 133 332 r; #X obj 193 310 cos; #X obj 193 334 * 2; #X obj 147 378 *; #X text 108 378 coef1; #X obj 176 48 t b a, f 9; #X text 154 426 coef2; #X obj 192 426 * -1; #X obj 129 488 * -1; #X obj 106 465 * -1; #X obj 40 465 * 2; #X obj 80 444 *; #X obj 108 204 t a a a, f 29; #X obj 192 392 pow 2; #X obj 65 465 +; #X obj 40 488 *; #X obj 108 285 t a a a; #X text 64 487 gain; #X text 149 132 fc; #X text 237 152 q; #X obj 206 176 max 0.001; #X obj 108 258 min 1; #X obj 128 354 t a a a; #X connect 0 0 7 0; #X connect 1 0 6 0; #X connect 3 0 31 0; #X connect 4 0 3 1; #X connect 5 0 13 0; #X connect 6 0 8 0; #X connect 7 0 2 0; #X connect 8 0 3 0; #X connect 11 0 24 0; #X connect 12 0 39 0; #X connect 13 0 6 0; #X connect 13 1 4 0; #X connect 13 2 12 0; #X connect 14 0 40 0; #X connect 15 0 16 0; #X connect 16 0 41 0; #X connect 20 0 21 0; #X connect 21 0 22 1; #X connect 22 0 28 0; #X connect 24 0 6 0; #X connect 24 1 12 0; #X connect 26 0 27 0; #X connect 27 0 7 5; #X connect 28 0 7 4; #X connect 29 0 34 0; #X connect 30 0 33 1; #X connect 31 0 14 0; #X connect 31 1 20 0; #X connect 31 2 30 1; #X connect 32 0 26 0; #X connect 33 0 34 1; #X connect 34 0 7 1; #X connect 35 0 29 0; #X connect 35 1 33 0; #X connect 35 2 15 0; #X connect 39 0 14 1; #X connect 40 0 35 0; #X connect 41 0 30 0; #X connect 41 1 22 0; #X connect 41 2 32 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/change.pd0000644000000000000000000000116314435670357017270 0ustar00#N canvas 877 436 234 342 10; #N canvas 0 22 260 165 @hv_obj 0; #X obj 60 35 inlet; #X obj 120 35 inlet; #X obj 60 95 outlet; #X obj 120 95 outlet; #X restore 72 169 pd @hv_obj if; #X obj 130 199 t f f; #X obj 22 274 outlet; #X obj 22 48 route bang set; #X obj 130 139 != \$1; #X text 21 305 @hv_arg \$1 value float 0 false; #X obj 22 19 inlet; #X obj 103 76 t f f; #X obj 22 244 f \$1; #X connect 0 1 1 0; #X connect 1 0 8 0; #X connect 1 1 4 1; #X connect 3 0 8 0; #X connect 3 1 4 1; #X connect 3 1 8 1; #X connect 3 2 7 0; #X connect 4 0 0 1; #X connect 6 0 3 0; #X connect 7 0 0 0; #X connect 7 1 4 0; #X connect 8 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/clip.pd0000644000000000000000000000056414435670357016776 0ustar00#N canvas 659 496 326 179 10; #X obj 61 14 inlet; #X obj 104 14 inlet; #X text 14 118 @hv_arg \$1 lower_threshold float 0 false; #X text 14 133 @hv_arg \$2 upper_threshold float 1 false; #X obj 14 39 min \$2; #X obj 14 66 max \$1; #X obj 14 92 outlet; #X obj 14 14 inlet; #X connect 0 0 5 1; #X connect 1 0 4 1; #X connect 4 0 5 0; #X connect 5 0 6 0; #X connect 7 0 4 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/clip~.pd0000644000000000000000000000057014435670357017171 0ustar00#N canvas 409 258 326 179 10; #X obj 14 14 inlet~; #X obj 61 14 inlet; #X obj 104 14 inlet; #X obj 14 92 outlet~; #X text 14 118 @hv_arg \$1 lower_threshold float 0 false; #X text 14 133 @hv_arg \$2 upper_threshold float 1 false; #X obj 14 39 min~ \$2; #X obj 14 66 max~ \$1; #X connect 0 0 6 0; #X connect 1 0 7 1; #X connect 2 0 6 1; #X connect 6 0 7 0; #X connect 7 0 3 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/cnv.pd0000644000000000000000000000016514435670357016632 0ustar00#N canvas 591 233 346 56 10; #X text 11 10 // this patch is left blank \, as the cnv object has no fuction in Heavy; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/cos.pd0000644000000000000000000000033514435670357016627 0ustar00#N canvas 439 480 151 128 10; #X obj 13 20 inlet; #X obj 13 80 outlet; #N canvas 0 22 183 125 @hv_obj 0; #X obj 19 24 inlet; #X obj 19 66 outlet; #X restore 13 50 pd @hv_obj __cos; #X connect 0 0 2 0; #X connect 2 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.272823 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/cos~.pd0000644000000000000000000000226114735300474017016 0ustar00#N canvas 515 39 304 425 10; #X obj 32 167 *~ 6.28319; #X obj 32 17 inlet~; #X obj 31 594 outlet~; #X obj 32 137 -~ 0.25; #X obj 32 77 -~ 0.5; #X obj 32 107 abs~; #X obj 32 47 wrap~; #X obj 64 268 *~; #X obj 92 327 *~; #X obj 127 215 *~; #X text 166 214 x^2; #X text 100 267 x^3; #X text 127 326 x^5; #X obj 32 430 +~; #X obj 32 360 -~; #X obj 65 298 *~ 0.166667; #X obj 92 359 *~ 0.00833333; #X obj 113 391 *~; #X obj 113 425 *~ 0.000198413; #X obj 32 518 -~; #X obj 139 455 *~; #X obj 31 551 +~; #X obj 139 481 *~ 2.75573e-06; #X text 148 390 x^7; #X text 176 454 x^9; #X text 121 166 sine taylor approximation; #X connect 0 0 14 0; #X connect 0 0 7 0; #X connect 0 0 9 0; #X connect 0 0 9 1; #X connect 1 0 6 0; #X connect 3 0 0 0; #X connect 4 0 5 0; #X connect 5 0 3 0; #X connect 6 0 4 0; #X connect 7 0 15 0; #X connect 7 0 8 0; #X connect 8 0 16 0; #X connect 8 0 17 0; #X connect 9 0 8 1; #X connect 9 0 7 1; #X connect 9 0 17 1; #X connect 9 0 20 1; #X connect 13 0 19 0; #X connect 14 0 13 0; #X connect 15 0 14 1; #X connect 16 0 13 1; #X connect 17 0 18 0; #X connect 17 0 20 0; #X connect 18 0 19 1; #X connect 19 0 21 0; #X connect 20 0 22 0; #X connect 21 0 2 0; #X connect 22 0 21 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.769207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/cpole~.pd0000644000000000000000000000107514435670357017345 0ustar00#N canvas 313 179 214 178 10; #X obj 59 35 inlet~; #X obj 20 15 inlet~; #X obj 137 145 outlet~; #X obj 98 77 *~ -1; #X obj 137 76 inlet~; #X obj 98 55 inlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 204 68 inlet~; #X obj 144 68 inlet~; #X obj 225 128 outlet~; #X obj 322 67 inlet~; #X obj 262 67 inlet~; #X obj 160 129 outlet~; #X restore 20 120 pd @hv_obj __cpole~f; #X obj 20 145 outlet~; #X obj 137 98 *~ -1; #X connect 0 0 6 1; #X connect 1 0 6 0; #X connect 3 0 6 2; #X connect 4 0 8 0; #X connect 5 0 3 0; #X connect 6 0 7 0; #X connect 6 1 2 0; #X connect 8 0 6 3; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2785518 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/ctlin.pd0000644000000000000000000000436314677551203017155 0ustar00#N canvas 881 247 766 648 12; #X obj 14 591 outlet; #X obj 229 591 outlet; #X obj 551 591 outlet; #X obj 33 60 loadbang; #X text 19 24 data1/value data0/cc# channel; #X obj 438 56 r __hv_ctlin; #X obj 33 93 t a a; #X obj 33 118 i \$1; #X obj 120 118 i \$2; #X obj 438 81 unpack f f f; #X obj 519 117 + 1; #X obj 519 201 max 1; #X obj 393 225 ==; #X obj 33 143 t f f; #X obj 33 168 == 0; #X obj 14 258 spigot; #X obj 70 258 spigot; #X obj 354 294 spigot; #X text 120 259 0 args case; #X obj 416 436 spigot 1, f 11; #X obj 31 414 spigot 1; #X obj 33 371 == 0; #X text 507 441 this should close if there is 2 args set, f 13; #X text 178 69 the special case when first argument is 0 is buggy at the moment, f 25; #X obj 31 543 spigot 1; #X obj 416 483 spigot 1; #X obj 551 303 spigot; #X obj 120 143 t f f; #X obj 590 270 != 0; #X obj 519 269 t f f; #X obj 468 221 t a a; #X obj 469 460 == 0; #X obj 84 501 ==; #X text 607 305 2 args case; #X obj 519 338 t f f; #X obj 551 366 spigot; #X text 605 365 0 arg case; #X text 420 509 1 arg case; #X obj 416 402 f; #X obj 590 337 t a; #X text 98 536 this will keep open unless there is a second arg and it doesn't match, f 15; #X text 102 409 this will close if there is 0 arg set, f 11; #X obj 393 255 t f b f; #X obj 33 193 t f f f f; #X connect 3 0 6 0; #X connect 5 0 9 0; #X connect 6 0 7 0; #X connect 6 1 8 0; #X connect 7 0 13 0; #X connect 8 0 27 0; #X connect 9 0 15 0; #X connect 9 0 17 0; #X connect 9 1 16 0; #X connect 9 1 12 0; #X connect 9 2 10 0; #X connect 10 0 11 0; #X connect 11 0 29 0; #X connect 12 0 42 0; #X connect 13 0 14 0; #X connect 13 1 12 1; #X connect 14 0 43 0; #X connect 15 0 0 0; #X connect 16 0 1 0; #X connect 17 0 20 0; #X connect 19 0 25 0; #X connect 20 0 24 0; #X connect 21 0 20 1; #X connect 24 0 0 0; #X connect 25 0 1 0; #X connect 26 0 32 0; #X connect 27 0 32 1; #X connect 27 1 30 0; #X connect 28 0 26 1; #X connect 29 0 34 0; #X connect 29 1 26 0; #X connect 30 0 31 0; #X connect 30 1 28 0; #X connect 31 0 25 1; #X connect 32 0 24 1; #X connect 34 0 38 1; #X connect 34 1 35 0; #X connect 35 0 2 0; #X connect 38 0 19 0; #X connect 39 0 35 1; #X connect 42 0 17 1; #X connect 42 1 38 0; #X connect 42 2 19 1; #X connect 43 0 21 0; #X connect 43 1 15 1; #X connect 43 2 16 1; #X connect 43 3 39 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/ctlout.pd0000644000000000000000000000101314435670357017347 0ustar00#N canvas 21 409 309 367 10; #X obj 59 278 pack f f f; #X obj 155 76 loadbang; #X obj 116 156 inlet channel; #X obj 59 310 s __hv_ctlout @hv_param; #X obj 59 46 inlet value; #X obj 116 203 f \$2; #X obj 87 76 inlet cc; #X obj 87 118 f \$1; #X obj 155 98 t b b; #X obj 116 225 - 1; #X obj 116 248 max; #X connect 0 0 3 0; #X connect 1 0 8 0; #X connect 2 0 5 0; #X connect 4 0 0 0; #X connect 5 0 9 0; #X connect 6 0 7 0; #X connect 7 0 0 1; #X connect 8 0 7 0; #X connect 8 1 5 0; #X connect 9 0 10 0; #X connect 10 0 0 2; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/czero_rev~.pd0000644000000000000000000000172514435670357020243 0ustar00#N canvas 561 23 370 282 10; #X obj 164 237 outlet~; #X obj 24 237 outlet~; #X obj 24 24 inlet~ a; #X obj 106 24 inlet~ b; #X obj 194 24 inlet~ c; #X obj 277 24 inlet~ d; #N canvas 0 22 450 300 @hv_obj 0; #X obj 175 149 outlet~; #X obj 173 75 inlet~; #X restore 24 177 pd @hv_obj __del1~f e; #N canvas 0 22 450 300 @hv_obj 0; #X obj 175 149 outlet~; #X obj 173 75 inlet~; #X restore 164 177 pd @hv_obj __del1~f f; #X obj 106 107 *~; #X obj 39 147 -~; #X obj 39 107 *~; #X obj 24 207 -~; #X obj 262 105 *~; #X obj 179 107 *~; #X obj 164 207 -~; #X obj 179 147 +~; #X connect 2 0 6 0; #X connect 2 0 10 0; #X connect 2 0 12 0; #X connect 3 0 7 0; #X connect 3 0 8 0; #X connect 3 0 13 0; #X connect 4 0 10 1; #X connect 4 0 13 1; #X connect 5 0 8 1; #X connect 5 0 12 1; #X connect 6 0 11 0; #X connect 7 0 14 0; #X connect 8 0 9 1; #X connect 9 0 11 1; #X connect 10 0 9 0; #X connect 11 0 1 0; #X connect 12 0 15 1; #X connect 13 0 15 0; #X connect 14 0 0 0; #X connect 15 0 14 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/czero~.pd0000644000000000000000000000172314435670357017365 0ustar00#N canvas 561 23 350 265 10; #X obj 207 217 outlet~; #X obj 16 233 outlet~; #X obj 16 211 +~; #X obj 146 139 *~; #X obj 25 139 *~; #X obj 16 18 inlet~ a; #X obj 161 16 inlet~ b; #X obj 220 17 inlet~ c; #X obj 280 17 inlet~ d; #N canvas 0 22 450 300 @hv_obj 0; #X obj 175 149 outlet~; #X obj 173 75 inlet~; #X restore 25 63 pd @hv_obj __del1~f e; #N canvas 0 22 450 300 @hv_obj 0; #X obj 175 149 outlet~; #X obj 173 75 inlet~; #X restore 161 63 pd @hv_obj __del1~f f; #X obj 31 185 -~; #X obj 205 139 *~; #X obj 265 139 *~; #X obj 250 164 +~; #X obj 207 193 -~; #X connect 2 0 1 0; #X connect 3 0 11 0; #X connect 4 0 11 1; #X connect 5 0 9 0; #X connect 5 0 2 0; #X connect 6 0 10 0; #X connect 6 0 15 0; #X connect 7 0 4 1; #X connect 7 0 12 1; #X connect 8 0 3 0; #X connect 8 0 13 1; #X connect 9 0 4 0; #X connect 9 0 13 0; #X connect 10 0 3 1; #X connect 10 0 12 0; #X connect 11 0 2 1; #X connect 12 0 14 0; #X connect 13 0 14 1; #X connect 14 0 15 1; #X connect 15 0 0 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/dbtopow.pd0000644000000000000000000000126614435670357017525 0ustar00#N canvas 32 267 339 384 10; #X msg 116 264 10; #X obj 116 294 pow; #X obj 116 174 - 100; #X obj 29 30 inlet; #X obj 29 342 outlet; #X obj 29 60 t f f; #X obj 116 88 > 0; #X msg 29 294 0; #X obj 116 144 min 870; #X obj 116 234 t a a; #N canvas 0 22 260 165 @hv_obj 0; #X obj 60 35 inlet; #X obj 120 35 inlet; #X obj 60 95 outlet; #X obj 120 95 outlet; #X restore 29 114 pd @hv_obj __if; #X obj 116 204 / 10; #X connect 0 0 1 0; #X connect 1 0 4 0; #X connect 2 0 11 0; #X connect 3 0 5 0; #X connect 5 0 10 0; #X connect 5 1 6 0; #X connect 6 0 10 1; #X connect 7 0 4 0; #X connect 8 0 2 0; #X connect 9 0 0 0; #X connect 9 1 1 1; #X connect 10 0 7 0; #X connect 10 1 8 0; #X connect 11 0 9 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/dbtopow~.pd0000644000000000000000000000034514435670357017720 0ustar00#N canvas 864 515 183 129 10; #X obj 11 38 -~ 100; #X obj 11 16 inlet~; #X obj 11 104 outlet~; #X obj 11 81 exp~; #X obj 11 60 *~ 0.230258509299405; #X connect 0 0 4 0; #X connect 1 0 0 0; #X connect 3 0 2 0; #X connect 4 0 3 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/dbtorms.pd0000644000000000000000000000126414435670357017517 0ustar00#N canvas 0 183 339 384 10; #X msg 116 264 10; #X obj 116 294 pow; #X obj 116 174 - 100; #X obj 29 30 inlet; #X obj 29 342 outlet; #X obj 29 60 t f f; #X obj 116 88 > 0; #X obj 116 144 min 485; #X msg 29 294 0; #N canvas 0 22 260 165 @hv_obj 0; #X obj 60 35 inlet; #X obj 120 35 inlet; #X obj 60 95 outlet; #X obj 120 95 outlet; #X restore 29 114 pd @hv_obj __if; #X obj 116 204 / 20; #X obj 116 234 t a a; #X connect 0 0 1 0; #X connect 1 0 4 0; #X connect 2 0 10 0; #X connect 3 0 5 0; #X connect 5 0 9 0; #X connect 5 1 6 0; #X connect 6 0 9 1; #X connect 7 0 2 0; #X connect 8 0 4 0; #X connect 9 0 8 0; #X connect 9 1 7 0; #X connect 10 0 11 0; #X connect 11 0 0 0; #X connect 11 1 1 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/dbtorms~.pd0000644000000000000000000000034514435670357017714 0ustar00#N canvas 973 242 183 134 10; #X obj 11 38 -~ 100; #X obj 11 16 inlet~; #X obj 11 104 outlet~; #X obj 11 81 exp~; #X obj 11 60 *~ 0.115129254649702; #X connect 0 0 4 0; #X connect 1 0 0 0; #X connect 3 0 2 0; #X connect 4 0 3 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/declare.pd0000644000000000000000000000007514435670357017443 0ustar00#N canvas 612 207 258 179 10; #X text 35 49 // dummy object; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/del.pd0000644000000000000000000000033514435670357016607 0ustar00#N canvas 66 332 226 143 10; #X obj 13 16 inlet; #X obj 58 16 inlet; #X obj 13 67 outlet; #X text 12 94 @hv_arg \$1 delay float 0 false; #X obj 13 42 delay \$1; #X connect 0 0 4 0; #X connect 1 0 4 1; #X connect 4 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/delay.pd0000644000000000000000000000122114435670357017134 0ustar00#N canvas 362 256 269 251 10; #X obj 21 20 inlet; #X obj 144 20 inlet; #X obj 21 221 outlet; #X text 67 221 @hv_arg \$1 delay float 0 false; #N canvas 0 22 450 300 @hv_obj 0; #X obj 179 47 inlet; #X obj 275 124 outlet; #X obj 209 124 outlet; #X restore 21 43 pd @hv_obj __switchcase stop; #X msg 21 149 clear; #N canvas 377 209 450 300 @hv_obj 0; #X obj 152 38 inlet; #X obj 261 44 inlet; #X obj 199 177 outlet; #X restore 21 196 pd @hv_obj __delay \$1; #X obj 186 67 t b a a; #X connect 0 0 4 0; #X connect 1 0 6 1; #X connect 4 0 5 0; #X connect 4 1 7 0; #X connect 5 0 6 0; #X connect 6 0 2 0; #X connect 7 0 6 0; #X connect 7 1 6 1; #X connect 7 2 5 0; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2785518 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/delread4~.pd0000644000000000000000000000641414677551203017725 0ustar00#N canvas 859 23 532 664 10; #X obj 19 26 inlet~; #X obj 4 638 outlet~; #X obj 19 163 *~; #X obj 34 116 samplerate~; #X text 79 140 convert millisecond delay to sample delay; #N canvas 0 22 450 300 @hv_obj 0; #X obj 146 77 inlet; #X obj 147 120 outlet; #X restore 95 93 pd @hv_obj system; #X obj 4 302 -~; #X obj 4 409 +~; #X text 33 301 table index; #X obj 19 565 -~; #X obj 47 565 -~; #X obj 19 589 *~; #X obj 4 613 +~; #X text 73 566 linear interpolation; #N canvas 587 66 450 300 @hv_obj 0; #X obj 146 106 inlet~; #X obj 154 156 outlet~; #X obj 239 103 inlet~; #X restore 35 385 pd @hv_obj __and~f; #X obj 4 279 +~; #X obj 68 26 t a a; #N canvas 587 66 450 300 @hv_obj 0; #X obj 221 104 inlet~; #X obj 154 156 outlet~; #X obj 146 106 inlet~; #X restore 150 363 pd @hv_obj __lt~f; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X restore 4 438 pd @hv_obj __cast~fi; #N canvas 0 23 450 300 @hv_obj 0; #X obj 232 43 inlet~; #X obj 169 185 outlet~; #X obj 165 46 inlet~; #X restore 195 478 pd @hv_obj __add~i; #N canvas 0 22 450 300 @hv_obj 0; #X obj 173 75 inlet; #X obj 175 149 outlet~; #X restore 300 456 pd @hv_obj __var_k~i 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 173 75 inlet; #X obj 175 149 outlet~; #X restore 249 341 pd @hv_obj __var_k~f 0; #X obj 95 49 symbol del-\$1; #X obj 34 139 / 1000; #N canvas 587 66 450 300 @hv_obj 0; #X obj 154 156 outlet~; #X obj 146 106 inlet; #X restore 4 234 pd @hv_obj __tabhead~f del-\$1; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X obj 280 42 inlet; #X restore 195 501 pd @hv_obj __tabread~if del-\$1; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X obj 249 48 inlet; #X restore 4 501 pd @hv_obj __tabread~if del-\$1; #X text 182 49 @hv_arg \$1 table string "" true; #N canvas 0 22 450 300 @hv_obj 0; #X obj 148 99 inlet; #X obj 143 158 outlet~; #X restore 27 257 pd @hv_obj __var_k~f -1 -1 true; #X obj 68 4 loadbang -1; #X msg 95 71 table \$1 size; #X text 150 430 NOTE(mhroth): SSE cast op seems to round to the nearest int \, not down; #X obj 19 210 max~ 0; #X obj 19 188 min~; #X text 70 202 [0 \, size-1]; #X text 71 187 ensure that the input never exceeds the table bounds ; #X obj 45 163 - 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 160 52 inlet~; #X obj 173 97 outlet~; #X restore 4 331 pd @hv_obj __floor~f; #X text 30 412 wrapped table index; #N canvas 0 22 450 300 @hv_obj 0; #X obj 148 99 inlet; #X obj 143 158 outlet~; #X restore 35 362 pd @hv_obj var; #X connect 0 0 2 0; #X connect 2 0 33 0; #X connect 3 0 23 0; #X connect 5 0 36 0; #X connect 5 0 39 0; #X connect 6 0 37 0; #X connect 6 0 10 0; #X connect 7 0 18 0; #X connect 9 0 11 0; #X connect 10 0 11 1; #X connect 11 0 12 1; #X connect 12 0 1 0; #X connect 14 0 7 1; #X connect 15 0 6 0; #X connect 16 0 3 0; #X connect 16 1 22 0; #X connect 17 0 14 1; #X connect 18 0 26 0; #X connect 18 0 19 0; #X connect 19 0 25 0; #X connect 20 0 19 1; #X connect 21 0 17 1; #X connect 22 0 30 0; #X connect 23 0 2 1; #X connect 24 0 15 0; #X connect 25 0 9 0; #X connect 26 0 9 1; #X connect 26 0 12 0; #X connect 28 0 15 1; #X connect 29 0 16 0; #X connect 30 0 5 0; #X connect 32 0 6 1; #X connect 33 0 32 0; #X connect 36 0 33 1; #X connect 37 0 17 0; #X connect 37 0 10 1; #X connect 37 0 7 0; #X connect 39 0 14 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/delread~.pd0000644000000000000000000000507314435670357017645 0ustar00#N canvas 238 23 573 595 10; #N canvas 0 22 450 300 @hv_obj 0; #X obj 167 41 inlet; #X obj 178 113 outlet; #X restore 17 86 pd @hv_obj __tabhead del-\$1; #X obj 32 111 samplerate~; #X text 66 156 ms to samples; #X obj 32 156 * \$2; #X obj 32 134 / 1000; #X obj 17 226 -; #N canvas 0 22 450 300 @hv_obj 0; #X obj 152 55 inlet; #X obj 145 120 outlet; #X restore 83 298 pd @hv_obj system; #X msg 83 274 table \$1 size; #N canvas 0 22 450 300 @hv_obj 0; #X obj 186 57 inlet; #X obj 190 116 outlet; #X restore 83 251 pd @hv_obj __var del-\$1; #N canvas 0 22 258 159 @hv_obj 0; #X obj 37 33 inlet; #X obj 141 33 inlet; #X obj 53 104 outlet; #X obj 88 31 inlet; #X restore 87 436 pd @hv_obj __delay \$2; #X obj 75 520 outlet~; #X text 74 562 @hv_arg \$2 delay float 10 true; #X text 74 543 @hv_arg \$1 table string "" true; #X msg 95 407 clear; #X obj 224 469 t a a; #N canvas 0 22 450 300 @hv_obj 0; #X obj 154 94 inlet; #X obj 191 93 inlet; #X obj 170 165 outlet; #X obj 233 92 inlet; #X restore 87 469 pd @hv_obj __delay; #X obj 95 6 inlet delay-ms; #X obj 17 6 loadbang -1; #X text 205 7 NOTE(mhroth): there may be an issue here in which; #X text 223 24 tabread sets itself to a different offset than; #X text 224 42 the input \, due to alignment issues.; #X text 224 58 But the first delay is set based on the original offset ; #X text 224 74 which may account for the difference of a few samples ; #X msg 47 178 @HV_N_SIMD; #X text 56 201 add minimum delay of HV_N_SIMD; #X obj 32 200 max; #X obj 56 345 t b a a; #X obj 17 32 t a a; #X obj 17 57 t a a a; #X obj 210 412 * -1; #X obj 210 391 -; #X text 263 469 delay from one end of the table to the other; #X text 222 435 delay from current head to the end of the table; #X obj 95 31 t b a; #N canvas 172 223 450 300 @hv_obj 0; #X obj 169 93 inlet; #X obj 156 131 outlet~; #X obj 229 137 outlet; #X restore 75 497 pd @hv_obj __tabread~f del-\$1; #X connect 0 0 5 0; #X connect 1 0 4 0; #X connect 3 0 25 0; #X connect 4 0 3 0; #X connect 5 0 26 0; #X connect 6 0 30 1; #X connect 6 0 15 2; #X connect 7 0 6 0; #X connect 8 0 7 0; #X connect 9 0 15 0; #X connect 9 0 34 0; #X connect 13 0 9 0; #X connect 13 0 15 0; #X connect 14 0 15 0; #X connect 14 1 34 0; #X connect 15 0 14 0; #X connect 16 0 33 0; #X connect 17 0 27 0; #X connect 23 0 25 1; #X connect 25 0 5 1; #X connect 26 0 9 0; #X connect 26 1 34 0; #X connect 26 2 13 0; #X connect 27 0 28 0; #X connect 27 1 23 0; #X connect 28 0 0 0; #X connect 28 1 1 0; #X connect 28 2 8 0; #X connect 29 0 9 2; #X connect 30 0 29 0; #X connect 33 0 28 0; #X connect 33 1 3 1; #X connect 34 0 10 0; #X connect 34 1 30 0; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5991824 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/delwrite~.pd0000644000000000000000000000323014735300037020041 0ustar00#N canvas 973 266 457 387 10; #N canvas 0 22 450 300 @hv_obj 0; #X obj 48 70 inlet~; #X obj 147 72 inlet; #X restore 10 309 pd @hv_obj __tabwrite~f del-\$1; #X text 9 356 @hv_arg \$2 delay float 0 true; #X obj 187 134 samplerate~; #X obj 187 174 * \$2; #N canvas 0 22 450 300 @hv_obj 0; #X obj 142 60 inlet; #X obj 135 103 outlet; #X restore 187 214 pd @hv_obj table del-\$1; #X msg 187 194 resize \$1; #X text 9 337 @hv_arg \$1 table string "" true; #X obj 187 154 / 1000; #N canvas 0 22 450 300 @hv_obj 0; #X obj 215 71 inlet; #X obj 165 71 inlet; #X obj 120 72 inlet; #X obj 129 122 outlet; #X restore 187 262 pd @hv_obj __delay; #X obj 187 111 loadbang; #X obj 187 285 t a a a; #X msg 226 331 mirror; #N canvas 0 22 450 300 @hv_obj 0; #X obj 215 71 inlet; #X obj 165 71 inlet; #X obj 120 72 inlet; #X obj 129 122 outlet; #X restore 226 309 pd @hv_obj __delay; #X obj 187 237 t b a a, f 25; #X text 254 193 returns the size of the table; #X msg 331 262 @HV_N_SIMD; #N canvas 1401 0 450 300 @hv_obj 0; #X obj 48 57 inlet; #X obj 48 114 outlet; #X restore 83 52 pd @hv_obj __switchcase clear; #X msg 83 75 clear; #X text 80 32 connection from the left inlet to the switchcase; #X text 81 21 NOTE(dreamer): there is supposed to be a control; #X obj 10 26 inlet~ -~>; #X connect 2 0 7 0; #X connect 3 0 5 0; #X connect 4 0 13 0; #X connect 5 0 4 0; #X connect 7 0 3 0; #X connect 8 0 10 0; #X connect 9 0 2 0; #X connect 10 0 0 1; #X connect 10 1 8 0; #X connect 10 2 12 0; #X connect 11 0 4 0; #X connect 12 0 11 0; #X connect 13 0 8 0; #X connect 13 1 8 2; #X connect 13 2 15 0; #X connect 15 0 12 2; #X connect 16 0 17 0; #X connect 17 0 0 1; #X connect 20 0 0 0; #X connect 20 0 16 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/div.pd0000644000000000000000000000052714435670357016630 0ustar00#N canvas 710 85 214 110 10; #X obj 12 59 outlet; #X obj 12 12 inlet -->; #X obj 141 13 inlet -->; #X text 11 81 @hv_arg \$1 k float 1 false; #N canvas 0 22 450 300 @hv_obj 0; #X obj 212 64 inlet; #X obj 163 64 inlet; #X obj 173 116 outlet; #X restore 12 35 pd @hv_obj __intdiv \$1; #X connect 1 0 4 0; #X connect 2 0 4 1; #X connect 4 0 0 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/env~.pd0000644000000000000000000000052614435670357017033 0ustar00#N canvas 241 322 302 155 10; #X obj 20 19 inlet~; #X obj 20 65 outlet; #N canvas 0 22 450 300 @hv_obj 0; #X obj 156 85 inlet~; #X obj 162 188 outlet; #X restore 20 42 pd @hv_obj __env~f \$1 \$2; #X text 19 91 @hv_arg \$1 windowSize float 1024 false; #X text 19 109 @hv_arg \$2 period float 512 false; #X connect 0 0 2 0; #X connect 2 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/exp.pd0000644000000000000000000000041414435670357016635 0ustar00#N canvas 556 377 141 159 10; #X obj 13 19 inlet; #X obj 13 110 outlet; #N canvas 0 22 183 125 @hv_obj 0; #X obj 19 66 outlet; #X obj 19 24 inlet; #X restore 13 80 pd @hv_obj __exp; #X obj 13 49 min 87.3365; #X connect 0 0 3 0; #X connect 2 0 1 0; #X connect 3 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/exp~.pd0000644000000000000000000000034414435670357017035 0ustar00#N canvas 164 442 186 95 10; #X obj 12 7 inlet~; #X obj 12 53 outlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 193 52 inlet~; #X obj 188 146 outlet~; #X restore 12 31 pd @hv_obj __exp~f; #X connect 0 0 2 0; #X connect 2 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/f.pd0000644000000000000000000000052014435670357016264 0ustar00#N canvas 0 149 210 157 10; #X text 11 119 @hv_arg \$1 k float 0 false; #N canvas 0 22 183 125 @hv_obj 0; #X obj 78 24 inlet; #X obj 19 66 outlet; #X obj 19 24 inlet; #X restore 13 60 pd @hv_obj __var \$1; #X obj 13 90 outlet; #X obj 13 20 inlet -->; #X obj 124 20 inlet -->; #X connect 1 0 2 0; #X connect 3 0 1 0; #X connect 4 0 1 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/float.pd0000644000000000000000000000052014435670357017144 0ustar00#N canvas 0 149 210 157 10; #X text 11 119 @hv_arg \$1 k float 0 false; #N canvas 0 22 183 125 @hv_obj 0; #X obj 78 24 inlet; #X obj 19 66 outlet; #X obj 19 24 inlet; #X restore 13 60 pd @hv_obj __var \$1; #X obj 13 90 outlet; #X obj 13 20 inlet -->; #X obj 124 20 inlet -->; #X connect 1 0 2 0; #X connect 3 0 1 0; #X connect 4 0 1 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/floatatom.pd0000644000000000000000000000025514435670357020032 0ustar00#N canvas 202 244 210 108 10; #X obj 17 9 inlet; #X obj 17 55 outlet; #X text 15 76 @hv_arg \$1 k float 0 false; #X obj 17 32 f \$1; #X connect 0 0 3 0; #X connect 3 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/ftom.pd0000644000000000000000000000207214435670357017010 0ustar00#N canvas 0 37 423 374 10; #X obj 21 19 inlet; #X obj 21 269 outlet; #X obj 108 139 / 440; #X obj 108 199 * 12; #X obj 108 229 + 69; #X text 19 299 // Note: Pd's internal implementation of [ftom] uses doubles instead of floats so there will be slight rounding discrepencies. ; #X obj 21 49 t f f; #X obj 108 79 > 0; #X msg 21 229 -1500; #N canvas 0 22 450 300 @hv_obj 0; #X obj 43 62 inlet; #X obj 43 84 outlet; #X obj 103 62 inlet; #X obj 103 84 outlet; #X connect 0 0 1 0; #X connect 2 0 3 0; #X restore 21 109 pd @hv_obj __if; #N canvas 0 22 450 300 @hv_obj 0; #X obj 65 52 inlet; #X obj 65 152 outlet; #X obj 65 74 log; #X obj 65 126 /; #X obj 114 124 log; #X obj 113 69 loadbang; #X msg 113 91 2; #X connect 0 0 2 0; #X connect 2 0 3 0; #X connect 3 0 1 0; #X connect 4 0 3 1; #X connect 5 0 6 0; #X connect 6 0 4 0; #X restore 108 169 pd @hv_obj __log2; #X connect 0 0 6 0; #X connect 2 0 10 0; #X connect 3 0 4 0; #X connect 4 0 1 0; #X connect 6 0 9 0; #X connect 6 1 7 0; #X connect 7 0 9 1; #X connect 8 0 1 0; #X connect 9 0 8 0; #X connect 9 1 2 0; #X connect 10 0 3 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/ftom~.pd0000644000000000000000000000056114435670357017207 0ustar00#N canvas 336 416 153 151 10; #X obj 14 125 outlet~; #X obj 14 11 inlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 133 40 inlet~; #X obj 134 119 outlet~; #X restore 14 80 pd @hv_obj __log2~f; #X obj 14 102 *~ 12; #X obj 14 57 *~ 0.122312205855086; #X obj 14 34 max~ 0; #X connect 1 0 5 0; #X connect 2 0 3 0; #X connect 3 0 0 0; #X connect 4 0 2 0; #X connect 5 0 4 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/hip~.pd0000644000000000000000000000232714435670357017024 0ustar00#N canvas 524 123 547 510 10; #X text 96 432 @hv_arg \$1 fc float 0 false; #X obj 172 361 + 1; #X obj 172 383 * 0.5; #X obj 28 411 *~; #X msg 145 197 1 \$1; #X obj 145 217 -; #X obj 145 237 clip 0 1; #X obj 61 360 sig~ 1; #X obj 28 387 rzero~; #X obj 145 310 sig~; #X obj 169 50 loadbang; #X obj 145 105 f \$1; #X obj 169 75 t a a; #X obj 28 432 outlet~; #X obj 145 257 t a a; #X obj 28 27 inlet~; #X obj 145 27 inlet fc; #N canvas 0 22 450 300 @hv_obj 0; #X obj 130 85 inlet~; #X obj 81 86 inlet~; #X obj 103 163 outlet~; #X restore 28 335 pd @hv_obj __rpole~f; #X obj 145 284 * -1; #X obj 145 126 max 1; #X obj 196 105 samplerate~; #X obj 145 148 * 6.28319; #X obj 145 173 /; #X text 193 125 hip~ 0 in Pd is a passthrough \, so we limit the cutoff ; #X connect 1 0 2 0; #X connect 2 0 3 1; #X connect 3 0 13 0; #X connect 4 0 5 0; #X connect 5 0 6 0; #X connect 6 0 14 0; #X connect 7 0 8 1; #X connect 8 0 3 0; #X connect 9 0 17 1; #X connect 10 0 12 0; #X connect 11 0 19 0; #X connect 12 0 11 0; #X connect 12 1 20 0; #X connect 14 0 18 0; #X connect 14 1 1 0; #X connect 15 0 17 0; #X connect 16 0 11 0; #X connect 17 0 8 0; #X connect 18 0 9 0; #X connect 19 0 21 0; #X connect 20 0 22 1; #X connect 21 0 22 0; #X connect 22 0 4 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/hradio.pd0000644000000000000000000000020314435670357017303 0ustar00#N canvas 0 149 210 157 10; #X obj 24 35 inlet; #X obj 24 57 float 0; #X obj 24 79 outlet; #X connect 0 0 1 0; #X connect 1 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/hsl.pd0000644000000000000000000000020314435670357016623 0ustar00#N canvas 0 149 210 157 10; #X obj 24 35 inlet; #X obj 24 57 float 0; #X obj 24 79 outlet; #X connect 0 0 1 0; #X connect 1 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/i.pd0000644000000000000000000000032414435670357016271 0ustar00#N canvas 872 130 183 121 10; #X obj 7 10 inlet; #X obj 40 31 inlet; #X obj 7 76 outlet; #X text 7 96 @hv_arg \$1 k float 0 false; #X obj 7 52 int \$1; #X connect 0 0 4 0; #X connect 1 0 4 1; #X connect 4 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/int.pd0000644000000000000000000000154314435670357016637 0ustar00#N canvas 872 130 257 234 10; #X obj 14 10 inlet; #X obj 14 56 f \$1; #X obj 35 31 inlet; #X obj 14 183 outlet; #N canvas 0 22 450 300 @hv_obj 0; #X obj 148 66 inlet; #X obj 222 64 inlet; #X obj 140 131 outlet; #X obj 233 141 outlet; #X restore 14 129 pd @hv_obj if \$1; #X obj 107 104 > 0; #N canvas 0 22 260 165 @hv_obj 0; #X obj 60 35 inlet; #X obj 120 35 inlet; #X obj 60 95 outlet; #X obj 120 95 outlet; #X restore 134 155 pd @hv_obj __floor; #N canvas 0 22 260 165 @hv_obj 0; #X obj 60 35 inlet; #X obj 120 35 inlet; #X obj 60 95 outlet; #X obj 120 95 outlet; #X restore 14 155 pd @hv_obj __ceil; #X text 11 205 @hv_arg \$1 k float 0 false; #X obj 14 80 t a a; #X connect 0 0 1 0; #X connect 1 0 9 0; #X connect 2 0 1 1; #X connect 4 0 7 0; #X connect 4 1 6 0; #X connect 5 0 4 1; #X connect 6 0 3 0; #X connect 7 0 3 0; #X connect 9 0 4 0; #X connect 9 1 5 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/line.pd0000644000000000000000000000524414435670357016776 0ustar00#N canvas 300 23 663 743 10; #X obj 118 709 outlet; #X obj 22 17 inlet target; #X obj 452 120 samplerate~; #X obj 437 317 / 1000; #X obj 437 293 *; #X obj 118 409 metro 20; #X obj 464 341 *; #X obj 465 363 / 1000; #X obj 118 449 f; #X obj 148 449 -; #X msg 118 378 1; #X obj 118 509 sel 0 1; #X msg 174 569 0; #X obj 118 479 <= 0; #X obj 159 649 +; #X obj 371 287 / 20; #X obj 270 457 /; #X obj 371 263 t f f; #X obj 190 276 t f f; #X obj 137 539 t b b; #X text 482 316 num samples to target; #X text 295 460 slope; #X obj 214 709 +; #X text 469 397 next output value; #X obj 452 142 t a a; #X obj 22 47 route stop set; #X msg 22 232 0; #X obj 165 202 inlet ramp; #X obj 373 17 inlet grain; #X text 284 691 @hv_arg \$1 initial_value float 0 false; #X text 284 707 @hv_arg \$2 grain float 20 false; #X obj 150 232 f 0; #X msg 103 93 0; #X obj 373 120 f \$2; #X obj 373 70 max 0; #X obj 373 143 sel 0; #X msg 373 167 20; #X obj 432 397 f \$1; #X obj 137 569 f; #X obj 118 649 f \$1; #X obj 62 187 t f b; #X obj 190 306 -; #X obj 174 597 t a a; #X obj 174 621 t a a; #X obj 195 458 t a a b; #X obj 373 193 t a a a; #X obj 118 679 t a a; #X obj 413 96 t a a a; #X obj 137 114 unpack f f; #X obj 103 70 t b b a b; #X obj 413 71 loadbang; #X connect 1 0 25 0; #X connect 2 0 24 0; #X connect 3 0 8 1; #X connect 4 0 3 0; #X connect 5 0 8 0; #X connect 6 0 7 0; #X connect 7 0 9 1; #X connect 8 0 9 0; #X connect 8 0 13 0; #X connect 9 0 8 1; #X connect 10 0 5 0; #X connect 11 0 39 0; #X connect 11 1 19 0; #X connect 12 0 42 0; #X connect 13 0 11 0; #X connect 14 0 39 1; #X connect 15 0 16 1; #X connect 16 0 43 0; #X connect 17 0 15 0; #X connect 17 1 4 0; #X connect 18 0 41 0; #X connect 18 1 38 1; #X connect 19 0 38 0; #X connect 19 1 12 0; #X connect 22 0 37 0; #X connect 24 0 4 1; #X connect 24 1 6 1; #X connect 25 0 26 0; #X connect 25 1 40 0; #X connect 25 2 49 0; #X connect 26 0 5 0; #X connect 27 0 31 1; #X connect 28 0 34 0; #X connect 31 0 17 0; #X connect 32 0 31 1; #X connect 33 0 35 0; #X connect 34 0 33 0; #X connect 35 0 36 0; #X connect 35 1 45 0; #X connect 36 0 45 0; #X connect 37 0 41 1; #X connect 38 0 39 0; #X connect 39 0 14 0; #X connect 39 0 46 0; #X connect 40 0 44 0; #X connect 40 1 26 0; #X connect 41 0 16 0; #X connect 42 0 43 0; #X connect 42 1 5 0; #X connect 43 0 14 1; #X connect 43 1 22 1; #X connect 44 0 39 1; #X connect 44 1 22 0; #X connect 44 2 12 0; #X connect 45 0 5 1; #X connect 45 1 15 1; #X connect 45 2 6 0; #X connect 46 0 0 0; #X connect 46 1 22 0; #X connect 47 0 33 0; #X connect 47 1 37 0; #X connect 47 2 2 0; #X connect 48 0 18 0; #X connect 48 1 17 0; #X connect 49 0 32 0; #X connect 49 1 10 0; #X connect 49 2 48 0; #X connect 49 3 31 0; #X connect 50 0 47 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/line~.pd0000644000000000000000000000045314435670357017171 0ustar00#N canvas 604 23 250 152 10; #X obj 24 28 inlet -->; #X obj 135 28 inlet -->; #N canvas 0 22 450 300 @hv_obj 0; #X obj 41 54 inlet; #X obj 89 60 inlet; #X obj 52 134 outlet~; #X restore 24 58 pd @hv_obj __line~f; #X obj 24 88 outlet~ ~f>; #X connect 0 0 2 0; #X connect 1 0 2 1; #X connect 2 0 3 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/loadbang.pd0000644000000000000000000000022314435670357017606 0ustar00#N canvas 880 53 226 80 10; #X obj 12 11 r __hv_init \$1; #X obj 12 34 outlet; #X text 12 58 @hv_arg \$1 priority int 0 false; #X connect 0 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/log.pd0000644000000000000000000000033514435670357016624 0ustar00#N canvas 439 480 151 128 10; #X obj 13 20 inlet; #X obj 13 80 outlet; #N canvas 0 22 183 125 @hv_obj 0; #X obj 19 24 inlet; #X obj 19 66 outlet; #X restore 13 50 pd @hv_obj __log; #X connect 0 0 2 0; #X connect 2 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/lop~.pd0000644000000000000000000000210014435670357017023 0ustar00#N canvas 659 183 231 379 10; #X text 21 347 @hv_arg \$1 fc float 22050 false; #X obj 62 70 loadbang; #X obj 23 22 inlet~; #X obj 38 125 f \$1; #N canvas 870 68 227 202 hz2rad 0; #X obj 88 50 samplerate~; #X obj 28 148 *; #X obj 28 178 outlet; #X obj 28 20 inlet fc; #X obj 88 20 inlet init; #X obj 88 108 /, f 5; #X msg 88 76 6.28319 \$1; #X connect 0 0 6 0; #X connect 1 0 2 0; #X connect 3 0 1 0; #X connect 4 0 0 0; #X connect 5 0 1 1; #X connect 6 0 5 0; #X restore 38 150 pd hz2rad; #X obj 23 227 *~; #X obj 38 47 inlet; #X obj 140 274 sig~; #X obj 23 325 outlet~; #X obj 38 176 clip 0 1; #X obj 38 202 t a a; #X obj 62 95 t a a; #N canvas 0 22 450 300 @hv_obj 0; #X obj 130 85 inlet~; #X obj 81 86 inlet~; #X obj 103 163 outlet~; #X restore 23 298 pd @hv_obj __rpole~f; #X obj 140 250 - 1; #X connect 1 0 11 0; #X connect 2 0 5 0; #X connect 3 0 4 0; #X connect 4 0 9 0; #X connect 5 0 12 0; #X connect 6 0 3 0; #X connect 7 0 12 1; #X connect 9 0 10 0; #X connect 10 0 5 1; #X connect 10 1 13 0; #X connect 11 0 3 0; #X connect 11 1 4 1; #X connect 12 0 8 0; #X connect 13 0 7 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/makenote.pd0000644000000000000000000000202314435670357017642 0ustar00#N canvas 732 230 504 438 10; #X obj 37 34 inlet pitch; #X obj 155 31 inlet velocity; #X obj 325 31 inlet duration; #X msg 102 342 0; #X obj 257 31 loadbang; #X obj 325 143 f \$2; #X obj 325 165 max 0; #X obj 37 250 pipe; #X obj 141 373 outlet velocity; #X obj 37 373 outlet pitch; #X obj 37 190 spigot 0; #X obj 155 99 f \$1; #X obj 141 314 f; #X obj 182 147 != 0; #X text 209 260 @hv_arg \$1 velocity float 0 false; #X text 209 281 @hv_arg \$2 duration float 0 false; #X obj 257 53 t a a; #X obj 155 123 t a a; #X obj 37 214 t a a; #X obj 37 293 t a a; #X obj 114 283 t a b; #X connect 0 0 10 0; #X connect 1 0 11 0; #X connect 2 0 5 0; #X connect 3 0 8 0; #X connect 4 0 16 0; #X connect 5 0 6 0; #X connect 6 0 7 1; #X connect 7 0 19 0; #X connect 10 0 18 0; #X connect 11 0 17 0; #X connect 12 0 8 0; #X connect 13 0 10 1; #X connect 16 0 11 0; #X connect 16 1 5 0; #X connect 17 0 12 1; #X connect 17 1 13 0; #X connect 18 0 7 0; #X connect 18 1 20 0; #X connect 19 0 9 0; #X connect 19 1 3 0; #X connect 20 0 9 0; #X connect 20 1 12 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/metro.pd0000644000000000000000000000224114435670357017167 0ustar00#N canvas 115 218 483 232 10; #X obj 62 50 inlet; #X obj 255 7 inlet; #X obj 62 205 outlet; #X text 112 206 @hv_arg \$1 period float 1000 false; #N canvas 0 22 450 300 @hv_obj 0; #X obj 158 79 inlet; #X obj 173 183 outlet; #X obj 275 180 outlet; #X obj 116 183 outlet; #X restore 62 76 pd @hv_obj __switchcase 0 stop; #X msg 150 145 clear; #X obj 62 175 t a a; #N canvas 0 22 450 300 @hv_obj 0; #X obj 133 43 inlet; #X obj 197 44 inlet; #X obj 179 240 outlet; #X obj 272 47 inlet; #X restore 150 175 pd @hv_obj __delay; #X obj 62 122 bang; #X obj 62 145 t a a; #X text 264 162 minimum period is set to one sample; #X obj 255 145 max 1; #X obj 292 76 samplerate~; #X obj 292 99 / 1000; #X obj 255 123 *; #X obj 255 76 f \$1; #X obj 265 52 t a a; #X obj 265 29 loadbang; #X connect 0 0 4 0; #X connect 1 0 15 0; #X connect 4 0 5 0; #X connect 4 1 5 0; #X connect 4 2 8 0; #X connect 5 0 7 0; #X connect 6 0 2 0; #X connect 6 1 7 0; #X connect 7 0 6 0; #X connect 8 0 9 0; #X connect 9 0 6 0; #X connect 9 1 5 0; #X connect 11 0 7 2; #X connect 12 0 13 0; #X connect 13 0 14 1; #X connect 14 0 11 0; #X connect 15 0 14 0; #X connect 16 0 15 0; #X connect 16 1 12 0; #X connect 17 0 16 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/midiin.pd0000644000000000000000000000037214435670357017315 0ustar00#N canvas 814 376 208 199 10; #X obj 77 126 outlet; #X obj 20 148 outlet; #X obj 20 37 r __hv_midiin; #X text 18 13 data port; #X obj 20 61 unpack f f; #X obj 77 93 + 1; #X connect 2 0 4 0; #X connect 4 0 1 0; #X connect 4 1 5 0; #X connect 5 0 0 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/midiout.pd0000644000000000000000000000057214435670357017520 0ustar00#N canvas 1026 489 417 247 10; #X obj 56 62 inlet data; #X obj 140 63 inlet port; #X obj 56 190 s __hv_midiout @hv_param; #X obj 140 161 s __hv_midioutport @hv_param; #X text 33 28 data packed in message; #X obj 152 95 loadbang; #X obj 140 130 f \$1; #X text 223 66 port is on separate Heavy send; #X connect 0 0 2 0; #X connect 1 0 6 0; #X connect 5 0 6 0; #X connect 6 0 3 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.272823 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/midirealtimein.pd0000644000000000000000000000033414735300474021027 0ustar00#N canvas 951 312 204 190 12; #X obj 86 148 outlet; #X obj 20 148 outlet; #X text 23 13 data port; #X obj 20 61 unpack f f; #X obj 20 37 r __hv_midirealtimein; #X connect 3 0 1 0; #X connect 3 1 0 0; #X connect 4 0 3 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/moses.pd0000644000000000000000000000076614435670357017201 0ustar00#N canvas 623 160 245 197 10; #X obj 15 12 inlet; #X obj 129 12 inlet; #X obj 15 122 outlet; #X obj 102 122 outlet; #X obj 102 63 >= \$1; #X text 13 162 @hv_arg \$1 threshold float 0 false; #X obj 15 35 t a a; #N canvas 0 22 260 165 @hv_obj 0; #X obj 60 35 inlet; #X obj 120 35 inlet; #X obj 60 95 outlet; #X obj 120 95 outlet; #X restore 15 92 pd @hv_obj __if; #X connect 0 0 6 0; #X connect 1 0 4 1; #X connect 4 0 7 1; #X connect 6 0 7 0; #X connect 6 1 4 0; #X connect 7 0 2 0; #X connect 7 1 3 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/mtof.pd0000644000000000000000000000075414435670357017015 0ustar00#N canvas 96 248 412 280 10; #X text 24 213 // Note: Pd's internal implementation of [mtof] uses doubles instead of floats so there will be slight rounding discrepencies. ; #X obj 25 20 inlet; #X obj 25 185 outlet; #X obj 25 162 * 440; #X obj 25 44 - 69; #X obj 25 68 / 12; #X obj 25 139 pow 1; #X msg 25 116 2; #X obj 25 92 t a a; #X connect 1 0 4 0; #X connect 3 0 2 0; #X connect 4 0 5 0; #X connect 5 0 8 0; #X connect 6 0 3 0; #X connect 7 0 6 0; #X connect 8 0 7 0; #X connect 8 1 6 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.770207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/mtof~.pd0000644000000000000000000000055614435670357017213 0ustar00#N canvas 672 125 396 190 10; #X obj 14 102 outlet~; #X obj 14 57 exp~; #X obj 14 11 inlet~; #X obj 14 34 *~ 0.057762265046662; #X obj 14 79 *~ 8.175798915643707; #X text 12 126 NOTE(mhroth): heavy uses an approximation of exp~ which may lead to slight inaccuracies at high midi notes; #X connect 1 0 4 0; #X connect 2 0 3 0; #X connect 3 0 1 0; #X connect 4 0 0 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/nbx.pd0000644000000000000000000000020314435670357016624 0ustar00#N canvas 0 149 210 157 10; #X obj 24 35 inlet; #X obj 24 57 float 0; #X obj 24 79 outlet; #X connect 0 0 1 0; #X connect 1 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/noise~.pd0000644000000000000000000000232214435670357017354 0ustar00#N canvas 655 41 342 290 10; #X obj 23 10 loadbang; #X obj 23 34 random 8.38861e+06; #N canvas 0 22 450 300 @hv_obj 0; #X obj 157 180 outlet~; #X restore 128 131 pd @hv_obj __var_k~i 16807; #N canvas 0 22 450 300 @hv_obj 0; #X obj 195 79 inlet~; #X obj 198 143 outlet~; #X restore 23 200 pd @hv_obj __cast~if; #N canvas 0 22 450 300 @hv_obj 0; #X obj 191 59 inlet~; #X obj 129 56 inlet~; #X obj 161 143 outlet~; #X restore 23 244 pd @hv_obj __mul~f; #N canvas 0 22 450 300 @hv_obj 0; #X obj 163 139 outlet~; #X restore 128 221 pd @hv_obj __var_k~f 4.65661e-10; #X obj 23 268 outlet~ ~f>; #N canvas 0 22 450 300 @hv_obj 0; #X obj 157 180 outlet~; #X obj 217 124 inlet~; #X obj 162 124 inlet~; #X restore 23 154 pd @hv_obj __mul~i; #X msg 23 83 \$1 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 162 124 inlet; #X obj 157 180 outlet~; #X restore 23 106 pd @hv_obj var 0 0 0 x; #N canvas 0 22 450 300 @hv_obj 0; #X obj 170 106 inlet~; #X restore 35 177 pd @hv_obj vario x; #X obj 36 57 inlet; #X text 78 56 set state; #X connect 0 0 1 0; #X connect 1 0 8 0; #X connect 2 0 7 1; #X connect 3 0 4 0; #X connect 4 0 6 0; #X connect 5 0 4 1; #X connect 7 0 3 0; #X connect 7 0 10 0; #X connect 8 0 9 0; #X connect 9 0 7 0; #X connect 11 0 8 0; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2795517 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/notein.pd0000644000000000000000000000162614677551203017337 0ustar00#N canvas 692 314 379 296 10; #X text 18 13 data0/pitch data1/velocity channel; #X obj 140 69 unpack f f f; #X obj 23 39 loadbang; #X obj 23 67 i \$1; #X obj 203 212 spigot; #X obj 22 181 spigot; #X obj 87 181 spigot; #X obj 209 100 + 1; #X obj 140 214 spigot; #X obj 23 99 == 0; #X obj 209 147 ==; #X obj 209 181 t f f; #X obj 23 124 t f f; #X obj 22 250 outlet; #X obj 140 247 outlet; #X obj 301 250 outlet; #X obj 140 38 r __hv_notein; #X obj 301 219 max 1; #X connect 1 0 8 0; #X connect 1 0 5 0; #X connect 1 1 6 0; #X connect 1 1 4 0; #X connect 1 2 7 0; #X connect 2 0 3 0; #X connect 3 0 9 0; #X connect 3 0 10 1; #X connect 4 0 14 0; #X connect 5 0 13 0; #X connect 6 0 14 0; #X connect 7 0 10 0; #X connect 7 0 17 0; #X connect 8 0 13 0; #X connect 9 0 12 0; #X connect 10 0 11 0; #X connect 11 0 8 1; #X connect 11 1 4 1; #X connect 12 0 5 1; #X connect 12 1 6 1; #X connect 16 0 1 0; #X connect 17 0 15 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/noteout.pd0000644000000000000000000000064614435670357017545 0ustar00#N canvas 331 418 278 331 10; #X obj 59 232 pack f f f; #X obj 59 264 s __hv_noteout @hv_param; #X obj 59 46 inlet note; #X obj 87 76 inlet vel; #X obj 126 133 loadbang; #X obj 116 163 f \$1; #X obj 116 106 inlet channel; #X obj 116 185 - 1; #X obj 116 208 max; #X connect 0 0 1 0; #X connect 2 0 0 0; #X connect 3 0 0 1; #X connect 4 0 5 0; #X connect 5 0 7 0; #X connect 6 0 5 0; #X connect 7 0 8 0; #X connect 8 0 0 2; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/osc~.pd0000644000000000000000000000220414435670357017022 0ustar00#N canvas 650 23 284 370 10; #X obj 33 178 *~; #X obj 44 231 *~; #X obj 48 154 *~; #X text 74 153 x^2; #X text 57 178 x^3; #X text 68 231 x^5; #X obj 18 276 +~; #X obj 18 299 outlet~; #X text 17 320 @hv_arg \$1 frequency float 440 false; #X text 85 122 x; #X obj 18 78 abs~; #X obj 18 56 -~ 0.5; #X text 67 98 [-0.25 \, +0.25]; #X obj 18 122 *~ 6.283185307179586; #X obj 18 99 -~ 0.25; #X obj 135 9 inlet phase; #X obj 18 9 inlet -~>; #X text 44 278 -5% to adjust for taylor expansion; #X obj 44 255 *~ 0.007833333333333; #X text 16 335 a cosine oscillator; #N canvas 0 22 450 300 @hv_obj 0; #X obj 185 86 inlet; #X obj 277 90 inlet; #X obj 182 150 outlet~; #X restore 18 33 pd @hv_obj phasor \$1; #X obj 33 202 *~ -0.166666666666667; #X obj 18 254 +~; #X connect 0 0 1 0; #X connect 0 0 21 0; #X connect 1 0 18 0; #X connect 2 0 1 1; #X connect 2 0 0 1; #X connect 6 0 7 0; #X connect 10 0 14 0; #X connect 11 0 10 0; #X connect 13 0 2 0; #X connect 13 0 2 1; #X connect 13 0 0 0; #X connect 13 0 22 0; #X connect 14 0 13 0; #X connect 15 0 20 1; #X connect 16 0 20 0; #X connect 18 0 6 1; #X connect 20 0 11 0; #X connect 21 0 22 1; #X connect 22 0 6 0; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2795517 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/pgmin.pd0000644000000000000000000000162214677551203017151 0ustar00#N canvas 114 229 459 438 10; #X obj 209 337 outlet; #X obj 152 76 unpack f f; #X obj 50 334 outlet; #X obj 83 104 loadbang; #X obj 83 174 == 0; #X obj 83 128 i \$1; #X obj 50 266 spigot; #X obj 209 101 + 1; #X obj 209 236 spigot; #X obj 215 175 ==; #X obj 152 237 spigot; #X obj 215 200 t f f; #X obj 209 313 max 1; #X obj 83 197 t f f; #X obj 150 270 spigot; #X obj 152 47 r __hv_pgmin; #X text 226 78 program value and channel/port; #X obj 50 299 + 1; #X connect 1 0 10 0; #X connect 1 0 6 0; #X connect 1 1 7 0; #X connect 3 0 5 0; #X connect 4 0 13 0; #X connect 5 0 4 0; #X connect 5 0 9 1; #X connect 6 0 17 0; #X connect 7 0 9 0; #X connect 7 0 14 0; #X connect 7 0 8 0; #X connect 8 0 12 0; #X connect 9 0 11 0; #X connect 10 0 17 0; #X connect 11 0 10 1; #X connect 11 1 8 1; #X connect 12 0 0 0; #X connect 13 0 6 1; #X connect 13 1 14 1; #X connect 14 0 12 0; #X connect 15 0 1 0; #X connect 17 0 2 0; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2795517 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/pgmout.pd0000644000000000000000000000070314677551203017351 0ustar00#N canvas 611 471 232 295 10; #X obj 52 248 s __hv_pgmout @hv_param; #X obj 52 216 pack f f; #X obj 97 74 inlet channel; #X obj 97 146 f \$1; #X obj 114 106 loadbang; #X obj 52 40 inlet program; #X obj 97 168 - 1; #X obj 97 191 max; #X obj 52 168 - 1; #X obj 52 191 max; #X connect 1 0 0 0; #X connect 2 0 3 0; #X connect 3 0 6 0; #X connect 4 0 3 0; #X connect 5 0 8 0; #X connect 6 0 7 0; #X connect 7 0 1 1; #X connect 8 0 9 0; #X connect 9 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/phasor~.pd0000644000000000000000000000053714435670357017541 0ustar00#N canvas 638 45 254 136 10; #X obj 25 69 outlet~; #X obj 142 14 inlet phase; #N canvas 0 22 450 300 @hv_obj 0; #X obj 130 77 inlet; #X obj 55 136 outlet~; #X obj 55 75 inlet; #X restore 25 41 pd @hv_obj phasor \$1; #X text 23 91 @hv_arg \$1 frequency float 0 false; #X obj 25 15 inlet -~>; #X connect 1 0 2 1; #X connect 2 0 0 0; #X connect 4 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/pipe.pd0000644000000000000000000000052614435670357017002 0ustar00#N canvas 715 492 262 117 10; #X obj 14 16 inlet; #X obj 137 16 inlet; #X obj 14 62 outlet; #X text 12 87 @hv_arg \$1 delay float 0 false; #N canvas 377 209 450 300 @hv_obj 0; #X obj 152 38 inlet; #X obj 261 44 inlet; #X obj 199 177 outlet; #X restore 14 39 pd @hv_obj __delay \$1; #X connect 0 0 4 0; #X connect 1 0 4 1; #X connect 4 0 2 0; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5991824 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/poly.pd0000644000000000000000000003076114735300037017020 0ustar00#N canvas 313 155 762 544 10; #X obj 448 121 s \$0-shouldSteal; #X obj 478 208 + 1; #X obj 448 281 s \$0-currentVoiceId; #X obj 181 490 outlet pitch; #X obj 311 490 outlet velocity; #X obj 448 35 loadbang; #X obj 448 78 \$2; #X obj 45 490 outlet id; #X obj 45 457 + 1; #X obj 448 185 r \$0-voiceId++; #X obj 448 208 f 0; #X obj 448 258 mod 65535; #X obj 448 344 table \$0-pitches \$1; #X obj 448 374 table \$0-used \$1; #X obj 448 404 table \$0-ids \$1; #X obj 448 55 t b b; #X obj 564 121 s \$0-maxVoiceId; #X msg 564 98 65535; #X obj 499 236 r \$0-maxVoiceId; #X obj 45 70 route stop clear; #X obj 153 152 unpack f f; #X obj 273 208 f; #X obj 273 35 inlet velocity; #X obj 198 291 > 0; #X obj 198 311 t a a; #X obj 260 351 spigot 0; #X obj 272 229 t a a a; #X obj 153 351 spigot 0; #X obj 198 331 == 0; #X obj 153 201 t a a; #X obj 45 35 inlet pitch; #X obj 448 98 != 0; #N canvas 696 131 696 703 NoteOff 0; #X obj 159 927 outlet pitch; #X obj 247 927 outlet velocity; #X obj 58 927 outlet id; #N canvas 0 22 317 402 count 0; #X obj 31 37 inlet; #X obj 70 217 t f f; #X obj 70 277 spigot 0; #X obj 115 247 <; #X obj 70 127 t f f; #X obj 70 187 f; #X obj 100 187 + 1; #X msg 70 157 0; #X obj 97 338 outlet; #X obj 31 97 moses 1; #X obj 31 67 int; #X obj 70 307 t f f; #X connect 0 0 10 0; #X connect 1 0 2 0; #X connect 1 1 3 0; #X connect 2 0 11 0; #X connect 3 0 2 1; #X connect 4 0 7 0; #X connect 4 1 3 1; #X connect 5 0 1 0; #X connect 6 0 5 0; #X connect 7 0 5 0; #X connect 9 1 4 0; #X connect 10 0 9 0; #X connect 11 0 6 0; #X connect 11 1 8 0; #X restore 157 226 pd count; #X obj 157 206 \$1; #X obj 157 246 t f f f f; #X msg 104 554 0; #X obj 282 292 tabread \$0-used; #X obj 392 292 tabread \$0-ids; #X obj 269 596 f; #X msg 176 554 1; #X obj 70 111 t a a b b; #X obj 157 166 unpack f f; #X obj 157 186 t b f; #X obj 157 292 tabread \$0-pitches; #X obj 157 408 ==; #X obj 157 434 &&; #X obj 282 408 &&; #X obj 562 272 r \$0-maxVoiceId; #X obj 547 300 f; #X obj 392 378 <; #X obj 157 463 sel 1; #X obj 157 493 t b b b; #X obj 407 347 f; #X obj 392 317 t f f; #X obj 59 632 spigot 0; #X obj 98 708 tabwrite \$0-used; #X obj 78 828 tabwrite \$0-ids; #X obj 78 729 t b b; #X obj 93 778 r \$0-currentVoiceId; #X obj 105 749 s \$0-voiceId++; #X obj 78 798 f; #X obj 59 655 t a b b; #X msg 98 688 0; #X obj 58 897 f; #X obj 59 865 t b a b; #X obj 159 897 unpack f f; #X msg 247 897 0; #X obj 70 31 inlet pitch; #X obj 115 56 inlet velocity; #X obj 70 89 pack f f; #X obj 104 596 t a; #X connect 3 0 5 0; #X connect 4 0 3 0; #X connect 5 0 14 0; #X connect 5 1 7 0; #X connect 5 2 8 0; #X connect 5 3 9 1; #X connect 6 0 41 0; #X connect 6 0 9 0; #X connect 7 0 17 0; #X connect 8 0 24 0; #X connect 9 0 26 1; #X connect 9 0 27 1; #X connect 9 0 34 1; #X connect 10 0 41 0; #X connect 11 0 25 0; #X connect 11 1 12 0; #X connect 11 2 6 0; #X connect 11 3 19 0; #X connect 12 0 13 0; #X connect 13 0 4 0; #X connect 13 1 15 1; #X connect 14 0 15 0; #X connect 15 0 16 0; #X connect 16 0 21 0; #X connect 17 0 16 1; #X connect 18 0 19 1; #X connect 19 0 20 1; #X connect 20 0 17 1; #X connect 21 0 22 0; #X connect 22 0 9 0; #X connect 22 1 10 0; #X connect 22 2 23 0; #X connect 23 0 20 1; #X connect 24 0 20 0; #X connect 24 1 23 1; #X connect 25 0 32 0; #X connect 28 0 31 0; #X connect 28 1 30 0; #X connect 29 0 31 1; #X connect 31 0 27 0; #X connect 32 0 35 0; #X connect 32 1 28 0; #X connect 32 2 33 0; #X connect 33 0 26 0; #X connect 34 0 2 0; #X connect 35 0 34 0; #X connect 35 1 36 0; #X connect 35 2 37 0; #X connect 36 0 0 0; #X connect 37 0 1 0; #X connect 38 0 40 0; #X connect 39 0 40 1; #X connect 40 0 11 0; #X connect 41 0 25 1; #X restore 153 381 pd NoteOff; #N canvas 596 156 499 510 Stop 0; #X obj 52 45 inlet; #N canvas 0 22 317 402 count 0; #X obj 31 37 inlet; #X obj 70 217 t f f; #X obj 70 277 spigot 0; #X obj 115 247 <; #X obj 70 127 t f f; #X obj 70 187 f; #X obj 100 187 + 1; #X msg 70 157 0; #X obj 97 338 outlet; #X obj 31 97 moses 1; #X obj 31 67 int; #X obj 70 307 t f f; #X connect 0 0 10 0; #X connect 1 0 2 0; #X connect 1 1 3 0; #X connect 2 0 11 0; #X connect 3 0 2 1; #X connect 4 0 7 0; #X connect 4 1 3 1; #X connect 5 0 1 0; #X connect 6 0 5 0; #X connect 7 0 5 0; #X connect 9 1 4 0; #X connect 10 0 9 0; #X connect 11 0 6 0; #X connect 11 1 8 0; #X restore 52 132 pd count; #X obj 52 105 \$1; #X obj 67 428 tabwrite \$0-used; #X obj 52 75 t b b; #X msg 128 114 0; #X obj 128 136 s \$0-voiceId++; #X obj 97 200 tabread \$0-used; #X obj 97 222 != 0; #X obj 52 157 t f f; #X obj 52 251 spigot 0; #X obj 83 351 outlet id; #X obj 173 351 outlet pitch; #X obj 307 351 outlet velocity; #X msg 307 321 0; #X obj 173 321 tabread \$0-pitches; #X obj 52 273 t b f f f b; #X obj 67 380 t b f; #X msg 67 402 0; #X obj 52 464 s \$0-voiceId++; #X connect 0 0 4 0; #X connect 1 0 9 0; #X connect 2 0 1 0; #X connect 4 0 2 0; #X connect 4 1 5 0; #X connect 5 0 6 0; #X connect 7 0 8 0; #X connect 8 0 10 1; #X connect 9 0 10 0; #X connect 9 1 7 0; #X connect 10 0 16 0; #X connect 14 0 13 0; #X connect 15 0 12 0; #X connect 16 0 19 0; #X connect 16 1 17 0; #X connect 16 2 11 0; #X connect 16 3 15 0; #X connect 16 4 14 0; #X connect 17 0 18 0; #X connect 17 1 3 1; #X connect 18 0 3 0; #X restore 45 381 pd Stop; #N canvas 0 22 329 363 Clear 0; #X obj 52 45 inlet; #N canvas 0 22 317 402 count 0; #X obj 31 37 inlet; #X obj 70 217 t f f; #X obj 70 277 spigot 0; #X obj 115 247 <; #X obj 70 127 t f f; #X obj 70 187 f; #X obj 100 187 + 1; #X msg 70 157 0; #X obj 97 338 outlet; #X obj 31 97 moses 1; #X obj 31 67 int; #X obj 70 307 t f f; #X connect 0 0 10 0; #X connect 1 0 2 0; #X connect 1 1 3 0; #X connect 2 0 11 0; #X connect 3 0 2 1; #X connect 4 0 7 0; #X connect 4 1 3 1; #X connect 5 0 1 0; #X connect 6 0 5 0; #X connect 7 0 5 0; #X connect 9 1 4 0; #X connect 10 0 9 0; #X connect 11 0 6 0; #X connect 11 1 8 0; #X restore 52 135 pd count; #X obj 52 105 \$1; #X obj 52 301 tabwrite \$0-used; #X obj 71 275 tabwrite \$0-ids; #X msg 52 195 0; #X obj 52 75 t b b; #X msg 128 114 0; #X obj 128 136 s \$0-voiceId++; #X obj 52 225 t a a a; #X obj 52 165 t b a a a; #X obj 91 250 tabwrite \$0-pitches; #X connect 0 0 6 0; #X connect 1 0 10 0; #X connect 2 0 1 0; #X connect 5 0 9 0; #X connect 6 0 2 0; #X connect 6 1 7 0; #X connect 7 0 8 0; #X connect 9 0 3 0; #X connect 9 1 4 0; #X connect 9 2 11 0; #X connect 10 0 5 0; #X connect 10 1 3 1; #X connect 10 2 4 1; #X connect 10 3 11 1; #X restore 91 152 pd Clear; #N canvas 549 249 1276 703 NoteOn 0; #N canvas 0 22 317 402 count 0; #X obj 31 37 inlet; #X obj 70 217 t f f; #X obj 70 277 spigot 0; #X obj 115 247 <; #X obj 70 127 t f f; #X obj 70 187 f; #X obj 100 187 + 1; #X msg 70 157 0; #X obj 97 338 outlet; #X obj 31 97 moses 1; #X obj 31 67 int; #X obj 70 307 t f f; #X connect 0 0 10 0; #X connect 1 0 2 0; #X connect 1 1 3 0; #X connect 2 0 11 0; #X connect 3 0 2 1; #X connect 4 0 7 0; #X connect 4 1 3 1; #X connect 5 0 1 0; #X connect 6 0 5 0; #X connect 7 0 5 0; #X connect 9 1 4 0; #X connect 10 0 9 0; #X connect 11 0 6 0; #X connect 11 1 8 0; #X restore 900 369 pd count; #X obj 897 336 \$1; #X obj 1050 624 &&; #X obj 1115 590 <; #X obj 1088 683 sel 1; #X obj 1081 768 f; #X obj 900 391 t f f f f; #X obj 1080 821 s \$0-indexOn; #X obj 989 557 t f f; #X obj 973 701 spigot 0; #X obj 982 628 &&; #X obj 980 587 == 0; #X obj 1050 646 t f f; #X obj 1047 680 == 0; #X obj 915 788 f; #X obj 921 843 s \$0-indexOff; #X obj 777 229 s \$0-indexOn; #X obj 730 251 s \$0-indexOff; #X obj 410 212 t a b b b; #X obj 973 723 sel 1; #X obj 1156 592 <; #X obj 1184 557 f; #X obj 1118 494 t f f f; #X obj 1226 557 f; #X obj 1184 499 t f f; #X obj 966 804 s \$0-isFirstOff; #X obj 973 745 t b b b; #X msg 967 777 1; #X msg 1167 739 1; #X obj 1167 774 s \$0-isFirstOn; #X obj 1088 705 t b b b; #X msg 733 189 0; #X obj 792 193 s \$0-isFirstOn; #X obj 821 169 s \$0-isFirstOff; #X obj 385 485 r \$0-isFirstOff; #X obj 288 567 spigot 0; #X obj 385 507 t f f; #X obj 498 555 r \$0-isFirstOn; #X obj 404 681 spigot 0; #X obj 460 637 &&; #X obj 412 536 == 0; #X obj 407 398 pack f f; #X obj 407 420 t a a; #X obj 291 966 outlet pitch; #X obj 377 966 outlet velocity; #X obj 138 592 r \$0-indexOff; #X obj 278 785 f; #X obj 305 794 unpack f f; #X obj 489 724 r \$0-indexOn; #X obj 428 776 f; #X obj 489 746 t a a a a; #X obj 138 614 t a a a a; #X msg 130 832 1; #X msg 472 902 1; #X obj 505 634 r \$0-shouldSteal; #X obj 460 659 spigot 0; #X obj 221 974 outlet id; #X obj 473 815 f; #X obj 468 783 t b b b; #X msg 393 939 0; #X obj 280 596 t b b b a; #X obj 258 630 t b b; #X obj 267 677 r \$0-currentVoiceId; #X obj 284 652 s \$0-voiceId++; #X obj 255 703 f; #X obj 999 430 tabread \$0-used; #X obj 1118 432 tabread \$0-ids; #X obj 427 874 tabwrite \$0-pitches; #X obj 473 839 tabread \$0-pitches; #X obj 122 799 tabwrite \$0-pitches; #X obj 124 859 tabwrite \$0-used; #X obj 196 889 tabwrite \$0-ids; #X obj 621 923 tabwrite \$0-ids; #X obj 632 752 t b b; #X obj 641 799 r \$0-currentVoiceId; #X obj 658 774 s \$0-voiceId++; #X obj 629 825 f; #X obj 404 703 t b b b a b; #X obj 498 577 t b f; #X obj 470 927 tabwrite \$0-used; #X obj 1015 251 r \$0-maxVoiceId; #X obj 1021 308 f; #X obj 389 815 unpack f f; #X obj 389 837 t a a; #X obj 304 822 t a a; #X obj 421 51 inlet pitch; #X obj 665 41 inlet vel; #X obj 457 610 f; #X connect 0 0 6 0; #X connect 1 0 0 0; #X connect 2 0 12 0; #X connect 3 0 10 1; #X connect 4 0 30 0; #X connect 5 0 7 0; #X connect 6 1 65 0; #X connect 6 2 66 0; #X connect 6 3 5 1; #X connect 6 3 14 1; #X connect 8 0 11 0; #X connect 8 1 2 0; #X connect 9 0 19 0; #X connect 10 0 9 0; #X connect 11 0 10 0; #X connect 12 0 13 0; #X connect 12 1 4 0; #X connect 13 0 9 1; #X connect 14 0 15 0; #X connect 18 0 41 0; #X connect 18 1 1 0; #X connect 18 2 81 0; #X connect 18 3 31 0; #X connect 19 0 26 0; #X connect 20 0 2 1; #X connect 21 0 3 1; #X connect 22 0 3 0; #X connect 22 1 20 0; #X connect 22 2 21 1; #X connect 22 2 23 1; #X connect 23 0 20 1; #X connect 24 0 21 0; #X connect 24 1 23 0; #X connect 26 0 14 0; #X connect 26 1 27 0; #X connect 26 2 21 0; #X connect 27 0 25 0; #X connect 28 0 29 0; #X connect 30 0 5 0; #X connect 30 1 28 0; #X connect 30 2 23 0; #X connect 31 0 17 0; #X connect 31 0 16 0; #X connect 31 0 32 0; #X connect 31 0 33 0; #X connect 34 0 36 0; #X connect 35 0 60 0; #X connect 36 0 35 1; #X connect 36 1 40 0; #X connect 37 0 78 0; #X connect 38 0 77 0; #X connect 39 0 55 0; #X connect 40 0 87 0; #X connect 41 0 42 0; #X connect 42 0 35 0; #X connect 42 1 38 0; #X connect 45 0 51 0; #X connect 46 0 56 0; #X connect 47 0 84 0; #X connect 47 1 44 0; #X connect 48 0 50 0; #X connect 49 0 56 0; #X connect 50 0 49 1; #X connect 50 0 57 1; #X connect 50 1 72 1; #X connect 50 2 79 1; #X connect 50 3 67 1; #X connect 51 0 70 1; #X connect 51 1 69 1; #X connect 51 2 71 1; #X connect 51 3 46 1; #X connect 52 0 70 0; #X connect 53 0 79 0; #X connect 54 0 55 1; #X connect 55 0 38 1; #X connect 57 0 68 0; #X connect 58 0 49 0; #X connect 58 1 57 0; #X connect 58 2 59 0; #X connect 59 0 44 0; #X connect 60 0 61 0; #X connect 60 1 52 0; #X connect 60 2 46 0; #X connect 60 3 47 0; #X connect 61 0 64 0; #X connect 61 1 63 0; #X connect 62 0 64 1; #X connect 64 0 71 0; #X connect 65 0 8 0; #X connect 66 0 22 0; #X connect 68 0 43 0; #X connect 73 0 76 0; #X connect 73 1 75 0; #X connect 74 0 76 1; #X connect 76 0 72 0; #X connect 77 0 73 0; #X connect 77 1 53 0; #X connect 77 2 49 0; #X connect 77 3 82 0; #X connect 77 4 58 0; #X connect 78 0 87 0; #X connect 78 1 39 1; #X connect 80 0 81 1; #X connect 81 0 24 0; #X connect 82 0 83 0; #X connect 82 1 44 0; #X connect 83 0 43 0; #X connect 83 1 67 0; #X connect 84 0 43 0; #X connect 84 1 69 0; #X connect 85 0 18 0; #X connect 86 0 41 1; #X connect 87 0 39 0; #X restore 260 381 pd NoteOn; #X text 447 466 @hv_arg \$1 NumVoices int 1 false; #X text 447 486 @hv_arg \$2 VoiceStealing int 0 false; #X connect 1 0 10 1; #X connect 5 0 15 0; #X connect 6 0 31 0; #X connect 8 0 7 0; #X connect 9 0 10 0; #X connect 10 0 11 0; #X connect 11 0 1 0; #X connect 11 0 2 0; #X connect 15 0 6 0; #X connect 15 1 17 0; #X connect 17 0 16 0; #X connect 18 0 11 1; #X connect 19 0 33 0; #X connect 19 1 34 0; #X connect 19 2 20 0; #X connect 20 0 29 0; #X connect 20 1 21 0; #X connect 21 0 26 0; #X connect 22 0 21 0; #X connect 23 0 24 0; #X connect 24 0 28 0; #X connect 24 1 25 1; #X connect 25 0 35 0; #X connect 26 0 23 0; #X connect 26 1 32 1; #X connect 26 2 35 1; #X connect 27 0 32 0; #X connect 28 0 27 1; #X connect 29 0 27 0; #X connect 29 1 25 0; #X connect 30 0 19 0; #X connect 31 0 0 0; #X connect 32 0 8 0; #X connect 32 1 3 0; #X connect 32 2 4 0; #X connect 33 0 8 0; #X connect 33 1 3 0; #X connect 33 2 4 0; #X connect 35 0 8 0; #X connect 35 1 3 0; #X connect 35 2 4 0; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2795517 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/polytouchin.pd0000644000000000000000000000162714677551203020421 0ustar00#N canvas 692 314 379 296 10; #X obj 140 69 unpack f f f; #X obj 23 39 loadbang; #X obj 23 67 i \$1; #X obj 203 212 spigot; #X obj 22 181 spigot; #X obj 87 181 spigot; #X obj 209 100 + 1; #X obj 140 214 spigot; #X obj 23 99 == 0; #X obj 209 147 ==; #X obj 209 181 t f f; #X obj 23 124 t f f; #X obj 22 250 outlet; #X obj 140 247 outlet; #X obj 301 250 outlet; #X obj 301 219 max 1; #X obj 140 38 r __hv_polytouchin; #X text 18 13 data0/note data1/pressure channel; #X connect 0 0 7 0; #X connect 0 0 4 0; #X connect 0 1 5 0; #X connect 0 1 3 0; #X connect 0 2 6 0; #X connect 1 0 2 0; #X connect 2 0 8 0; #X connect 2 0 9 1; #X connect 3 0 13 0; #X connect 4 0 12 0; #X connect 5 0 13 0; #X connect 6 0 9 0; #X connect 6 0 15 0; #X connect 7 0 12 0; #X connect 8 0 11 0; #X connect 9 0 10 0; #X connect 10 0 7 1; #X connect 10 1 3 1; #X connect 11 0 4 1; #X connect 11 1 5 1; #X connect 15 0 14 0; #X connect 16 0 0 0; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2795517 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/polytouchout.pd0000644000000000000000000000065614677551203020623 0ustar00#N canvas 1225 622 278 331 10; #X obj 59 232 pack f f f; #X obj 126 133 loadbang; #X obj 116 163 f \$1; #X obj 116 106 inlet channel; #X obj 116 185 - 1; #X obj 116 208 max; #X obj 59 264 s __hv_polytouchout @hv_param; #X obj 59 46 inlet touch; #X obj 87 76 inlet note; #X connect 0 0 6 0; #X connect 1 0 2 0; #X connect 2 0 4 0; #X connect 3 0 2 0; #X connect 4 0 5 0; #X connect 5 0 0 2; #X connect 7 0 0 0; #X connect 8 0 0 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/powtodb.pd0000644000000000000000000000125014435670357017516 0ustar00#N canvas 243 267 355 324 10; #X obj 26 21 inlet; #X obj 26 273 outlet; #X obj 26 51 t f f; #X msg 26 225 0; #X obj 113 195 + 100; #X obj 113 225 max 0; #X obj 113 79 > 0; #X obj 113 165 * 10; #N canvas 0 22 260 165 @hv_obj 0; #X obj 60 35 inlet; #X obj 120 35 inlet; #X obj 60 95 outlet; #X obj 120 95 outlet; #X restore 26 105 pd @hv_obj __if; #N canvas 0 22 260 165 @hv_obj 0; #X obj 60 35 inlet; #X obj 60 95 outlet; #X restore 113 135 pd @hv_obj __log10; #X connect 0 0 2 0; #X connect 2 0 8 0; #X connect 2 1 6 0; #X connect 3 0 1 0; #X connect 4 0 5 0; #X connect 5 0 1 0; #X connect 6 0 8 1; #X connect 7 0 4 0; #X connect 8 0 3 0; #X connect 8 1 9 0; #X connect 9 0 7 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/powtodb~.pd0000644000000000000000000000063414435670357017721 0ustar00#N canvas 712 409 141 174 10; #X obj 14 147 outlet~; #X obj 14 11 inlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 133 40 inlet~; #X obj 134 119 outlet~; #X restore 14 57 pd @hv_obj __log2~f; #X obj 14 34 max~ 0; #X obj 14 102 +~ 100; #X obj 14 79 *~ 3.010299956639812; #X obj 14 125 max~ 0; #X connect 1 0 3 0; #X connect 2 0 5 0; #X connect 3 0 2 0; #X connect 4 0 6 0; #X connect 5 0 4 0; #X connect 6 0 0 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/print.pd0000644000000000000000000000032714435670357017200 0ustar00#N canvas 801 225 258 123 10; #N canvas 0 22 450 300 @hv_obj 0; #X obj 46 72 inlet; #X restore 21 51 pd @hv_obj print \$1; #X obj 21 21 inlet; #X text 19 83 @hv_arg \$1 label string print false; #X connect 1 0 0 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/q8_rsqrt~.pd0000644000000000000000000000034314435670357020023 0ustar00#N canvas 0 22 191 83 10; #X obj 10 4 inlet~; #X obj 10 52 outlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 163 70 inlet~; #X obj 156 144 outlet~; #X restore 10 27 pd @hv_obj __rsqrt~f; #X connect 0 0 2 0; #X connect 2 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/q8_sqrt~.pd0000644000000000000000000000034214435670357017640 0ustar00#N canvas 0 22 191 83 10; #X obj 10 4 inlet~; #X obj 10 52 outlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 163 70 inlet~; #X obj 156 144 outlet~; #X restore 10 27 pd @hv_obj __sqrt~f; #X connect 0 0 2 0; #X connect 2 0 1 0; ././@PaxHeader0000000000000000000000000000003200000000000010210 xustar0026 mtime=1692674740.67764 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/random.pd0000644000000000000000000000150314471025265017311 0ustar00#N canvas 585 151 215 219 10; #X obj 13 10 inlet; #X obj 34 105 inlet; #X obj 13 172 outlet; #X obj 13 128 * \$1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 223 53 inlet; #X obj 241 144 outlet; #X restore 13 150 pd @hv_obj floor; #X text 12 192 @hv_arg \$1 range float 2 false; #N canvas 636 94 450 300 @hv_obj 0; #X obj 37 37 inlet; #X obj 190 49 inlet; #X obj 155 131 outlet; #X restore 13 83 pd @hv_obj random; #N canvas 0 22 450 300 @hv_obj 0; #X obj 178 47 inlet; #X obj 165 128 outlet; #X restore 13 57 pd @hv_obj slice 1 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 169 24 inlet; #X obj 221 83 outlet; #X obj 159 83 outlet; #X restore 13 34 pd @hv_obj __switchcase seed; #X connect 0 0 8 0; #X connect 1 0 3 1; #X connect 3 0 4 0; #X connect 4 0 2 0; #X connect 6 0 3 0; #X connect 7 0 6 1; #X connect 8 0 7 0; #X connect 8 1 6 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/rmstodb.pd0000644000000000000000000000125014435670357017512 0ustar00#N canvas 474 236 355 324 10; #X obj 26 21 inlet; #X obj 26 273 outlet; #X obj 26 51 t f f; #X msg 26 225 0; #X obj 113 165 * 20; #X obj 113 195 + 100; #X obj 113 225 max 0; #X obj 113 79 > 0; #N canvas 0 22 260 165 @hv_obj 0; #X obj 60 35 inlet; #X obj 120 35 inlet; #X obj 60 95 outlet; #X obj 120 95 outlet; #X restore 26 105 pd @hv_obj __if; #N canvas 0 22 260 165 @hv_obj 0; #X obj 60 35 inlet; #X obj 60 95 outlet; #X restore 113 135 pd @hv_obj __log10; #X connect 0 0 2 0; #X connect 2 0 8 0; #X connect 2 1 7 0; #X connect 3 0 1 0; #X connect 4 0 5 0; #X connect 5 0 6 0; #X connect 6 0 1 0; #X connect 7 0 8 1; #X connect 8 0 3 0; #X connect 8 1 9 0; #X connect 9 0 4 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/rmstodb~.pd0000644000000000000000000000063414435670357017715 0ustar00#N canvas 569 274 140 178 10; #X obj 14 148 outlet~; #X obj 14 11 inlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 133 40 inlet~; #X obj 134 119 outlet~; #X restore 14 57 pd @hv_obj __log2~f; #X obj 14 79 *~ 6.020599913279624; #X obj 14 34 max~ 0; #X obj 14 102 +~ 100; #X obj 14 125 max~ 0; #X connect 1 0 4 0; #X connect 2 0 3 0; #X connect 3 0 5 0; #X connect 4 0 2 0; #X connect 5 0 6 0; #X connect 6 0 0 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/rpole~.pd0000644000000000000000000000052114435670357017357 0ustar00#N canvas 796 340 189 114 10; #X obj 130 16 inlet~; #X obj 13 16 inlet~; #X obj 13 84 outlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 204 68 inlet~; #X obj 144 68 inlet~; #X obj 160 129 outlet~; #X restore 13 61 pd @hv_obj __rpole~f; #X obj 130 38 *~ -1; #X connect 0 0 4 0; #X connect 1 0 3 0; #X connect 3 0 2 0; #X connect 4 0 3 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/rsqrt~.pd0000644000000000000000000000161314435670357017414 0ustar00#N canvas 0 23 281 147 10; #X obj 19 10 inlet~; #X obj 19 105 outlet~; #N canvas 467 216 450 300 @hv_obj 0; #X obj 217 60 inlet~; #X obj 120 60 inlet~; #X obj 170 183 outlet~; #X connect 1 0 2 0; #X restore 19 81 pd @hv_obj __and~f; #X obj 118 10 sig~ 0; #N canvas 715 101 191 233 @hv_obj 0; #X obj 49 83 -~; #X obj 50 109 clip~ -1e-37 0; #X obj 49 32 inlet~; #X obj 93 33 inlet~; #X obj 50 174 outlet~; #X obj 50 151 *~ 1e+37; #X obj 49 58 min~; #X obj 50 130 +~ 1e-37; #X connect 0 0 1 0; #X connect 1 0 7 0; #X connect 2 0 6 0; #X connect 2 0 0 1; #X connect 3 0 6 1; #X connect 5 0 4 0; #X connect 6 0 0 0; #X connect 7 0 5 0; #X restore 19 33 pd @hv_obj __gt~f; #N canvas 0 23 450 300 @hv_obj 0; #X obj 163 70 inlet~; #X obj 156 144 outlet~; #X restore 124 60 pd @hv_obj __rsqrt~f; #X connect 0 0 4 0; #X connect 0 0 5 0; #X connect 2 0 1 0; #X connect 3 0 4 1; #X connect 4 0 2 0; #X connect 5 0 2 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/rzero_rev~.pd0000644000000000000000000000055714435670357020264 0ustar00#N canvas 932 23 172 215 10; #X obj 71 18 inlet~; #X obj 16 18 inlet~; #X obj 16 163 outlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 175 149 outlet~; #X obj 173 75 inlet~; #X restore 16 96 pd @hv_obj __del1~f; #X obj 31 64 *~; #X obj 16 141 -~; #X connect 0 0 4 1; #X connect 1 0 3 0; #X connect 1 0 4 0; #X connect 3 0 5 0; #X connect 4 0 5 1; #X connect 5 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/rzero~.pd0000644000000000000000000000064114435670357017402 0ustar00#N canvas 397 215 281 159 10; #X obj 46 65 inlet~; #X obj 16 18 inlet~; #X obj 16 133 outlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 175 149 outlet~; #X obj 173 75 inlet~; #X restore 31 43 pd @hv_obj __del1~f; #X obj 31 88 *~; #X obj 16 111 -~; #X text 65 18 Implements Pd's H(z) = 1 - a*z^-1; #X connect 0 0 4 1; #X connect 1 0 3 0; #X connect 1 0 5 0; #X connect 3 0 4 0; #X connect 4 0 5 1; #X connect 5 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/samphold~.pd0000644000000000000000000000114714435670357020052 0ustar00#N canvas 714 389 383 150 10; #X obj 12 114 outlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 55 136 outlet~; #X obj 54 74 inlet~; #X obj 130 77 inlet~; #X restore 12 86 pd @hv_obj __samphold~f; #X obj 12 12 inlet~; #X obj 147 12 inlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 175 149 outlet~; #X obj 173 75 inlet~; #X restore 246 38 pd @hv_obj __del1~f; #N canvas 0 22 450 300 @hv_obj 0; #X obj 216 44 inlet~; #X obj 139 45 inlet~; #X obj 172 91 outlet~; #X restore 147 61 pd @hv_obj __lt~f; #X connect 1 0 0 0; #X connect 2 0 1 0; #X connect 3 0 4 0; #X connect 3 0 5 0; #X connect 4 0 5 1; #X connect 5 0 1 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/samplerate~.pd0000644000000000000000000000041514435670357020375 0ustar00#N canvas 698 370 281 258 10; #X obj 19 11 inlet; #X obj 19 84 outlet; #X msg 19 35 samplerate; #N canvas 0 22 450 300 @hv_obj 0; #X obj 119 57 inlet; #X obj 119 97 outlet; #X restore 19 59 pd @hv_obj system; #X connect 0 0 2 0; #X connect 2 0 3 0; #X connect 3 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/sig~.pd0000644000000000000000000000041314435670357017020 0ustar00#N canvas 329 553 183 106 10; #X obj 9 11 inlet; #X obj 9 57 outlet~; #X text 7 78 @hv_arg \$1 k float 0 false; #N canvas 0 22 450 300 @hv_obj 0; #X obj 170 59 inlet; #X obj 180 116 outlet~; #X restore 9 34 pd @hv_obj var \$1; #X connect 0 0 3 0; #X connect 3 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/sin.pd0000644000000000000000000000033514435670357016634 0ustar00#N canvas 439 480 151 128 10; #X obj 13 20 inlet; #X obj 13 80 outlet; #N canvas 0 22 183 125 @hv_obj 0; #X obj 19 24 inlet; #X obj 19 66 outlet; #X restore 13 50 pd @hv_obj __sin; #X connect 0 0 2 0; #X connect 2 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/snapshot~.pd0000644000000000000000000000063314435670357020101 0ustar00#N canvas 450 250 412 101 10; #X obj 15 61 outlet; #N canvas 0 22 450 300 @hv_obj 0; #X obj 186 56 inlet~; #X obj 194 120 outlet; #X obj 260 62 inlet; #X restore 15 36 pd @hv_obj __sample~f; #X text 65 59 NOTE(mhroth): there is supposed to be a control; #X text 64 72 connection from the inlet to the right __sample~f inlet ; #X obj 15 11 inlet~ -~>; #X connect 1 0 0 0; #X connect 4 0 1 0; #X connect 4 0 1 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/spigot.pd0000644000000000000000000000054714435670357017355 0ustar00#N canvas 623 160 225 146 10; #X obj 10 8 inlet; #X obj 103 44 inlet; #X obj 103 92 outlet; #X text 8 118 @hv_arg \$1 is_true float 0 false; #N canvas 0 22 450 300 @hv_obj 0; #X obj 148 66 inlet; #X obj 222 64 inlet; #X obj 140 131 outlet; #X obj 233 141 outlet; #X restore 10 68 pd @hv_obj if \$1; #X connect 0 0 4 0; #X connect 1 0 4 1; #X connect 4 1 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/sqrt.pd0000644000000000000000000000033614435670357017035 0ustar00#N canvas 399 260 218 85 10; #X obj 16 9 inlet; #X obj 16 59 outlet; #N canvas 0 22 450 300 @hv_obj 0; #X obj 172 24 inlet; #X obj 172 78 outlet; #X restore 16 34 pd @hv_obj __sqrt; #X connect 0 0 2 0; #X connect 2 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/sqrt~.pd0000644000000000000000000000161514435670357017234 0ustar00#N canvas 170 337 302 168 10; #N canvas 0 23 450 300 @hv_obj 0; #X obj 163 70 inlet~; #X obj 156 144 outlet~; #X restore 135 69 pd @hv_obj __sqrt~f; #X obj 30 19 inlet~; #X obj 30 114 outlet~; #N canvas 467 216 450 300 @hv_obj 0; #X obj 217 60 inlet~; #X obj 120 60 inlet~; #X obj 170 183 outlet~; #X connect 1 0 2 0; #X restore 30 90 pd @hv_obj __and~f; #X obj 129 19 sig~ 0; #N canvas 715 101 191 233 @hv_obj 0; #X obj 49 83 -~; #X obj 50 109 clip~ -1e-37 0; #X obj 49 32 inlet~; #X obj 93 33 inlet~; #X obj 50 174 outlet~; #X obj 50 151 *~ 1e+37; #X obj 49 58 min~; #X obj 50 130 +~ 1e-37; #X connect 0 0 1 0; #X connect 1 0 7 0; #X connect 2 0 6 0; #X connect 2 0 0 1; #X connect 3 0 6 1; #X connect 5 0 4 0; #X connect 6 0 0 0; #X connect 7 0 5 0; #X restore 30 42 pd @hv_obj __gt~f; #X connect 0 0 3 1; #X connect 1 0 5 0; #X connect 1 0 0 0; #X connect 3 0 2 0; #X connect 4 0 5 1; #X connect 5 0 3 0; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5991824 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/stripnote.pd0000644000000000000000000000173314735300037020061 0ustar00#N canvas 648 404 450 300 12; #X obj 47 10 inlet; #X obj 47 503 outlet; #X obj 47 335 unpack f f; #X obj 96 503 outlet; #X obj 47 460 spigot; #X obj 107 408 != 0; #X obj 96 460 spigot; #X obj 248 10 inlet; #X obj 216 289 spigot; #X obj 96 365 t f f; #X obj 96 87 unpack f f; #X obj 47 41 t a a; #X obj 111 199 f; #X msg 96 159 0; #X msg 144 159 1; #X obj 47 289 spigot; #X obj 216 199 pack f f; #X obj 96 117 t b f b; #X obj 241 258 == 0; #X connect 0 0 11 0; #X connect 2 0 4 0; #X connect 2 1 9 0; #X connect 4 0 1 0; #X connect 5 0 4 1; #X connect 5 0 6 1; #X connect 6 0 3 0; #X connect 6 0 16 1; #X connect 7 0 16 1; #X connect 8 0 2 0; #X connect 9 0 6 0; #X connect 9 1 5 0; #X connect 10 0 17 0; #X connect 10 1 14 0; #X connect 11 0 15 0; #X connect 11 1 10 0; #X connect 12 0 15 1; #X connect 12 0 18 0; #X connect 13 0 12 1; #X connect 14 0 12 1; #X connect 15 0 2 0; #X connect 16 0 8 0; #X connect 17 0 13 0; #X connect 17 1 16 0; #X connect 17 2 12 0; #X connect 18 0 8 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/swap.pd0000644000000000000000000000111114435670357017006 0ustar00#N canvas 566 310 291 266 10; #X obj 28 26 inlet; #X obj 107 26 inlet; #X obj 28 196 outlet; #X obj 220 189 outlet; #X obj 220 149 f; #X obj 28 106 t b b; #X obj 193 109 t b f; #X obj 28 156 f \$1; #N canvas 0 22 201 165 @hv_obj 0; #X obj 34 25 inlet; #X obj 34 97 outlet; #X obj 86 93 outlet; #X restore 28 66 pd @hv_obj __switchcase bang; #X text 27 235 @hv_arg \$1 k float 0 false; #X connect 0 0 8 0; #X connect 1 0 7 1; #X connect 4 0 3 0; #X connect 5 0 7 0; #X connect 5 1 4 0; #X connect 6 0 7 0; #X connect 6 1 4 0; #X connect 7 0 2 0; #X connect 8 0 5 0; #X connect 8 1 6 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/symbol.pd0000644000000000000000000000051414435670357017347 0ustar00#N canvas 779 41 226 111 10; #X obj 13 9 inlet; #X obj 13 53 outlet; #N canvas 0 22 450 300 @hv_obj 0; #X obj 173 49 inlet; #X obj 172 144 outlet; #X obj 259 42 inlet; #X restore 13 31 pd @hv_obj __var \$1; #X obj 124 9 inlet; #X text 13 74 @hv_arg \$1 k string "" false; #X connect 0 0 2 0; #X connect 2 0 1 0; #X connect 3 0 2 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/symbolatom.pd0000644000000000000000000000026314435670357020231 0ustar00#N canvas 172 200 211 99 10; #X obj 16 9 inlet; #X obj 16 55 outlet; #X obj 16 32 symbol \$1; #X text 14 74 @hv_arg \$1 k string "" false; #X connect 0 0 2 0; #X connect 2 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.771207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/tabosc4~.pd0000644000000000000000000000447114435670357017605 0ustar00#N canvas 117 51 500 497 10; #X obj 9 196 *~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 146 77 inlet; #X obj 147 120 outlet; #X restore 24 152 pd @hv_obj system; #X msg 24 130 table \$1 size; #N canvas 0 22 450 300 @hv_obj 0; #X obj 150 61 inlet; #X obj 147 118 outlet; #X restore 24 108 pd @hv_obj __var \$1; #X obj 9 431 outlet~; #X obj 24 359 -~; #X obj 52 359 -~; #X obj 24 383 *~; #X obj 9 406 +~; #X text 78 360 linear interpolation; #N canvas 0 22 450 300 @hv_obj 0; #X obj 160 52 inlet~; #X obj 173 97 outlet~; #X restore 9 233 pd @hv_obj __floor~f; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X restore 9 259 pd @hv_obj __cast~fi; #N canvas 0 23 450 300 @hv_obj 0; #X obj 232 43 inlet~; #X obj 169 185 outlet~; #X obj 165 46 inlet~; #X restore 180 288 pd @hv_obj __add~i; #N canvas 0 22 450 300 @hv_obj 0; #X obj 173 75 inlet; #X obj 175 149 outlet~; #X restore 285 266 pd @hv_obj __var_k~i 1; #X text 6 455 @hv_arg \$1 table string "" true; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X obj 280 42 inlet; #X restore 180 310 pd @hv_obj __tabread~if \$1; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X obj 249 48 inlet; #X restore 9 310 pd @hv_obj __tabread~if \$1; #X obj 24 174 - 2; #N canvas 0 22 450 300 @hv_obj 0; #X obj 169 24 inlet; #X obj 221 83 outlet; #X obj 159 83 outlet; #X restore 162 29 pd @hv_obj __switchcase set; #N canvas 0 22 450 300 @hv_obj 0; #X obj 178 47 inlet; #X obj 165 128 outlet; #X restore 162 52 pd @hv_obj slice 1 1; #X obj 108 39 inlet; #X obj 24 85 loadbang -1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 170 45 inlet; #X obj 127 48 inlet; #X obj 138 82 outlet~; #X restore 9 62 pd @hv_obj phasor; #X obj 9 3 inlet -~>; #X connect 0 0 10 0; #X connect 0 0 6 0; #X connect 1 0 17 0; #X connect 2 0 1 0; #X connect 3 0 2 0; #X connect 5 0 7 0; #X connect 6 0 7 1; #X connect 7 0 8 1; #X connect 8 0 4 0; #X connect 10 0 6 1; #X connect 10 0 11 0; #X connect 11 0 16 0; #X connect 11 0 12 0; #X connect 12 0 15 0; #X connect 13 0 12 1; #X connect 15 0 5 0; #X connect 16 0 8 0; #X connect 16 0 5 1; #X connect 17 0 0 1; #X connect 18 0 19 0; #X connect 19 0 3 0; #X connect 19 0 16 1; #X connect 19 0 15 1; #X connect 20 0 22 1; #X connect 21 0 3 0; #X connect 22 0 0 0; #X connect 23 0 18 0; #X connect 23 0 22 0; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735753758.5991824 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/tabplay~.pd0000644000000000000000000000337414735300037017667 0ustar00#N canvas 303 459 461 431 10; #X obj 41 351 outlet~; #X text 38 375 @hv_arg \$1 table string "" true; #N canvas 0 22 450 300 @hv_obj 0; #X obj 146 77 inlet; #X obj 147 120 outlet; #X restore 112 150 pd @hv_obj system; #X msg 112 128 table \$1 size; #N canvas 0 22 450 300 @hv_obj 0; #X obj 178 47 inlet; #X obj 165 128 outlet; #X restore 43 55 pd @hv_obj slice 1 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 150 61 inlet; #X obj 147 118 outlet; #X restore 112 106 pd @hv_obj __var \$1; #X obj 112 174 - 1; #X obj 112 80 loadbang -1; #N canvas 0 23 450 300 @hv_obj 1; #X obj 169 185 outlet~; #X obj 249 48 inlet; #X obj 165 46 inlet; #X obj 337 48 inlet; #X obj 306 185 outlet; #X obj 374 185 outlet; #X restore 41 327 pd @hv_obj __tabread_stoppable~f \$1; #X obj 42 7 inlet -->; #X obj 41 270 max 0; #X obj 41 297 min 0; #X msg 253 131 \$1; #X obj 248 358 outlet; #N canvas 0 22 450 300 @hv_obj 0; #X obj 169 24 inlet; #X obj 273 82 outlet; #X obj 159 83 outlet; #X obj 333 82 outlet; #X obj 212 82 outlet; #X restore 42 34 pd @hv_obj __switchcase set bang stop; #X obj 41 221 loadbang 0; #N canvas 1361 151 307 222 @hv_obj 0; #X obj 37 37 inlet; #X obj 40 90 outlet; #X restore 41 244 pd @hv_obj __var \$1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 178 47 inlet; #X obj 165 128 outlet; #X restore 287 132 pd @hv_obj slice 1 2; #X connect 2 0 6 0; #X connect 3 0 2 0; #X connect 4 0 8 1; #X connect 4 0 5 0; #X connect 5 0 3 0; #X connect 6 0 11 1; #X connect 7 0 5 0; #X connect 8 0 0 0; #X connect 8 2 13 0; #X connect 9 0 14 0; #X connect 10 0 11 0; #X connect 11 0 8 0; #X connect 12 0 16 0; #X connect 14 0 4 0; #X connect 14 1 16 0; #X connect 14 1 8 0; #X connect 14 2 8 0; #X connect 14 3 12 0; #X connect 14 3 17 0; #X connect 15 0 16 0; #X connect 16 0 10 0; #X connect 17 0 8 2; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/tabread.pd0000644000000000000000000000143414435670357017446 0ustar00#N canvas 451 572 294 338 10; #X obj 13 10 inlet -->; #X obj 64 272 outlet -->; #N canvas 0 22 450 300 @hv_obj 0; #X obj 169 52 inlet; #X obj 244 58 inlet; #X obj 189 127 outlet; #X restore 64 242 pd @hv_obj __tabread \$1; #X obj 13 32 route set; #X text 63 293 @hv_arg \$1 table string "" true; #N canvas 0 22 450 300 @hv_obj 0; #X obj 146 77 inlet; #X obj 147 120 outlet; #X restore 105 152 pd @hv_obj system; #X obj 64 92 max 0; #X obj 64 62 t f b; #X obj 105 92 symbol \$1; #X obj 64 212 min 0; #X msg 105 122 table \$1 length; #X obj 105 182 - 1; #X connect 0 0 3 0; #X connect 2 0 1 0; #X connect 3 0 2 1; #X connect 3 1 7 0; #X connect 5 0 11 0; #X connect 6 0 9 0; #X connect 7 0 6 0; #X connect 7 1 8 0; #X connect 8 0 10 0; #X connect 9 0 2 0; #X connect 10 0 5 0; #X connect 11 0 9 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/tabread4~.pd0000644000000000000000000000467614435670357017743 0ustar00#N canvas 75 23 584 478 10; #X obj 10 424 outlet~; #X obj 25 352 -~; #X obj 53 352 -~; #X obj 25 376 *~; #X obj 10 399 +~; #X text 79 353 linear interpolation; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X restore 10 252 pd @hv_obj __cast~fi; #N canvas 0 23 450 300 @hv_obj 0; #X obj 232 43 inlet~; #X obj 169 185 outlet~; #X obj 165 46 inlet~; #X restore 181 281 pd @hv_obj __add~i; #N canvas 0 22 450 300 @hv_obj 0; #X obj 173 75 inlet; #X obj 175 149 outlet~; #X restore 286 259 pd @hv_obj __var_k~i 1; #X text 7 448 @hv_arg \$1 table string "" true; #X obj 10 201 max~ 0; #N canvas 0 22 450 300 @hv_obj 0; #X obj 146 77 inlet; #X obj 147 120 outlet; #X restore 81 130 pd @hv_obj system; #X obj 10 178 min~; #X obj 81 154 - 2; #X text 52 201 the sample delay may not exceed the table boundaries ; #X msg 81 108 table \$1 size; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X obj 280 42 inlet; #X restore 181 303 pd @hv_obj __tabread~if \$1; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X obj 249 48 inlet; #X restore 10 303 pd @hv_obj __tabread~if \$1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 169 24 inlet; #X obj 221 83 outlet; #X obj 159 83 outlet; #X restore 163 38 pd @hv_obj __switchcase set; #X text 162 7 NOTE(mhroth): there is supposed to be a control; #X text 161 20 connection from the left inlet to the switchcase; #N canvas 0 22 450 300 @hv_obj 0; #X obj 178 47 inlet; #X obj 165 128 outlet; #X restore 163 61 pd @hv_obj slice 1 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 150 61 inlet; #X obj 147 118 outlet; #X restore 81 86 pd @hv_obj __var \$1; #X obj 81 60 loadbang -1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 160 52 inlet~; #X obj 173 97 outlet~; #X restore 10 227 pd @hv_obj __floor~f; #X obj 328 79 inlet; #X text 327 60 a "fake" inlet to mimic onset messages; #X obj 10 154 inlet~ -~>; #X connect 1 0 3 0; #X connect 2 0 3 1; #X connect 3 0 4 1; #X connect 4 0 0 0; #X connect 6 0 17 0; #X connect 6 0 7 0; #X connect 7 0 16 0; #X connect 8 0 7 1; #X connect 10 0 2 0; #X connect 10 0 24 0; #X connect 11 0 13 0; #X connect 12 0 10 0; #X connect 13 0 12 1; #X connect 15 0 11 0; #X connect 16 0 1 0; #X connect 17 0 4 0; #X connect 17 0 1 1; #X connect 18 0 21 0; #X connect 21 0 16 1; #X connect 21 0 17 1; #X connect 21 0 22 0; #X connect 22 0 15 0; #X connect 23 0 22 0; #X connect 24 0 2 1; #X connect 24 0 6 0; #X connect 27 0 12 0; #X connect 27 0 18 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/tabread~.pd0000644000000000000000000000273114435670357017645 0ustar00#N canvas 672 216 463 321 10; #X obj 10 273 outlet~; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X restore 10 226 pd @hv_obj __cast~fi; #X text 7 297 @hv_arg \$1 table string "" true; #X obj 10 201 max~ 0; #N canvas 0 22 450 300 @hv_obj 0; #X obj 146 77 inlet; #X obj 147 120 outlet; #X restore 81 130 pd @hv_obj system; #X obj 10 178 min~; #X text 52 201 the sample delay may not exceed the table boundaries ; #X msg 81 108 table \$1 size; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X obj 249 48 inlet; #X restore 10 249 pd @hv_obj __tabread~if \$1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 169 24 inlet; #X obj 221 83 outlet; #X obj 159 83 outlet; #X restore 163 38 pd @hv_obj __switchcase set; #X text 162 7 NOTE(mhroth): there is supposed to be a control; #X text 161 20 connection from the left inlet to the switchcase; #N canvas 0 22 450 300 @hv_obj 0; #X obj 178 47 inlet; #X obj 165 128 outlet; #X restore 163 61 pd @hv_obj slice 1 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 150 61 inlet; #X obj 147 118 outlet; #X restore 81 86 pd @hv_obj __var \$1; #X obj 81 154 - 1; #X obj 81 60 loadbang -1; #X obj 10 154 inlet~ -~>; #X connect 1 0 8 0; #X connect 3 0 1 0; #X connect 4 0 14 0; #X connect 5 0 3 0; #X connect 7 0 4 0; #X connect 8 0 0 0; #X connect 9 0 12 0; #X connect 12 0 8 1; #X connect 12 0 13 0; #X connect 13 0 7 0; #X connect 14 0 5 1; #X connect 15 0 13 0; #X connect 16 0 5 0; #X connect 16 0 9 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/tabwrite.pd0000644000000000000000000000067014435670357017666 0ustar00#N canvas 686 568 220 136 10; #X obj 12 13 inlet -->; #X obj 82 13 inlet -->; #X obj 12 84 outlet -->; #N canvas 0 22 450 300 @hv_obj 0; #X obj 142 59 inlet; #X obj 157 109 outlet; #X obj 257 62 inlet; #X obj 206 59 inlet; #X restore 12 62 pd @hv_obj __tabwrite \$1; #X obj 12 35 route set; #X text 12 105 @hv_arg \$1 table string "" true; #X connect 0 0 4 0; #X connect 1 0 3 1; #X connect 3 0 2 0; #X connect 4 0 3 2; #X connect 4 1 3 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/tabwrite~.pd0000644000000000000000000000507314435670357020066 0ustar00#N canvas 536 160 472 533 10; #N canvas 107 52 450 300 @hv_obj 0; #X obj 145 102 inlet; #X obj 345 193 outlet; #X obj 236 180 outlet; #X obj 159 188 outlet; #X obj 291 186 outlet; #X restore 80 35 pd @hv_obj __switchcase start stop set; #N canvas 0 22 450 300 @hv_obj 0; #X obj 174 66 inlet; #X obj 176 154 outlet; #X obj 256 66 inlet; #X obj 316 65 inlet; #X restore 230 57 pd @hv_obj slice 1 1; #N canvas 0 23 450 300 @hv_obj 0; #X obj 174 66 inlet; #X obj 193 152 outlet; #X obj 256 66 inlet; #X obj 316 65 inlet; #X obj 259 153 outlet; #X restore 80 57 pd @hv_obj slice 1 1; #X text 8 499 @hv_arg \$1 table string "" true; #N canvas 0 22 450 300 @hv_obj 0; #X obj 169 68 inlet; #X obj 273 67 inlet; #X obj 96 70 inlet~; #X restore 9 479 pd @hv_obj __tabwrite_stoppable~f \$1; #X text 234 479 tabwrite~ starts in stopped state; #X obj 320 296 / 1000; #X obj 305 318 /; #X msg 305 80 0; #X text 366 296 samples per ms; #X text 329 319 ms per sample; #N canvas 0 22 450 300 @hv_obj 0; #X obj 151 67 inlet; #X obj 174 161 outlet; #X restore 336 167 pd @hv_obj system; #X msg 336 143 table \$1 size; #X obj 305 187 -; #X obj 305 207 * -1; #X obj 305 340 t a a a; #X text 39 178 TODO(mhroth): deal with OOB indicies; #X msg 316 363 clear; #X msg 152 446 stop; #N canvas 0 22 450 300 @hv_obj 0; #X obj 198 56 inlet; #X obj 128 57 inlet; #X obj 137 128 outlet; #X restore 305 385 pd @hv_obj __delay; #X text 79 3 NOTE(mhroth): there is supposed to be a control; #X text 78 16 connection from the left inlet to the switchcase; #X msg 320 249 samplerate; #N canvas 0 22 450 300 @hv_obj 0; #X obj 119 57 inlet; #X obj 119 97 outlet; #X restore 320 273 pd @hv_obj system; #N canvas 0 22 450 300 @hv_obj 0; #X obj 173 49 inlet; #X obj 172 144 outlet; #X obj 259 42 inlet; #X restore 336 120 pd @hv_obj __var \$1; #X obj 336 97 loadbang; #X obj 320 226 loadbang; #X obj 164 420 loadbang; #X msg 197 81 0; #X obj 9 35 inlet~ -~>; #X connect 0 0 2 0; #X connect 0 1 18 0; #X connect 0 2 1 0; #X connect 0 3 8 0; #X connect 1 0 4 2; #X connect 1 0 24 0; #X connect 2 0 4 1; #X connect 2 0 13 0; #X connect 2 1 28 0; #X connect 6 0 7 1; #X connect 7 0 15 0; #X connect 8 0 4 1; #X connect 8 0 13 0; #X connect 11 0 13 1; #X connect 12 0 11 0; #X connect 13 0 14 0; #X connect 14 0 7 0; #X connect 15 0 19 0; #X connect 15 1 19 1; #X connect 15 2 17 0; #X connect 17 0 19 0; #X connect 18 0 4 1; #X connect 19 0 18 0; #X connect 22 0 23 0; #X connect 23 0 6 0; #X connect 24 0 12 0; #X connect 25 0 24 0; #X connect 26 0 22 0; #X connect 27 0 18 0; #X connect 28 0 4 1; #X connect 28 0 13 0; #X connect 29 0 4 0; #X connect 29 0 0 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/tan.pd0000644000000000000000000000033514435670357016625 0ustar00#N canvas 439 480 151 128 10; #X obj 13 20 inlet; #X obj 13 80 outlet; #N canvas 0 22 183 125 @hv_obj 0; #X obj 19 24 inlet; #X obj 19 66 outlet; #X restore 13 50 pd @hv_obj __tan; #X connect 0 0 2 0; #X connect 2 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/tgl.pd0000644000000000000000000000027414435670357016633 0ustar00#N canvas 409 120 143 157 10; #X obj 32 32 inlet; #X obj 71 64 == 0; #X obj 32 96 outlet; #X obj 32 64 f 1; #X connect 0 0 3 0; #X connect 1 0 3 1; #X connect 3 0 1 0; #X connect 3 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/timer.pd0000644000000000000000000000154514435670357017167 0ustar00#N canvas 192 130 288 304 10; #X obj 24 23 inlet, f 6; #X obj 136 23 inlet; #X obj 83 272 outlet; #N canvas 0 22 450 300 @hv_obj 0; #X obj 145 62 inlet; #X obj 150 127 outlet; #X restore 24 115 pd @hv_obj system; #X msg 24 85 currentTime; #X obj 82 161 -; #N canvas 0 22 450 300 @hv_obj 0; #X obj 145 62 inlet; #X obj 150 127 outlet; #X restore 136 115 pd @hv_obj system; #X msg 136 85 currentTime; #X obj 83 247 /; #X obj 136 53 t a a; #N canvas 0 22 450 300 @hv_obj 0; #X obj 145 62 inlet; #X obj 150 127 outlet; #X restore 163 177 pd @hv_obj system; #X msg 163 147 samplerate; #X obj 163 207 / 1000; #X connect 0 0 4 0; #X connect 1 0 9 0; #X connect 3 0 5 1; #X connect 4 0 3 0; #X connect 5 0 8 0; #X connect 6 0 5 0; #X connect 7 0 6 0; #X connect 8 0 2 0; #X connect 9 0 7 0; #X connect 9 1 11 0; #X connect 10 0 12 0; #X connect 11 0 10 0; #X connect 12 0 8 1; ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1727976067.2795517 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/touchin.pd0000644000000000000000000000155314677551203017513 0ustar00#N canvas 114 229 459 438 10; #X obj 209 337 outlet; #X obj 152 76 unpack f f; #X obj 50 334 outlet; #X obj 83 104 loadbang; #X obj 83 174 == 0; #X obj 83 128 i \$1; #X obj 50 266 spigot; #X obj 209 101 + 1; #X obj 209 236 spigot; #X obj 215 175 ==; #X obj 152 237 spigot; #X obj 215 200 t f f; #X obj 209 313 max 1; #X obj 83 197 t f f; #X obj 150 270 spigot; #X obj 152 47 r __hv_touchin; #X text 226 78 pressure value and channel/port; #X connect 1 0 10 0; #X connect 1 0 6 0; #X connect 1 1 7 0; #X connect 3 0 5 0; #X connect 4 0 13 0; #X connect 5 0 4 0; #X connect 5 0 9 1; #X connect 6 0 2 0; #X connect 7 0 9 0; #X connect 7 0 14 0; #X connect 7 0 8 0; #X connect 8 0 12 0; #X connect 9 0 11 0; #X connect 10 0 2 0; #X connect 11 0 10 1; #X connect 11 1 8 1; #X connect 12 0 0 0; #X connect 13 0 6 1; #X connect 13 1 14 1; #X connect 14 0 12 0; #X connect 15 0 1 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/touchout.pd0000644000000000000000000000056514435670357017722 0ustar00#N canvas 860 405 231 322 10; #X obj 52 215 pack f f; #X obj 97 74 inlet channel; #X obj 97 146 f \$1; #X obj 114 106 loadbang; #X obj 52 40 inlet touch; #X obj 52 247 s __hv_touchout @hv_param; #X obj 97 168 - 1; #X obj 97 191 max; #X connect 0 0 5 0; #X connect 1 0 2 0; #X connect 2 0 6 0; #X connect 3 0 2 0; #X connect 4 0 0 0; #X connect 6 0 7 0; #X connect 7 0 0 1; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/until.pd0000644000000000000000000000166214435670357017202 0ustar00#N canvas 121 411 250 478 10; #X obj 39 26 inlet; #X obj 78 236 t f f; #X obj 78 296 spigot 0; #X obj 123 266 <; #X obj 78 206 f; #X obj 125 167 + 1; #X obj 105 357 outlet; #X obj 39 106 moses 1; #X obj 39 76 int; #X obj 78 326 t f b; #X obj 170 24 inlet; #X msg 170 76 0; #X obj 39 48 t f b; #X msg 66 76 1; #X obj 125 136 spigot 1; #X msg 39 394 input needs to be >= 1; #X obj 39 424 print (heavy) until error; #X obj 78 167 f 0; #X obj 78 136 t b f; #X connect 0 0 12 0; #X connect 1 0 2 0; #X connect 1 1 3 0; #X connect 2 0 9 0; #X connect 3 0 2 1; #X connect 4 0 1 0; #X connect 5 0 4 0; #X connect 7 0 15 0; #X connect 7 1 18 0; #X connect 8 0 7 0; #X connect 9 0 14 0; #X connect 9 1 6 0; #X connect 10 0 11 0; #X connect 11 0 14 1; #X connect 12 0 8 0; #X connect 12 1 13 0; #X connect 13 0 14 1; #X connect 14 0 5 0; #X connect 15 0 16 0; #X connect 17 0 4 0; #X connect 18 0 17 0; #X connect 18 1 3 1; #X coords 0 478 1 477 111 106 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/vcf~.pd0000644000000000000000000000522514435670357017022 0ustar00#N canvas 830 72 440 622 10; #X obj 96 11 inlet~ f; #X obj 260 11 inlet q; #X msg 361 189 1 \$1; #X obj 361 212 /; #X text 384 213 invq; #X obj 260 147 + 2; #X msg 260 168 2 \$1; #X obj 260 189 /; #X msg 260 212 2 \$1; #X obj 260 234 -; #X text 284 235 ampcorrect; #X obj 144 103 samplerate~; #X obj 112 143 /; #X obj 97 166 *~; #X obj 97 372 *~; #X obj 112 403 sig~ 1; #X obj 97 433 -~; #X obj 136 566 outlet~; #X obj 19 566 outlet~; #X msg 112 123 6.28319 \$1; #X obj 19 419 *~; #X obj 19 455 *~; #X obj 97 496 *~; #X obj 224 482 *~; #X obj 254 397 *~; #X obj 239 437 -~; #X obj 239 458 sqrt~; #X text 277 457 sin; #N canvas 0 23 450 300 @hv_obj 0; #X obj 188 51 inlet~; #X obj 135 50 inlet~; #X obj 209 193 outlet~; #X obj 290 50 inlet~; #X obj 235 50 inlet~; #X obj 137 192 outlet~; #X obj 146 125 cpole~; #X obj 235 72 *~ -1; #X obj 291 72 *~ -1; #X connect 0 0 6 1; #X connect 1 0 6 0; #X connect 3 0 8 0; #X connect 4 0 7 0; #X connect 6 0 5 0; #X connect 6 1 2 0; #X connect 7 0 6 2; #X connect 8 0 6 3; #X restore 19 543 pd @hv_obj __cpole~f; #X text 125 431 -r = cf*qinv-1; #X text 122 495 -coefr; #X text 251 482 -coefi; #X obj 260 53 f \$1; #X obj 171 11 loadbang; #N canvas 0 23 450 300 @hv_obj 0; #X obj 131 90 inlet~; #X obj 131 156 cos~; #X obj 131 177 outlet~; #X obj 131 126 /~ 6.28319; #X connect 0 0 3 0; #X connect 1 0 2 0; #X connect 3 0 1 0; #X restore 254 368 pd @hv_obj __cos~f; #X obj 19 11 inlet~ in; #X msg 260 119 0; #X obj 361 235 t a; #X obj 171 32 t a a; #X obj 97 329 min~; #X msg 231 119 -1; #X text 125 372 oneminusr = cf*qinv; #X obj 260 76 moses 1e-05; #X text 333 90 > 0; #X text 147 246 cf [1e-05 \, pi]; #X obj 97 247 max~ 1e-05; #X connect 0 0 13 0; #X connect 1 0 32 0; #X connect 2 0 3 0; #X connect 3 0 37 0; #X connect 5 0 6 0; #X connect 6 0 7 0; #X connect 7 0 8 0; #X connect 8 0 9 0; #X connect 9 0 21 1; #X connect 11 0 19 0; #X connect 12 0 13 1; #X connect 13 0 45 0; #X connect 14 0 20 1; #X connect 14 0 16 0; #X connect 15 0 16 1; #X connect 15 0 25 0; #X connect 16 0 22 0; #X connect 16 0 23 0; #X connect 19 0 12 0; #X connect 20 0 21 0; #X connect 21 0 28 0; #X connect 22 0 28 2; #X connect 23 0 28 3; #X connect 24 0 25 1; #X connect 25 0 26 0; #X connect 26 0 23 1; #X connect 28 0 18 0; #X connect 28 1 17 0; #X connect 32 0 42 0; #X connect 33 0 38 0; #X connect 34 0 24 0; #X connect 34 0 24 1; #X connect 34 0 22 1; #X connect 35 0 20 0; #X connect 36 0 5 0; #X connect 37 0 14 1; #X connect 38 0 32 0; #X connect 38 1 11 0; #X connect 39 0 14 0; #X connect 40 0 39 1; #X connect 40 0 14 1; #X connect 42 0 36 0; #X connect 42 0 40 0; #X connect 42 1 2 0; #X connect 42 1 5 0; #X connect 42 1 39 1; #X connect 45 0 39 0; #X connect 45 0 34 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/vd~.pd0000644000000000000000000000641414435670357016656 0ustar00#N canvas 859 23 532 664 10; #X obj 19 26 inlet~; #X obj 4 638 outlet~; #X obj 19 163 *~; #X obj 34 116 samplerate~; #X text 79 140 convert millisecond delay to sample delay; #N canvas 0 22 450 300 @hv_obj 0; #X obj 146 77 inlet; #X obj 147 120 outlet; #X restore 95 93 pd @hv_obj system; #X obj 4 302 -~; #X obj 4 409 +~; #X text 33 301 table index; #X obj 19 565 -~; #X obj 47 565 -~; #X obj 19 589 *~; #X obj 4 613 +~; #X text 73 566 linear interpolation; #N canvas 587 66 450 300 @hv_obj 0; #X obj 146 106 inlet~; #X obj 154 156 outlet~; #X obj 239 103 inlet~; #X restore 35 385 pd @hv_obj __and~f; #X obj 4 279 +~; #X obj 68 26 t a a; #N canvas 587 66 450 300 @hv_obj 0; #X obj 221 104 inlet~; #X obj 154 156 outlet~; #X obj 146 106 inlet~; #X restore 150 363 pd @hv_obj __lt~f; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X restore 4 438 pd @hv_obj __cast~fi; #N canvas 0 23 450 300 @hv_obj 0; #X obj 232 43 inlet~; #X obj 169 185 outlet~; #X obj 165 46 inlet~; #X restore 195 478 pd @hv_obj __add~i; #N canvas 0 22 450 300 @hv_obj 0; #X obj 173 75 inlet; #X obj 175 149 outlet~; #X restore 300 456 pd @hv_obj __var_k~i 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 173 75 inlet; #X obj 175 149 outlet~; #X restore 249 341 pd @hv_obj __var_k~f 0; #X obj 95 49 symbol del-\$1; #X obj 34 139 / 1000; #N canvas 587 66 450 300 @hv_obj 0; #X obj 154 156 outlet~; #X obj 146 106 inlet; #X restore 4 234 pd @hv_obj __tabhead~f del-\$1; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X obj 280 42 inlet; #X restore 195 501 pd @hv_obj __tabread~if del-\$1; #N canvas 0 23 450 300 @hv_obj 0; #X obj 165 46 inlet~; #X obj 169 185 outlet~; #X obj 249 48 inlet; #X restore 4 501 pd @hv_obj __tabread~if del-\$1; #X text 182 49 @hv_arg \$1 table string "" true; #N canvas 0 22 450 300 @hv_obj 0; #X obj 148 99 inlet; #X obj 143 158 outlet~; #X restore 27 257 pd @hv_obj __var_k~f -1 -1 true; #X obj 68 4 loadbang -1; #X msg 95 71 table \$1 size; #X text 150 430 NOTE(mhroth): SSE cast op seems to round to the nearest int \, not down; #X obj 19 210 max~ 0; #X obj 19 188 min~; #X text 70 202 [0 \, size-1]; #X text 71 187 ensure that the input never exceeds the table bounds ; #X obj 45 163 - 1; #N canvas 0 22 450 300 @hv_obj 0; #X obj 160 52 inlet~; #X obj 173 97 outlet~; #X restore 4 331 pd @hv_obj __floor~f; #X text 30 412 wrapped table index; #N canvas 0 22 450 300 @hv_obj 0; #X obj 148 99 inlet; #X obj 143 158 outlet~; #X restore 35 362 pd @hv_obj var; #X connect 0 0 2 0; #X connect 2 0 33 0; #X connect 3 0 23 0; #X connect 5 0 36 0; #X connect 5 0 39 0; #X connect 6 0 37 0; #X connect 6 0 10 0; #X connect 7 0 18 0; #X connect 9 0 11 0; #X connect 10 0 11 1; #X connect 11 0 12 1; #X connect 12 0 1 0; #X connect 14 0 7 1; #X connect 15 0 6 0; #X connect 16 0 3 0; #X connect 16 1 22 0; #X connect 17 0 14 1; #X connect 18 0 26 0; #X connect 18 0 19 0; #X connect 19 0 25 0; #X connect 20 0 19 1; #X connect 21 0 17 1; #X connect 22 0 30 0; #X connect 23 0 2 1; #X connect 24 0 15 0; #X connect 25 0 9 0; #X connect 26 0 9 1; #X connect 26 0 12 0; #X connect 28 0 15 1; #X connect 29 0 16 0; #X connect 30 0 5 0; #X connect 32 0 6 1; #X connect 33 0 32 0; #X connect 36 0 33 1; #X connect 37 0 17 0; #X connect 37 0 10 1; #X connect 37 0 7 0; #X connect 39 0 14 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/vradio.pd0000644000000000000000000000020314435670357017321 0ustar00#N canvas 0 149 210 157 10; #X obj 24 35 inlet; #X obj 24 57 float 0; #X obj 24 79 outlet; #X connect 0 0 1 0; #X connect 1 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/vsl.pd0000644000000000000000000000020314435670357016641 0ustar00#N canvas 0 149 210 157 10; #X obj 24 35 inlet; #X obj 24 57 float 0; #X obj 24 79 outlet; #X connect 0 0 1 0; #X connect 1 0 2 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/wrap.pd0000644000000000000000000000076114435670357017017 0ustar00#N canvas 525 135 222 227 10; #X obj 39 30 inlet; #X obj 39 150 -; #X obj 39 180 outlet; #N canvas 0 22 450 300 @hv_obj 0; #X obj 118 64 inlet; #X obj 118 86 outlet; #X connect 0 0 1 0; #X restore 66 120 pd @hv_obj __floor; #X obj 39 90 t a a; #N canvas 0 22 450 300 @hv_obj 0; #X obj 87 75 inlet; #X obj 87 97 outlet; #X connect 0 0 1 0; #X restore 39 60 pd @hv_obj __cast_f; #X connect 0 0 5 0; #X connect 1 0 2 0; #X connect 3 0 1 1; #X connect 4 0 1 0; #X connect 4 1 3 0; #X connect 5 0 4 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1685549294.772207 hvcc-0.13.3/hvcc/interpreters/pd2hv/libs/pd/wrap~.pd0000644000000000000000000000044014435670357017207 0ustar00#N canvas 525 135 213 168 10; #X obj 29 26 inlet~; #N canvas 0 22 450 300 @hv_obj 0; #X obj 69 171 outlet~; #X obj 69 82 inlet~; #X restore 44 56 pd @hv_obj __floor~f; #X obj 29 86 -~; #X obj 29 116 outlet~; #X connect 0 0 1 0; #X connect 0 0 2 0; #X connect 1 0 2 1; #X connect 2 0 3 0; ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.272823 hvcc-0.13.3/hvcc/interpreters/pd2hv/pd2hv.py0000644000000000000000000001157714735300474015562 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2023-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import argparse import json import os import time from typing import List, Optional from hvcc.interpreters.pd2hv.PdParser import PdParser from hvcc.types.compiler import CompilerResp, CompilerNotif class Colours: purple = "\033[95m" cyan = "\033[96m" dark_cyan = "\033[36m" blue = "\033[94m" green = "\033[92m" yellow = "\033[93m" red = "\033[91m" bold = "\033[1m" underline = "\033[4m" end = "\033[0m" class pd2hv: @classmethod def get_supported_objects(cls) -> List: return PdParser.get_supported_objects() @classmethod def compile( cls, pd_path: str, hv_dir: str, search_paths: Optional[List] = None, verbose: bool = False, export_args: bool = False ) -> CompilerResp: tick = time.time() parser = PdParser() # create parser state if search_paths is not None: for p in search_paths: parser.add_absolute_search_directory(p) pd_graph = parser.graph_from_file(pd_path) notices = pd_graph.get_notices() # check for errors if len(notices.errors) > 0: return CompilerResp( stage="pd2hv", obj_counter=parser.obj_counter, notifs=CompilerNotif( has_error=True, errors=notices.errors, warnings=notices.warnings ), in_dir=os.path.dirname(pd_path), in_file=os.path.basename(pd_path), compile_time=(time.time() - tick) ) if not os.path.exists(hv_dir): os.makedirs(hv_dir) hv_file = f"{os.path.splitext(os.path.basename(pd_path))[0]}.hv.json" hv_path = os.path.join(hv_dir, hv_file) with open(hv_path, "w") as f: if verbose: json.dump(pd_graph.to_hv(export_args=export_args), f, sort_keys=True, indent=2, separators=(",", ": ")) else: json.dump(pd_graph.to_hv(export_args=export_args), f) return CompilerResp( stage="pd2hv", obj_counter=parser.obj_counter, notifs=CompilerNotif( warnings=notices.warnings ), in_dir=os.path.dirname(pd_path), in_file=os.path.basename(pd_path), out_dir=hv_dir, out_file=hv_file, compile_time=(time.time() - tick) ) def main() -> None: parser = argparse.ArgumentParser( description="Converts a Pd patch into the Heavy language format.") parser.add_argument( "pd_path", help="The Pd patch to convert to Heavy.") parser.add_argument( "hv_dir", help="Directory to store generated Heavy patches.") parser.add_argument( "--export", help="Export Heavy arguments. Use this to make precompiled patches.", action="count") parser.add_argument( "-v", "--verbose", help="Show debugging information.", action="count") args = parser.parse_args() args.pd_path = os.path.abspath(os.path.expanduser(args.pd_path)) args.hv_dir = os.path.abspath(os.path.expanduser(args.hv_dir)) result = pd2hv.compile( pd_path=args.pd_path, hv_dir=args.hv_dir, search_paths=None, verbose=args.verbose, export_args=args.export) for i, n in enumerate(result.notifs.errors): print("{0:3d}) {1}Error #{2:4d}:{3} {4}".format( i + 1, Colours.red, n.enum, Colours.end, n.message)) for i, n in enumerate(result.notifs.warnings): print("{0:3d}) {1}Warning #{2:4d}:{3} {4}".format( i + 1, Colours.yellow, n.enum, Colours.end, n.message)) if args.verbose: if len(result.notifs.errors) == 0: print("Heavy file written to", os.path.join(result.out_dir, result.out_file)) print("Total pd2hv compile time: {0:.2f}ms".format(result.compile_time * 1000)) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739952822.5713618 hvcc-0.13.3/hvcc/main.py0000644000000000000000000001167014755311267011710 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # Copyright (C) 2021-2024 Wasted Audio # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import argparse import json import os import sys import time from hvcc.version import VERSION from hvcc.compiler import compile_dataflow class Colours: purple = "\033[95m" cyan = "\033[96m" dark_cyan = "\033[36m" blue = "\033[94m" green = "\033[92m" yellow = "\033[93m" red = "\033[91m" bold = "\033[1m" underline = "\033[4m" end = "\033[0m" def main() -> bool: tick = time.time() parser = argparse.ArgumentParser( description="This is the Wasted Audio Heavy compiler. It compiles supported dataflow languages into C," " and other supported frameworks.") parser.add_argument( "in_path", help="The input dataflow file.") parser.add_argument( "-o", "--out_dir", help="Build output path.") parser.add_argument( "-p", "--search_paths", nargs="+", help="Add a list of directories to search through for abstractions.") parser.add_argument( "-n", "--name", default="heavy", help="Provides a name for the generated Heavy context.") parser.add_argument( "-m", "--meta", help="Provide metadata file (json) for generator") parser.add_argument( "-g", "--gen", nargs="+", default=["c"], help="List of generator outputs: c, unity, wwise, js, pdext, daisy, dpf, fabric, owl") parser.add_argument( "-G", "--ext-gen", nargs="*", help="List of external generator modules, see 'External Generators' docs page.") parser.add_argument( "--results_path", help="Write results dictionary to the given path as a JSON-formatted string." " Target directory will be created if it does not exist.") parser.add_argument( "--nodsp", action='store_true', help="Disable DSP. Run as control-only patch." ) parser.add_argument( "-v", "--verbose", help="Show debugging information.", action="count") parser.add_argument( "--copyright", help="A string indicating the owner of the copyright.") parser.add_argument( "-V", "--version", action='version', help="Print version and exit.", version=VERSION ) args = parser.parse_args() in_path = os.path.abspath(args.in_path) results = compile_dataflow( in_path=in_path, out_dir=args.out_dir or os.path.dirname(in_path), patch_name=args.name, patch_meta_file=args.meta, search_paths=args.search_paths, generators=args.gen, ext_generators=args.ext_gen, verbose=args.verbose, copyright=args.copyright, nodsp=args.nodsp ) errorCount = 0 for r in list(results.root.values()): # print any errors if r.notifs.has_error: for i, error in enumerate(r.notifs.errors): errorCount += 1 print("{4:3d}) {2}Error{3} {0}: {1}".format( r.stage, error.message, Colours.red, Colours.end, i + 1)) # only print exception if no errors are indicated if len(r.notifs.errors) == 0 and r.notifs.exception is not None: errorCount += 1 print("{2}Error{3} {0} exception: {1}".format( r.stage, r.notifs.exception, Colours.red, Colours.end)) # clear any exceptions such that results can be JSONified if necessary r.notifs.exception = None # print any warnings for i, warning in enumerate(r.notifs.warnings): print("{4:3d}) {2}Warning{3} {0}: {1}".format( r.stage, warning.message, Colours.yellow, Colours.end, i + 1)) if args.results_path: results_path = os.path.realpath(os.path.abspath(args.results_path)) results_dir = os.path.dirname(results_path) if not os.path.exists(results_dir): os.makedirs(results_dir) with open(results_path, "w") as f: json.dump(results.model_dump(), f) if args.verbose: print("Total compile time: {0:.2f}ms".format(1000 * (time.time() - tick))) return errorCount != 0 if __name__ == "__main__": ret = main() sys.exit(ret) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.272823 hvcc-0.13.3/hvcc/types/IR.py0000644000000000000000000000567114735300474012442 0ustar00# Heavy Compiler Collection # Copyright (C) 2024 Wasted Audio # # SPDX-License-Identifier: GPL-3.0-only from pydantic import BaseModel, RootModel from typing import Dict, List, Optional, Union from hvcc.types.Lang import LangLetType from hvcc.version import VERSION # IR Object Definitions IRValue = Union[float, int, str, List[float], List[int]] class IRArg(BaseModel): name: str value_type: str description: str = "" default: Optional[IRValue] = None required: bool class IR(BaseModel): control: bool signal: bool init: bool class Perf(BaseModel): avx: float = 0 sse: float = 0 neon: float = 0 class IRNode(BaseModel): inlets: List[LangLetType] ir: IR outlets: List[LangLetType] args: List[IRArg] = [] perf: Optional[Perf] = Perf() # perf: Perf description: Optional[str] = None alias: List[str] = [] tags: List[str] = [] keywords: List[str] = [] class HeavyIRType(RootModel): root: Dict[str, IRNode] # IR Graph Definitions class IRName(BaseModel): escaped: str display: str class IRObjectdict(BaseModel): args: Dict type: str class IRInit(BaseModel): order: List[str] = [] class IRReceiver(BaseModel): display: str hash: str extern: Optional[str] = None attributes: Dict ids: List[str] class IROnMessage(BaseModel): id: str inletIndex: Optional[int] = None class IRSendMessage(BaseModel): """ This object is a mess and should be split up """ id: str onMessage: List[List[IROnMessage]] # TODO: why is it a nested List? type: Optional[str] = None extern: Optional[str] = '' attributes: Optional[Union[List, Dict]] = None # TODO: List from IR and Dict from Lang hash: Optional[str] = None display: Optional[str] = None name: str = '' class IRTable(BaseModel): id: str display: str hash: str extern: Optional[bool] = None class IRControl(BaseModel): receivers: Dict[str, IRReceiver] sendMessage: List[IRSendMessage] class IRNumTempBuffer(BaseModel): float: int integer: int class IRBuffer(BaseModel): type: str index: int class IRSignalList(BaseModel): id: str inputBuffers: List[IRBuffer] outputBuffers: List[IRBuffer] class IRSignal(BaseModel): numInputBuffers: int numOutputBuffers: int numTemporaryBuffers: IRNumTempBuffer processOrder: List[IRSignalList] class IRGraph(BaseModel): version: str = VERSION name: IRName objects: Dict[str, IRObjectdict] = {} init: IRInit tables: Dict[str, IRTable] = {} control: IRControl signal: IRSignal if __name__ == "__main__": """ Test object definitions """ import json import importlib_resources heavy_ir_json = importlib_resources.files('hvcc') / 'core/json/heavy.ir.json' with open(heavy_ir_json, "r") as f: data = json.load(f) heavy_ir = HeavyIRType(root=data) print(heavy_ir.root.keys()) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.272823 hvcc-0.13.3/hvcc/types/Lang.py0000644000000000000000000000235714735300474013007 0ustar00# Heavy Compiler Collection # Copyright (C) 2024 Wasted Audio # # SPDX-License-Identifier: GPL-3.0-only from pydantic import BaseModel, RootModel from typing import List, Optional, Dict, Literal, Union LangConnectionType = Literal["-->", "-~>", "~f>"] LangLetType = Literal["-->", "-~>", "~i>", "~f>", "signal"] LangValueType = Literal["float", "int", "string", "bool", "dict", "floatarray", "intarray", "stringarray"] class LangArg(BaseModel): name: str value_type: Optional[LangValueType] = None description: str default: Union[float, int, str, Dict, List, None] = None required: bool class LangLet(BaseModel): name: str connectionType: LangConnectionType description: str class LangNode(BaseModel): description: str inlets: List[LangLet] outlets: List[LangLet] args: List[LangArg] alias: List[str] tags: List[str] class HeavyLangType(RootModel): root: Dict[str, LangNode] if __name__ == "__main__": import json import importlib_resources heavy_lang_json = importlib_resources.files('hvcc') / 'core/json/heavy.lang.json' with open(heavy_lang_json, "r") as f: data = json.load(f) heavy_lang = HeavyLangType(root=data) print(heavy_lang.root.keys()) ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.273823 hvcc-0.13.3/hvcc/types/__.init__.py0000644000000000000000000000000014735300474013722 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739952822.5713618 hvcc-0.13.3/hvcc/types/compiler.py0000644000000000000000000000443714755311267013745 0ustar00# Heavy Compiler Collection # Copyright (C) 2024 Wasted Audio # # SPDX-License-Identifier: GPL-3.0-only from abc import ABC, abstractmethod from collections import Counter, defaultdict from typing import Dict, List, Optional, Tuple from pydantic import BaseModel, RootModel from hvcc.interpreters.pd2hv.NotificationEnum import NotificationEnum from hvcc.types.meta import Meta from hvcc.types.IR import IRGraph, IRReceiver, IRSendMessage, IRTable class CompilerMsg(BaseModel): enum: NotificationEnum = NotificationEnum.EMPTY message: str class CompilerNotif(BaseModel, arbitrary_types_allowed=True): has_error: bool = False exception: Optional[Exception] = None warnings: List[CompilerMsg] = [] errors: List[CompilerMsg] = [] class CompilerResp(BaseModel): stage: str notifs: CompilerNotif = CompilerNotif() in_dir: str = "" in_file: str = "" out_dir: str = "" out_file: str = "" compile_time: float = 0.0 obj_counter: Counter = Counter() obj_perf: Dict[str, Counter] = defaultdict(Counter) ir: Optional[IRGraph] = None class CompilerResults(RootModel): root: Dict[str, CompilerResp] class ExternParams(BaseModel): inParam: List[Tuple[str, IRReceiver]] = [] outParam: List[Tuple[str, IRSendMessage]] = [] class ExternEvents(BaseModel): inEvent: List[Tuple[str, IRReceiver]] = [] outEvent: List[Tuple[str, IRSendMessage]] = [] class ExternMidi(BaseModel): inMidi: List[str] = [] outMidi: List[str] = [] class ExternMemoryPool(BaseModel): internal: int = 0 inputQueue: int = 0 outputQueue: int = 0 class ExternInfo(BaseModel): parameters: ExternParams = ExternParams() events: ExternEvents = ExternEvents() midi: ExternMidi = ExternMidi() tables: List[Tuple[str, IRTable]] = [] memoryPoolSizesKb: ExternMemoryPool = ExternMemoryPool() class Generator(ABC): @classmethod @abstractmethod def compile( cls, c_src_dir: str, out_dir: str, externs: ExternInfo, patch_name: Optional[str] = None, patch_meta: Meta = Meta(), num_input_channels: int = 0, num_output_channels: int = 0, copyright: Optional[str] = None, verbose: Optional[bool] = False ) -> CompilerResp: raise NotImplementedError ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1735754044.273823 hvcc-0.13.3/hvcc/types/meta.py0000644000000000000000000000375514735300474013057 0ustar00# Heavy Compiler Collection # Copyright (C) 2024 Wasted Audio # # SPDX-License-Identifier: GPL-3.0-only from typing import Dict, Literal, List, Optional, Tuple, Union from pydantic import BaseModel, HttpUrl DaisyBoards = Literal['pod', 'petal', 'patch', 'patch_init', 'field'] DaisyBootloader = Literal['BOOT_NONE', 'BOOT_SRAM', 'BOOT_QSPI'] DPFFormats = Literal['lv2', 'lv2_sep', 'vst2', 'vst3', 'clap', 'jack', 'dssi', 'ladspa'] class Daisy(BaseModel): board: DaisyBoards = 'pod' board_file: Optional[str] = None libdaisy_path: Union[str, int] = 2 usb_midi: bool = False debug_printing: bool = False samplerate: int = 48000 blocksize: Optional[int] = None linker_script: str = '' bootloader: Optional[DaisyBootloader] = None class DPFUISize(BaseModel): width: int height: int class DPFPortGroups(BaseModel): input: Dict[str, Dict[str, Union[int, Tuple[int, bool]]]] = {} output: Dict[str, Dict[str, Union[int, Tuple[int, bool]]]] = {} class DPF(BaseModel): dpf_path: str = "" description: Optional[str] = None makefile_dep: List[str] = [] enable_ui: bool = False enable_modgui: bool = False ui_size: Optional[DPFUISize] = None midi_input: bool = False midi_output: bool = False port_groups: Optional[DPFPortGroups] = None enumerators: Optional[Dict[str, List[str]]] = None denormals: bool = True version: Optional[str] = None license: Optional[str] = None maker: Optional[str] = None homepage: Optional[HttpUrl] = None plugin_uri: Optional[str] = None plugin_clap_id: Optional[str] = None plugin_formats: List[DPFFormats] = [] lv2_info: Optional[str] = None vst3_info: Optional[str] = None clap_info: List[str] = [] class Meta(BaseModel): name: Optional[str] = None nosimd: Optional[bool] = False daisy: Daisy = Daisy() dpf: DPF = DPF() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1735754044.2748232 hvcc-0.13.3/hvcc/utils.py0000644000000000000000000000461214735300474012116 0ustar00# Copyright (C) 2014-2018 Enzien Audio, Ltd. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import sys import argparse import json from hvcc.core.hv2ir.HeavyLangObject import HeavyLangObject from hvcc.interpreters.pd2hv.PdParser import PdParser from hvcc.types.meta import Meta, DPF, Daisy gens = { "dpf": DPF, "daisy": Daisy } def main() -> None: parser = argparse.ArgumentParser( description="Some separate heavy utilities, wrapped into a single app") subparsers = parser.add_subparsers(dest="command") subparsers.add_parser("pdobjects", help="list supported Pure Data objects") subparser_hvhash = subparsers.add_parser("hvhash", help="print the heavy hash of the input string") subparser_hvhash.add_argument("string") subparser_meta = subparsers.add_parser("metaschema", help="show JSON Schema of the Meta() model") subparser_meta.add_argument("-g", "--generator", help="Choose supported generator: DPF, Daisy") parsed_args = parser.parse_args(args=None if sys.argv[1:] else ['--help']) args = vars(parsed_args) command = args.pop("command") if command == "pdobjects": obj_list = PdParser.get_supported_objects() obj_list.sort() obj_dict = { "Message Objects": [k for k in obj_list if '~' not in k], "Signal Objects": [k for k in obj_list if '~' in k] } print(json.dumps(obj_dict, indent=4)) elif command == "hvhash": print("0x{0:X}".format(HeavyLangObject.get_hash(args['string']))) elif command == "metaschema": generator = args.get('generator') if generator is not None: model = gens[generator.lower()]() else: model = Meta print(json.dumps(model.model_json_schema(), indent=4)) else: pass if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739952989.4296463 hvcc-0.13.3/hvcc/version.py0000644000000000000000000000002314755311535012435 0ustar00VERSION = "0.13.3" ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739952989.4296463 hvcc-0.13.3/pyproject.toml0000644000000000000000000000342114755311535012374 0ustar00[tool.poetry] name = "hvcc" version = "0.13.3" description = "`hvcc` is a python-based dataflow audio programming language compiler that generates C/C++ code and a variety of specific framework wrappers." authors = ["Enzien Audio, Wasted Audio"] license = "GPLv3" readme = "README.md" documentation = "https://wasted-audio.github.io/hvcc/" repository = "https://github.com/Wasted-Audio/hvcc" classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Topic :: Software Development :: Compilers", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12" ] [tool.poetry.scripts] hvcc = "hvcc:main" hvutil = "hvcc.utils:main" [tool.poetry.dependencies] python = "^3.8.1" Jinja2 = ">=2.11" importlib-resources = ">=5.1" wstd2daisy = ">=0.5.3" pydantic = ">=2.9.1" [tool.poetry.group.dev.dependencies] numpy = [ { version = "^2.0.1", python = "^3.9" }, { version = "^1.24.3", python = "==3.8"} ] scipy = [ { version = "^1.13.1", python = "^3.9"}, { version = "^1.9.1", python = "==3.8"} ] pytest-cov = "^5.0.0" flake8 = "^7.1.1" mypy = "^1.11.2" pytest = "^8.3.3" [tool.poetry-pyinstaller-plugin] collect = { all = ["json2daisy"] } include = { "hvcc/generators" = "hvcc/generators", "hvcc/core" = "hvcc/core", "hvcc/interpreters" = "hvcc/interpreters" } [tool.poetry-pyinstaller-plugin.scripts] Heavy = { source = "hvcc/main.py", type = "onefile", bundle = true, arch = "x86_64" } [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.mypy] plugins = [ "pydantic.mypy" ] hvcc-0.13.3/PKG-INFO0000644000000000000000000002050700000000000010511 0ustar00Metadata-Version: 2.1 Name: hvcc Version: 0.13.3 Summary: `hvcc` is a python-based dataflow audio programming language compiler that generates C/C++ code and a variety of specific framework wrappers. Home-page: https://github.com/Wasted-Audio/hvcc License: GPLv3 Author: Enzien Audio, Wasted Audio Requires-Python: >=3.8.1,<4.0.0 Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3) Classifier: License :: Other/Proprietary License Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: 3.8 Classifier: Topic :: Software Development :: Compilers Requires-Dist: Jinja2 (>=2.11) Requires-Dist: importlib-resources (>=5.1) Requires-Dist: pydantic (>=2.9.1) Requires-Dist: wstd2daisy (>=0.5.3) Project-URL: Documentation, https://wasted-audio.github.io/hvcc/ Project-URL: Repository, https://github.com/Wasted-Audio/hvcc Description-Content-Type: text/markdown # Heavy Compiler Collection (hvcc) [![Build Status](https://github.com/Wasted-Audio/hvcc/actions/workflows/ci.yml/badge.svg)](https://github.com/Wasted-Audio/hvcc/actions) [![pypi](https://img.shields.io/pypi/v/hvcc.svg)](https://pypi.python.org/pypi/hvcc) [![python](https://img.shields.io/pypi/pyversions/hvcc.svg)](https://pypi.python.org/pypi/hvcc) `hvcc` is a python-based dataflow audio programming language compiler that generates C/C++ code and a variety of specific framework wrappers. ## Background Originaly created by Enzien Audio, the need for `hvcc` arose from running against performance limitations while creating interactive music and sound products for the iPhone. [Pure Data](https://puredata.info) (libpd) was the only real choice for a design tool as it was embeddable and provided a high enough abstraction level that musicians or sound designers could be creative. The goal was to leverage Pure Data as a design interface and statically interpret the resultant patches to generate a low-level, portable and optimised C/C++ program that would be structured to take advantage of modern hardware whilst still generating the same behaviour and audio output as Pure Data. It has since then been expanded to provide further support for many different platforms and frameworks, targeting game audio design, daw plugins and embedded production tools. In 2021 Wasted Audio took over maintenance of the project. ## Documentation * [Introduction](/docs/01.introduction.md) * [What is heavy?](/docs/01.introduction.md#what-is-heavy) * [Supported patch formats](/docs/01.introduction.md#supported-patch-formats) * [Supported platforms](/docs/01.introduction.md#supported-platforms) * [Supported frameworks](/docs/01.introduction.md#supported-frameworks) * [Licensing](/docs/01.introduction.md#licensing) * [Getting Started](/docs/02.getting_started.md) * [Generators](/docs/03.generators.md) * [MIDI](/docs/04.midi.md) * [C API](/docs/05.c.md) * [C++ API](/docs/06.cpp.md) * [Heavy Lang Info](/docs/07.heavy_lang.md) * [Heavy IR Info](/docs/08.heavy_ir_lang.md) * [Supported vanilla objects](/docs/09.supported_vanilla_objects.md) * [Unsupported vanilla objects](/docs/10.unsupported_vanilla_objects.md) ## Integrations hvcc has been integrated into several projects and services. This allows to easily compile patches without having to install hvcc manually. * [plugdata](https://plugdata.org/) - Modern interface for Pure Data. Includes a full cross-platform toolchain and targets Daisy, DPF and PD Externals. * [mod-cloud-builder](https://github.com/moddevices/mod-cloud-builder) - Online service for building LV2 plugins for the MOD platform. * [OWL Patch Library](https://www.rebeltech.org/patch-library) - Online service for building OWL plugins (uses an old fork). ## Requirements Python 3.8 up to 3.12 * `jinja2` (for generator templating) * `importlib_resources` (for reading static resources) * `json2daisy` (for daisy integration) For tests: * `tox` (python install) * `numpy/scipy` (requirements-dev) * `midifile` (git submodule) * `tinywav` (git submodule) * `clang/clang++` (system install) ## Installation hvcc is available from pypi.org and can be installed using python3 pip: `$ pip3 install hvcc` If you want to develop hvcc you can install it from the source directory: `$ git clone https://github.com/Wasted-Audio/hvcc.git` `$ cd hvcc/` `$ pip3 install -e .` ## Usage `hvcc` requires at least one argument that determines the top-level patch file to be loaded. Generate a C/C++ program from `input.pd` and place the files in `~/myProject/` `$ hvcc ~/myProject/_main.pd` This command will generate the following directories: * `~/myProject/hv` heavylang representation of the input pd patch(es) * `~/myProject/ir` heavyir representation of the heavylang patch * `~/myProject/c` final generated C/C++ source files (this is what you would use in your project) ### `-o` Select output directory As seen in the above command, typical output of `hvcc` is split into several directories that contain the intermediate files used by the compiler itself, the final generated source files, and any additional framework specific files and projects. The `-o` or `--out_dir` parameter will specify where the output files are placed after a successful compile. For example: `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/` Will place all the generated files in `~/Desktop/somewhere/else/`. ### `-n` Specify Patch Name The `-n` or `--name` parameter can be used to easily namespace the generated code so that there are no conflicts when integrating multiple patches into the same project. `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/ -n mySynth` ### `-g` Generators Once `hvcc` has generated internal information about the patch the `-g` or `--gen` parameter can be used to specify the output files it should generate. By default it will always include `c` for the C/C++ source files and additional generators can specified for certain framework targets. For example: `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/ -n mySynth -g unity` Will also generate a `unity` section in the output directory contain all the build projects and source files to compile a Unity plugin. It is also possible to pass a list of generators: `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/ -n mySynth -g unity wwise js` A list of available generator options can be found [here](/docs/03.generators.md) ### `-p` Search Paths `hvcc` will iterate through various directories when resolving patch objects and abstractions. The `-p` or `--search_paths` argument can be used to add additional folders for `hvcc` to look in. Note that this argument is not needed for abstractions in the same folder as the top-level patch. This can be handy when using a third-party patch library like [heavylib](https://github.com/Wasted-Audio/heavylib) for example. Simply append any folder paths after the `-p` flag like so: `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/ -n mySynth -p ~/Workspace/Projects/Enzien/heavylib/ ~/Desktop/myLib/` ### `-m` Meta Data `hvcc` can take extra meta-data via a supplied json file. It depends on the generator which fields are supported. ### `--copyright` User Copyright By default all the generated source files via `hvcc` will have the following copyright text applied to the top of the file: `Copyright (c) 2018 Enzien Audio, Ltd.` This can be changed with `--copyright` parameter `$ hvcc ~/myProject/_main.pd -o ~/Desktop/somewhere/else/ -n mySynth --copyright "Copyright (c) Los Pollos Hermanos 2019"` ### `--help` Displays all the available parameters and options for hvcc. ## Contact There are several places where heavy/hvcc conversation is happening: * [Discord](https://discord.gg/fmxJveg) * [IRC](https://web.libera.chat/#hvcc) * A number of forums: * [Bela](https://forum.bela.io/?q=hvcc) * [Rebel Technology](https://community.rebeltech.org/tags/puredata) * [Daisy](https://forum.electro-smith.com/c/integrations/pure-data/32) * [MOD](https://forum.moddevices.com/c/developers/pure-data/56) Or you can use the [discussions](https://github.com/Wasted-Audio/hvcc/discussions) tab of this repository