aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS8
-rw-r--r--COPYING674
-rw-r--r--INSTALL35
-rw-r--r--README3
-rw-r--r--blip.lv2/adsr.ttl89
-rw-r--r--blip.lv2/adsr_gt.ttl95
-rw-r--r--blip.lv2/amp.ttl47
-rw-r--r--blip.lv2/branch.ttl47
-rw-r--r--blip.lv2/dahdsr.ttl115
-rw-r--r--blip.lv2/difference.ttl47
-rw-r--r--blip.lv2/fmod.ttl52
-rw-r--r--blip.lv2/interpolator.ttl38
-rw-r--r--blip.lv2/lp4pole.ttl63
-rw-r--r--blip.lv2/manifest.ttl.in138
-rw-r--r--blip.lv2/product.ttl46
-rw-r--r--blip.lv2/pulse.ttl56
-rw-r--r--blip.lv2/quantiser_100.ttl819
-rw-r--r--blip.lv2/quantiser_20.ttl259
-rw-r--r--blip.lv2/quantiser_50.ttl469
-rw-r--r--blip.lv2/random.ttl59
-rw-r--r--blip.lv2/ratio.ttl48
-rw-r--r--blip.lv2/sawtooth.ttl43
-rw-r--r--blip.lv2/sequencer_16.ttl191
-rw-r--r--blip.lv2/sequencer_32.ttl303
-rw-r--r--blip.lv2/sequencer_64.ttl527
-rw-r--r--blip.lv2/square.ttl43
-rw-r--r--blip.lv2/sum.ttl46
-rw-r--r--blip.lv2/sync_pulse.ttl59
-rw-r--r--blip.lv2/sync_square.ttl52
-rw-r--r--blip.lv2/tracker.ttl115
-rw-r--r--blip.lv2/triangle.ttl57
-rw-r--r--src/adsr.c256
-rw-r--r--src/adsr_gt.c264
-rw-r--r--src/amp.c142
-rw-r--r--src/branch.c133
-rw-r--r--src/dahdsr.c685
-rw-r--r--src/difference.c180
-rw-r--r--src/fmod.c192
-rw-r--r--src/include/common.h54
-rw-r--r--src/include/interpolate.h75
-rw-r--r--src/include/lp4pole_filter.h137
-rw-r--r--src/include/math_func.h36
-rw-r--r--src/include/wavedata.h192
-rw-r--r--src/include/wdatutil.h141
-rw-r--r--src/interpolator.c142
-rw-r--r--src/lp4pole.c182
-rw-r--r--src/lp4pole_filter.c55
-rw-r--r--src/product.c156
-rw-r--r--src/pulse.c288
-rw-r--r--src/quantiser.c474
-rw-r--r--src/random.c348
-rw-r--r--src/ratio.c189
-rw-r--r--src/sawtooth.c171
-rw-r--r--src/sequencer.c193
-rw-r--r--src/square.c172
-rw-r--r--src/sum.c156
-rw-r--r--src/sync_pulse.c205
-rw-r--r--src/sync_square.c193
-rw-r--r--src/tracker.c229
-rw-r--r--src/triangle.c307
-rw-r--r--src/wavedata.c141
-rw-r--r--src/wavegen.c319
-rw-r--r--src/wdatutil.c672
-rwxr-xr-xwafbin0 -> 89530 bytes
-rw-r--r--wscript126
65 files changed, 11848 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..0a786aa
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,8 @@
+Blop LADSPA plugins:
+
+Mike Rawes <mike_rawes@yahoo.co.uk>
+
+
+LV2 Port:
+
+David Robillard <d@drobilla.net> \ No newline at end of file
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..f6e4dd4
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,35 @@
+This software requires only Python to build.
+
+Like an auto* project, building has three phases:
+
+
+* Configure: ./waf configure [OPTIONS]
+
+ Example:
+ ./waf configure --prefix=/some/where --debug --strict
+
+ If --debug is not given, the flags from the environment variables
+ CFLAGS and CXXFLAGS will be used.
+
+ The default prefix is /usr/local
+
+
+* Build: ./waf [OPTIONS]
+
+ Example:
+ ./waf -j4
+
+
+* Install: ./waf install [OPTIONS]
+
+ The environment variable DESTDIR can be used to add any prefix to
+ the install paths (useful for packaging). Example:
+
+ DESTDIR=/home/drobilla/packages ./waf install
+
+
+*** IMPORTANT: You must use absolute paths everywhere
+
+
+Run './waf --help' for detailed option information.
+
diff --git a/README b/README
new file mode 100644
index 0000000..1120dd7
--- /dev/null
+++ b/README
@@ -0,0 +1,3 @@
+An LV2 port of the "blop" collection of LADSPA plugins.
+
+This port is based on blop-0.2.8.
diff --git a/blip.lv2/adsr.ttl b/blip.lv2/adsr.ttl
new file mode 100644
index 0000000..48e2189
--- /dev/null
+++ b/blip.lv2/adsr.ttl
@@ -0,0 +1,89 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:adsr
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Driving Signal" ;
+ lv2:symbol "port0" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Trigger Threshold" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 2 ;
+ lv2:minimum 0 ;
+ lv2:name "Attack Time (s)" ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 3 ;
+ lv2:minimum 0 ;
+ lv2:name "Decay Time (s)" ;
+ lv2:symbol "port3" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 1 ;
+ lv2:index 4 ;
+ lv2:maximum 1 ;
+ lv2:minimum 0 ;
+ lv2:name "Sustain Level" ;
+ lv2:symbol "port4" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 5 ;
+ lv2:minimum 0 ;
+ lv2:name "Release Time (s)" ;
+ lv2:symbol "port5" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 6 ;
+ lv2:name "Envelope Out" ;
+ lv2:symbol "port6" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1653> ;
+ dc:rights "GPL" ;
+ doap:name "ADSR Envelope" ;
+ lv2:documentation """
+<p>Generates an ADSR (Attack, Decay, Sustain and Release) envelope.</p>
+
+<p>Driven by a gate signal - if the level of the signal goes higher than the
+Trigger Threshold, the attack stage begins, proceeds to the decay stage and
+then holds at the sustain level. The release stage begins when the gate falls
+below this theshold - even if the previous stages have not completed.</p>
+
+<p>The output is a signal between 0.0 (rest) and 1.0 (peak) and the transitions
+are linear.</p>
+""" ;
+ a lv2:Plugin .
diff --git a/blip.lv2/adsr_gt.ttl b/blip.lv2/adsr_gt.ttl
new file mode 100644
index 0000000..6507897
--- /dev/null
+++ b/blip.lv2/adsr_gt.ttl
@@ -0,0 +1,95 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:adsr_gt
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Gate" ;
+ lv2:symbol "port0" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Trigger" ;
+ lv2:symbol "port1" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 2 ;
+ lv2:minimum 0 ;
+ lv2:name "Attack Time (s)" ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 3 ;
+ lv2:minimum 0 ;
+ lv2:name "Decay Time (s)" ;
+ lv2:symbol "port3" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 1 ;
+ lv2:index 4 ;
+ lv2:maximum 1 ;
+ lv2:minimum 0 ;
+ lv2:name "Sustain Level" ;
+ lv2:symbol "port4" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 5 ;
+ lv2:minimum 0 ;
+ lv2:name "Release Time (s)" ;
+ lv2:symbol "port5" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 6 ;
+ lv2:name "Envelope Out" ;
+ lv2:symbol "port6" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1680> ;
+ dc:rights "GPL" ;
+ doap:name "ADSR Envelope with Gate and Trigger" ;
+ lv2:documentation """
+<p>Generates an ADSR (Attack, Decay, Sustain and Release)
+envelope.</p>
+
+<p>Does the same thing as the other ADSR (1658) above, except the
+Trigger Threshold is fixed at zero, and the additional Trigger
+input allows retriggering whilst the gate is still high.</p>
+
+<p>The reasoning behind this design is to remove the need for a keyboard player
+to release a key before pressing another when using with a monosynth. <a
+href="http://www.sospubs.co.uk/sos/nov99/articles/synthsecrets.htm">The
+&lsquo;Synth Secrets&rsquo; article in the November 1999 issue of &lsquo;Sound
+on Sound&rsquo;</a> explains this in detail.</p>
+
+<p>The output is a signal between 0.0 (rest) and 1.0 (peak) and the
+transitions are linear.</p>
+""" ;
+ a lv2:Plugin .
diff --git a/blip.lv2/amp.ttl b/blip.lv2/amp.ttl
new file mode 100644
index 0000000..385008f
--- /dev/null
+++ b/blip.lv2/amp.ttl
@@ -0,0 +1,47 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:amp
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:maximum 96 ;
+ lv2:minimum -96 ;
+ lv2:name "Gain (dB)" ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Input" ;
+ lv2:symbol "port1" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Output" ;
+ lv2:symbol "port2" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1654> ,
+ <urn:ladspa:1655> ;
+ dc:rights "GPL" ;
+ doap:name "Amplifier" ;
+ lv2:documentation """
+<p>A simple monophonic amplifier.</p>
+""" ;
+ a lv2:Plugin , lv2:AmplifierPlugin .
diff --git a/blip.lv2/branch.ttl b/blip.lv2/branch.ttl
new file mode 100644
index 0000000..69ec27a
--- /dev/null
+++ b/blip.lv2/branch.ttl
@@ -0,0 +1,47 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:branch
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Input" ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "First Output" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Second Output" ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1673> ,
+ <urn:ladspa:1674> ;
+ dc:rights "GPL" ;
+ doap:name "Signal Branch" ;
+ lv2:documentation """
+<p>Splits an input signal into two identical signals. Somewhat redundant, as
+most modular synth hosts allow you to connect an output to more than one input.
+If your host of choice does not allow this, this plugin will do the job...</p>
+""" ;
+ a lv2:Plugin , lv2:UtilityPlugin .
diff --git a/blip.lv2/dahdsr.ttl b/blip.lv2/dahdsr.ttl
new file mode 100644
index 0000000..3252a75
--- /dev/null
+++ b/blip.lv2/dahdsr.ttl
@@ -0,0 +1,115 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:dahdsr
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Gate" ;
+ lv2:symbol "port0" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Trigger" ;
+ lv2:symbol "port1" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 2 ;
+ lv2:minimum 0 ;
+ lv2:name "Delay Time (s)" ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 3 ;
+ lv2:minimum 0 ;
+ lv2:name "Attack Time (s)" ;
+ lv2:symbol "port3" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 4 ;
+ lv2:minimum 0 ;
+ lv2:name "Hold Time (s)" ;
+ lv2:symbol "port4" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 5 ;
+ lv2:minimum 0 ;
+ lv2:name "Decay Time (s)" ;
+ lv2:symbol "port5" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 1 ;
+ lv2:index 6 ;
+ lv2:maximum 1 ;
+ lv2:minimum 0 ;
+ lv2:name "Sustain Level" ;
+ lv2:symbol "port6" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 7 ;
+ lv2:minimum 0 ;
+ lv2:name "Release Time (s)" ;
+ lv2:symbol "port7" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 8 ;
+ lv2:name "Envelope Out" ;
+ lv2:symbol "port8" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:2021> ,
+ <urn:ladspa:2022> ,
+ <urn:ladspa:2038> ;
+ dc:rights "GPL" ;
+ doap:name "DAHDSR Envelope with Gate and Trigger" ;
+ lv2:documentation """
+<p>Generates a DAHDSR (Delay, Attack, Hold, Decay, Sustain, Release)
+envelope.</p>
+
+<p>Another envelope generator, this time with two additional stages - Delay,
+which delays the onset of the Attack stage, and Hold, which holds the output at
+maximum before the Decay stage begins.</p>
+
+<p>Triggering works in subtly different ways to the <a href="#adsr_gnt">ADSR
+(1680)</a> - the Trigger will restart the envelope even if the Gate is closed -
+the effect of this is to proceed through the stages and begin the release stage
+immediately after the decay stage.</p>
+
+<p>The final variant (ID 2038) uses control-rate gate and trigger, which is a
+little less CPU hungry, but will cause timing errors that are dependent on the
+block size being used by the host.</p>
+""" ;
+ a lv2:Plugin .
diff --git a/blip.lv2/difference.ttl b/blip.lv2/difference.ttl
new file mode 100644
index 0000000..69c8252
--- /dev/null
+++ b/blip.lv2/difference.ttl
@@ -0,0 +1,47 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:difference
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Input" ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Input to Subtract" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Difference Output" ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:2030> ,
+ <urn:ladspa:2031> ,
+ <urn:ladspa:2032> ,
+ <urn:ladspa:2033> ;
+ dc:rights "GPL" ;
+ doap:name "Signal Difference" ;
+ lv2:documentation """
+<p>Subtract two signals.</p>
+""" ;
+ a lv2:Plugin , lv2:UtilityPlugin .
diff --git a/blip.lv2/fmod.ttl b/blip.lv2/fmod.ttl
new file mode 100644
index 0000000..6bcf033
--- /dev/null
+++ b/blip.lv2/fmod.ttl
@@ -0,0 +1,52 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:fmod
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:maximum 0.5 ;
+ lv2:minimum "2.08333e-05"^^xsd:double ;
+ lv2:name "Frequency (Hz)" ;
+ lv2:portProperty <http://lv2plug.in/ns/dev/extportinfo#logarithmic> ,
+ lv2:sampleRate ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Modulation (Octaves)" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Modulated Frequency (Hz)" ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1656> ,
+ <urn:ladspa:1657> ,
+ <urn:ladspa:1658> ,
+ <urn:ladspa:1659> ;
+ dc:rights "GPL" ;
+ doap:name "Frequency Modulator" ;
+ lv2:documentation """
+<p>Modulates an input frequency by a driving signal, transposing the frequency
+by &#177;1 Octave per unit amplitude of signal.</p>
+""" ;
+ a lv2:Plugin , lv2:SpectralPlugin .
diff --git a/blip.lv2/interpolator.ttl b/blip.lv2/interpolator.ttl
new file mode 100644
index 0000000..45cc987
--- /dev/null
+++ b/blip.lv2/interpolator.ttl
@@ -0,0 +1,38 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:interpolator
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Control Input" ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Interpolated Output" ;
+ lv2:symbol "port1" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1660> ;
+ dc:rights "GPL" ;
+ doap:name "Control to Audio Interpolator" ;
+ lv2:documentation """
+<p>Interpolates a control-rate (per-block) signal into a smooth audio
+(per-sample) signal.</p>
+""" ;
+ a lv2:Plugin , lv2:UtilityPlugin .
diff --git a/blip.lv2/lp4pole.ttl b/blip.lv2/lp4pole.ttl
new file mode 100644
index 0000000..4d90d5c
--- /dev/null
+++ b/blip.lv2/lp4pole.ttl
@@ -0,0 +1,63 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:lp4pole
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:default 0.5 ;
+ lv2:index 0 ;
+ lv2:maximum 0.5 ;
+ lv2:minimum "2.08333e-05"^^xsd:double ;
+ lv2:name "Cutoff Frequency" ;
+ lv2:portProperty <http://lv2plug.in/ns/dev/extportinfo#logarithmic> ,
+ lv2:sampleRate ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 1 ;
+ lv2:maximum 4 ;
+ lv2:minimum 0 ;
+ lv2:name "Resonance" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Input" ;
+ lv2:symbol "port2" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 3 ;
+ lv2:name "Output" ;
+ lv2:symbol "port3" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1671> ,
+ <urn:ladspa:1672> ;
+ dc:rights "GPL" ;
+ doap:name "4 Pole Resonant Low-Pass Filter" ;
+ lv2:documentation """
+<p>Emulates a low pass filter in popular analogue synthesisers. This particular
+filter is derived from one of <a
+href="http://www.musicdsp.org/archive.php?classid=3#24">many
+implementations</a> of the Moog 4 pole filter.</p>
+""" ;
+ a lv2:Plugin , lv2:LowpassPlugin .
diff --git a/blip.lv2/manifest.ttl.in b/blip.lv2/manifest.ttl.in
new file mode 100644
index 0000000..e1ceab7
--- /dev/null
+++ b/blip.lv2/manifest.ttl.in
@@ -0,0 +1,138 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:adsr
+ a lv2:Plugin ;
+ rdfs:seeAlso <adsr.ttl> ;
+ lv2:binary <adsr@LIB_EXT@> .
+
+blip:adsr_gt
+ a lv2:Plugin ;
+ rdfs:seeAlso <adsr_gt.ttl> ;
+ lv2:binary <adsr_gt@LIB_EXT@> .
+
+blip:amp
+ a lv2:Plugin ;
+ rdfs:seeAlso <amp.ttl> ;
+ lv2:binary <amp@LIB_EXT@> .
+
+blip:branch
+ a lv2:Plugin ;
+ rdfs:seeAlso <branch.ttl> ;
+ lv2:binary <branch@LIB_EXT@> .
+
+blip:dahdsr
+ a lv2:Plugin ;
+ rdfs:seeAlso <dahdsr.ttl> ;
+ lv2:binary <dahdsr@LIB_EXT@> .
+
+blip:difference
+ a lv2:Plugin ;
+ rdfs:seeAlso <difference.ttl> ;
+ lv2:binary <difference@LIB_EXT@> .
+
+blip:fmod
+ a lv2:Plugin ;
+ rdfs:seeAlso <fmod.ttl> ;
+ lv2:binary <fmod@LIB_EXT@> .
+
+blip:interpolator
+ a lv2:Plugin ;
+ rdfs:seeAlso <interpolator.ttl> ;
+ lv2:binary <interpolator@LIB_EXT@> .
+
+blip:lp4pole
+ a lv2:Plugin ;
+ rdfs:seeAlso <lp4pole.ttl> ;
+ lv2:binary <lp4pole@LIB_EXT@> .
+
+blip:product
+ a lv2:Plugin ;
+ rdfs:seeAlso <product.ttl> ;
+ lv2:binary <product@LIB_EXT@> .
+
+blip:pulse
+ a lv2:Plugin ;
+ rdfs:seeAlso <pulse.ttl> ;
+ lv2:binary <pulse@LIB_EXT@> .
+
+blip:quantiser_20
+ a lv2:Plugin ;
+ rdfs:seeAlso <quantiser_20.ttl> ;
+ lv2:binary <quantiser_20@LIB_EXT@> .
+
+blip:quantiser_50
+ a lv2:Plugin ;
+ rdfs:seeAlso <quantiser_50.ttl> ;
+ lv2:binary <quantiser_50@LIB_EXT@> .
+
+blip:quantiser_100
+ a lv2:Plugin ;
+ rdfs:seeAlso <quantiser_100.ttl> ;
+ lv2:binary <quantiser_100@LIB_EXT@> .
+
+blip:random
+ a lv2:Plugin ;
+ rdfs:seeAlso <random.ttl> ;
+ lv2:binary <random@LIB_EXT@> .
+
+blip:ratio
+ a lv2:Plugin ;
+ rdfs:seeAlso <ratio.ttl> ;
+ lv2:binary <ratio@LIB_EXT@> .
+
+blip:sawtooth
+ a lv2:Plugin ;
+ rdfs:seeAlso <sawtooth.ttl> ;
+ lv2:binary <sawtooth@LIB_EXT@> .
+
+blip:sequencer_16
+ a lv2:Plugin ;
+ rdfs:seeAlso <sequencer_16.ttl> ;
+ lv2:binary <sequencer_16@LIB_EXT@> .
+
+blip:sequencer_32
+ a lv2:Plugin ;
+ rdfs:seeAlso <sequencer_32.ttl> ;
+ lv2:binary <sequencer_32@LIB_EXT@> .
+
+blip:sequencer_64
+ a lv2:Plugin ;
+ rdfs:seeAlso <sequencer_64.ttl> ;
+ lv2:binary <sequencer_64@LIB_EXT@> .
+
+blip:square
+ a lv2:Plugin ;
+ rdfs:seeAlso <square.ttl> ;
+ lv2:binary <square@LIB_EXT@> .
+
+blip:sum
+ a lv2:Plugin ;
+ rdfs:seeAlso <sum.ttl> ;
+ lv2:binary <sum@LIB_EXT@> .
+
+blip:sync_pulse
+ a lv2:Plugin ;
+ rdfs:seeAlso <sync_pulse.ttl> ;
+ lv2:binary <sync_pulse@LIB_EXT@> .
+
+blip:sync_square
+ a lv2:Plugin ;
+ rdfs:seeAlso <sync_square.ttl> ;
+ lv2:binary <sync_square@LIB_EXT@> .
+
+blip:tracker
+ a lv2:Plugin ;
+ rdfs:seeAlso <tracker.ttl> ;
+ lv2:binary <tracker@LIB_EXT@> .
+
+blip:triangle
+ a lv2:Plugin ;
+ rdfs:seeAlso <triangle.ttl> ;
+ lv2:binary <triangle@LIB_EXT@> .
diff --git a/blip.lv2/product.ttl b/blip.lv2/product.ttl
new file mode 100644
index 0000000..ee00258
--- /dev/null
+++ b/blip.lv2/product.ttl
@@ -0,0 +1,46 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:product
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "First Input" ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Second Input" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Product Output" ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1668> ,
+ <urn:ladspa:1669> ,
+ <urn:ladspa:1670> ;
+ dc:rights "GPL" ;
+ doap:name "Signal Product" ;
+ lv2:documentation """
+<p>Multiply two signals.</p>
+""" ;
+ a lv2:Plugin , lv2:UtilityPlugin .
diff --git a/blip.lv2/pulse.ttl b/blip.lv2/pulse.ttl
new file mode 100644
index 0000000..0330ab2
--- /dev/null
+++ b/blip.lv2/pulse.ttl
@@ -0,0 +1,56 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:pulse
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:maximum 0.5 ;
+ lv2:minimum 0.000001 ;
+ lv2:default 440.0 ;
+ lv2:name "Frequency" ;
+ lv2:portProperty <http://lv2plug.in/ns/dev/extportinfo#logarithmic> ,
+ lv2:sampleRate ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0.5 ;
+ lv2:index 1 ;
+ lv2:maximum 1 ;
+ lv2:minimum 0 ;
+ lv2:name "Pulse Width" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Output" ;
+ lv2:symbol "port2" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1645> ,
+ <urn:ladspa:1646> ,
+ <urn:ladspa:1647> ,
+ <urn:ladspa:1648> ;
+ dc:rights "GPL" ;
+ doap:name "Variable Width Pulse Oscillator" ;
+ lv2:documentation """
+<p>Generates an alias-free pulse wave at given input frequency and pulse width
+(duty).</p>
+""" ;
+ a lv2:Plugin , lv2:OscillatorPlugin .
diff --git a/blip.lv2/quantiser_100.ttl b/blip.lv2/quantiser_100.ttl
new file mode 100644
index 0000000..ca3ee84
--- /dev/null
+++ b/blip.lv2/quantiser_100.ttl
@@ -0,0 +1,819 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:quantiser_100
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Quantise Range Minimum" ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Quantise Range Maximum" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 10 ;
+ lv2:name "Value 5" ;
+ lv2:symbol "port10" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 100 ;
+ lv2:name "Value 95" ;
+ lv2:symbol "port100" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 101 ;
+ lv2:name "Value 96" ;
+ lv2:symbol "port101" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 102 ;
+ lv2:name "Value 97" ;
+ lv2:symbol "port102" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 103 ;
+ lv2:name "Value 98" ;
+ lv2:symbol "port103" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 104 ;
+ lv2:name "Value 99" ;
+ lv2:symbol "port104" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 105 ;
+ lv2:name "Input" ;
+ lv2:symbol "port105" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 106 ;
+ lv2:name "Quantised Output" ;
+ lv2:symbol "port106" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 107 ;
+ lv2:name "Output Changed" ;
+ lv2:symbol "port107" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 11 ;
+ lv2:name "Value 6" ;
+ lv2:symbol "port11" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 12 ;
+ lv2:name "Value 7" ;
+ lv2:symbol "port12" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 13 ;
+ lv2:name "Value 8" ;
+ lv2:symbol "port13" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 14 ;
+ lv2:name "Value 9" ;
+ lv2:symbol "port14" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 15 ;
+ lv2:name "Value 10" ;
+ lv2:symbol "port15" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 16 ;
+ lv2:name "Value 11" ;
+ lv2:symbol "port16" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 17 ;
+ lv2:name "Value 12" ;
+ lv2:symbol "port17" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 18 ;
+ lv2:name "Value 13" ;
+ lv2:symbol "port18" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 19 ;
+ lv2:name "Value 14" ;
+ lv2:symbol "port19" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 2 ;
+ lv2:minimum 0 ;
+ lv2:name "Match Range" ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 20 ;
+ lv2:name "Value 15" ;
+ lv2:symbol "port20" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 21 ;
+ lv2:name "Value 16" ;
+ lv2:symbol "port21" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 22 ;
+ lv2:name "Value 17" ;
+ lv2:symbol "port22" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 23 ;
+ lv2:name "Value 18" ;
+ lv2:symbol "port23" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 24 ;
+ lv2:name "Value 19" ;
+ lv2:symbol "port24" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 25 ;
+ lv2:name "Value 20" ;
+ lv2:symbol "port25" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 26 ;
+ lv2:name "Value 21" ;
+ lv2:symbol "port26" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 27 ;
+ lv2:name "Value 22" ;
+ lv2:symbol "port27" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 28 ;
+ lv2:name "Value 23" ;
+ lv2:symbol "port28" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 29 ;
+ lv2:name "Value 24" ;
+ lv2:symbol "port29" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 3 ;
+ lv2:maximum 2 ;
+ lv2:minimum 0 ;
+ lv2:name "Mode (0 = Extend, 1 = Wrap, 2 = Clip)" ;
+ lv2:portProperty lv2:integer ;
+ lv2:symbol "port3" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 30 ;
+ lv2:name "Value 25" ;
+ lv2:symbol "port30" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 31 ;
+ lv2:name "Value 26" ;
+ lv2:symbol "port31" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 32 ;
+ lv2:name "Value 27" ;
+ lv2:symbol "port32" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 33 ;
+ lv2:name "Value 28" ;
+ lv2:symbol "port33" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 34 ;
+ lv2:name "Value 29" ;
+ lv2:symbol "port34" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 35 ;
+ lv2:name "Value 30" ;
+ lv2:symbol "port35" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 36 ;
+ lv2:name "Value 31" ;
+ lv2:symbol "port36" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 37 ;
+ lv2:name "Value 32" ;
+ lv2:symbol "port37" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 38 ;
+ lv2:name "Value 33" ;
+ lv2:symbol "port38" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 39 ;
+ lv2:name "Value 34" ;
+ lv2:symbol "port39" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 100 ;
+ lv2:index 4 ;
+ lv2:maximum 100 ;
+ lv2:minimum 1 ;
+ lv2:name "Steps (1 - 100)" ;
+ lv2:portProperty lv2:integer ;
+ lv2:symbol "port4" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 40 ;
+ lv2:name "Value 35" ;
+ lv2:symbol "port40" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 41 ;
+ lv2:name "Value 36" ;
+ lv2:symbol "port41" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 42 ;
+ lv2:name "Value 37" ;
+ lv2:symbol "port42" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 43 ;
+ lv2:name "Value 38" ;
+ lv2:symbol "port43" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 44 ;
+ lv2:name "Value 39" ;
+ lv2:symbol "port44" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 45 ;
+ lv2:name "Value 40" ;
+ lv2:symbol "port45" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 46 ;
+ lv2:name "Value 41" ;
+ lv2:symbol "port46" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 47 ;
+ lv2:name "Value 42" ;
+ lv2:symbol "port47" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 48 ;
+ lv2:name "Value 43" ;
+ lv2:symbol "port48" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 49 ;
+ lv2:name "Value 44" ;
+ lv2:symbol "port49" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 5 ;
+ lv2:name "Value 0" ;
+ lv2:symbol "port5" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 50 ;
+ lv2:name "Value 45" ;
+ lv2:symbol "port50" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 51 ;
+ lv2:name "Value 46" ;
+ lv2:symbol "port51" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 52 ;
+ lv2:name "Value 47" ;
+ lv2:symbol "port52" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 53 ;
+ lv2:name "Value 48" ;
+ lv2:symbol "port53" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 54 ;
+ lv2:name "Value 49" ;
+ lv2:symbol "port54" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 55 ;
+ lv2:name "Value 50" ;
+ lv2:symbol "port55" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 56 ;
+ lv2:name "Value 51" ;
+ lv2:symbol "port56" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 57 ;
+ lv2:name "Value 52" ;
+ lv2:symbol "port57" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 58 ;
+ lv2:name "Value 53" ;
+ lv2:symbol "port58" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 59 ;
+ lv2:name "Value 54" ;
+ lv2:symbol "port59" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 6 ;
+ lv2:name "Value 1" ;
+ lv2:symbol "port6" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 60 ;
+ lv2:name "Value 55" ;
+ lv2:symbol "port60" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 61 ;
+ lv2:name "Value 56" ;
+ lv2:symbol "port61" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 62 ;
+ lv2:name "Value 57" ;
+ lv2:symbol "port62" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 63 ;
+ lv2:name "Value 58" ;
+ lv2:symbol "port63" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 64 ;
+ lv2:name "Value 59" ;
+ lv2:symbol "port64" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 65 ;
+ lv2:name "Value 60" ;
+ lv2:symbol "port65" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 66 ;
+ lv2:name "Value 61" ;
+ lv2:symbol "port66" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 67 ;
+ lv2:name "Value 62" ;
+ lv2:symbol "port67" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 68 ;
+ lv2:name "Value 63" ;
+ lv2:symbol "port68" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 69 ;
+ lv2:name "Value 64" ;
+ lv2:symbol "port69" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 7 ;
+ lv2:name "Value 2" ;
+ lv2:symbol "port7" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 70 ;
+ lv2:name "Value 65" ;
+ lv2:symbol "port70" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 71 ;
+ lv2:name "Value 66" ;
+ lv2:symbol "port71" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 72 ;
+ lv2:name "Value 67" ;
+ lv2:symbol "port72" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 73 ;
+ lv2:name "Value 68" ;
+ lv2:symbol "port73" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 74 ;
+ lv2:name "Value 69" ;
+ lv2:symbol "port74" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 75 ;
+ lv2:name "Value 70" ;
+ lv2:symbol "port75" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 76 ;
+ lv2:name "Value 71" ;
+ lv2:symbol "port76" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 77 ;
+ lv2:name "Value 72" ;
+ lv2:symbol "port77" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 78 ;
+ lv2:name "Value 73" ;
+ lv2:symbol "port78" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 79 ;
+ lv2:name "Value 74" ;
+ lv2:symbol "port79" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 8 ;
+ lv2:name "Value 3" ;
+ lv2:symbol "port8" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 80 ;
+ lv2:name "Value 75" ;
+ lv2:symbol "port80" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 81 ;
+ lv2:name "Value 76" ;
+ lv2:symbol "port81" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 82 ;
+ lv2:name "Value 77" ;
+ lv2:symbol "port82" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 83 ;
+ lv2:name "Value 78" ;
+ lv2:symbol "port83" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 84 ;
+ lv2:name "Value 79" ;
+ lv2:symbol "port84" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 85 ;
+ lv2:name "Value 80" ;
+ lv2:symbol "port85" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 86 ;
+ lv2:name "Value 81" ;
+ lv2:symbol "port86" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 87 ;
+ lv2:name "Value 82" ;
+ lv2:symbol "port87" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 88 ;
+ lv2:name "Value 83" ;
+ lv2:symbol "port88" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 89 ;
+ lv2:name "Value 84" ;
+ lv2:symbol "port89" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 9 ;
+ lv2:name "Value 4" ;
+ lv2:symbol "port9" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 90 ;
+ lv2:name "Value 85" ;
+ lv2:symbol "port90" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 91 ;
+ lv2:name "Value 86" ;
+ lv2:symbol "port91" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 92 ;
+ lv2:name "Value 87" ;
+ lv2:symbol "port92" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 93 ;
+ lv2:name "Value 88" ;
+ lv2:symbol "port93" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 94 ;
+ lv2:name "Value 89" ;
+ lv2:symbol "port94" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 95 ;
+ lv2:name "Value 90" ;
+ lv2:symbol "port95" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 96 ;
+ lv2:name "Value 91" ;
+ lv2:symbol "port96" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 97 ;
+ lv2:name "Value 92" ;
+ lv2:symbol "port97" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 98 ;
+ lv2:name "Value 93" ;
+ lv2:symbol "port98" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 99 ;
+ lv2:name "Value 94" ;
+ lv2:symbol "port99" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:2029> ;
+ dc:rights "GPL" ;
+ doap:name "Quantiser (100 Steps)" ;
+ lv2:documentation """
+<p>Quantises a signal to a set of arbitrary values within a range.</p>
+
+<p>Match Range determines the distance from the quantised value that the input
+can deviate before being altered. This allows small variations in input to get
+through unmolested. If it is set to 0 the input is quantised to the nearest
+exact match.</p>
+
+<p>Mode is one of Extend (0), Wrap (1) or Clip (2).</p>
+
+<p>Steps is the number of quantisation steps to use (up to a maximum of
+100).</p>
+
+<p>For example, given the following settings:</p>
+<ul>
+ <li>Range Minimum = 0.0</li>
+ <li>Range Maximum = 12.0</li>
+ <li>Match Range = 0.0</li>
+ <li>Steps = 4</li>
+ <li>Quantisation Values 3, 5, 7 and 10</li>
+</ul>
+
+<p>and an input that is a line from -24 to 24, the output will be:</p>
+<ul>
+ <li>Extend: -26, -21, -19, -17, -14, -9, -7, -5, -2, 3, 5, 7, 10, 15, 17, 19,
+ 22</li>
+ <li>Wrap: 10, 3, 5, 7, 10, 3, 5, 7, 10, 3, 5, 7, 10, 3, 5, 7, 10</li>
+ <li>Clip: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 7, 10, 10, 10, 10, 10</li>
+</ul>
+
+<p>The quantisation values should all be within the range minimum and maximum
+for it to work!</p>
+""" ;
+ a lv2:Plugin .
diff --git a/blip.lv2/quantiser_20.ttl b/blip.lv2/quantiser_20.ttl
new file mode 100644
index 0000000..5bded34
--- /dev/null
+++ b/blip.lv2/quantiser_20.ttl
@@ -0,0 +1,259 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:quantiser_20
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Quantise Range Minimum" ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Quantise Range Maximum" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 10 ;
+ lv2:name "Value 5" ;
+ lv2:symbol "port10" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 11 ;
+ lv2:name "Value 6" ;
+ lv2:symbol "port11" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 12 ;
+ lv2:name "Value 7" ;
+ lv2:symbol "port12" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 13 ;
+ lv2:name "Value 8" ;
+ lv2:symbol "port13" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 14 ;
+ lv2:name "Value 9" ;
+ lv2:symbol "port14" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 15 ;
+ lv2:name "Value 10" ;
+ lv2:symbol "port15" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 16 ;
+ lv2:name "Value 11" ;
+ lv2:symbol "port16" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 17 ;
+ lv2:name "Value 12" ;
+ lv2:symbol "port17" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 18 ;
+ lv2:name "Value 13" ;
+ lv2:symbol "port18" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 19 ;
+ lv2:name "Value 14" ;
+ lv2:symbol "port19" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 2 ;
+ lv2:minimum 0 ;
+ lv2:name "Match Range" ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 20 ;
+ lv2:name "Value 15" ;
+ lv2:symbol "port20" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 21 ;
+ lv2:name "Value 16" ;
+ lv2:symbol "port21" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 22 ;
+ lv2:name "Value 17" ;
+ lv2:symbol "port22" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 23 ;
+ lv2:name "Value 18" ;
+ lv2:symbol "port23" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 24 ;
+ lv2:name "Value 19" ;
+ lv2:symbol "port24" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 25 ;
+ lv2:name "Input" ;
+ lv2:symbol "port25" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 26 ;
+ lv2:name "Quantised Output" ;
+ lv2:symbol "port26" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 27 ;
+ lv2:name "Output Changed" ;
+ lv2:symbol "port27" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 3 ;
+ lv2:maximum 2 ;
+ lv2:minimum 0 ;
+ lv2:name "Mode (0 = Extend, 1 = Wrap, 2 = Clip)" ;
+ lv2:portProperty lv2:integer ;
+ lv2:symbol "port3" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 20 ;
+ lv2:index 4 ;
+ lv2:maximum 20 ;
+ lv2:minimum 1 ;
+ lv2:name "Steps (1 - 20)" ;
+ lv2:portProperty lv2:integer ;
+ lv2:symbol "port4" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 5 ;
+ lv2:name "Value 0" ;
+ lv2:symbol "port5" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 6 ;
+ lv2:name "Value 1" ;
+ lv2:symbol "port6" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 7 ;
+ lv2:name "Value 2" ;
+ lv2:symbol "port7" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 8 ;
+ lv2:name "Value 3" ;
+ lv2:symbol "port8" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 9 ;
+ lv2:name "Value 4" ;
+ lv2:symbol "port9" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:2027> ;
+ dc:rights "GPL" ;
+ doap:name "Quantiser (20 Steps)" ;
+ lv2:documentation """
+<p>Quantises a signal to a set of arbitrary values within a range.</p>
+
+<p>Match Range determines the distance from the quantised value that the input
+can deviate before being altered. This allows small variations in input to get
+through unmolested. If it is set to 0 the input is quantised to the nearest
+exact match.</p>
+
+<p>Mode is one of Extend (0), Wrap (1) or Clip (2).</p>
+
+<p>Steps is the number of quantisation steps to use (up to a maximum of
+20).</p>
+
+<p>For example, given the following settings:</p>
+<ul>
+ <li>Range Minimum = 0.0</li>
+ <li>Range Maximum = 12.0</li>
+ <li>Match Range = 0.0</li>
+ <li>Steps = 4</li>
+ <li>Quantisation Values 3, 5, 7 and 10</li>
+</ul>
+
+<p>and an input that is a line from -24 to 24, the output will be:</p>
+<ul>
+ <li>Extend: -26, -21, -19, -17, -14, -9, -7, -5, -2, 3, 5, 7, 10, 15, 17, 19,
+ 22</li>
+ <li>Wrap: 10, 3, 5, 7, 10, 3, 5, 7, 10, 3, 5, 7, 10, 3, 5, 7, 10</li>
+ <li>Clip: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 7, 10, 10, 10, 10, 10</li>
+</ul>
+
+<p>The quantisation values should all be within the range minimum and maximum
+for it to work!</p>
+""" ;
+ a lv2:Plugin .
diff --git a/blip.lv2/quantiser_50.ttl b/blip.lv2/quantiser_50.ttl
new file mode 100644
index 0000000..223cb0e
--- /dev/null
+++ b/blip.lv2/quantiser_50.ttl
@@ -0,0 +1,469 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:quantiser_50
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Quantise Range Minimum" ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Quantise Range Maximum" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 10 ;
+ lv2:name "Value 5" ;
+ lv2:symbol "port10" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 11 ;
+ lv2:name "Value 6" ;
+ lv2:symbol "port11" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 12 ;
+ lv2:name "Value 7" ;
+ lv2:symbol "port12" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 13 ;
+ lv2:name "Value 8" ;
+ lv2:symbol "port13" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 14 ;
+ lv2:name "Value 9" ;
+ lv2:symbol "port14" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 15 ;
+ lv2:name "Value 10" ;
+ lv2:symbol "port15" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 16 ;
+ lv2:name "Value 11" ;
+ lv2:symbol "port16" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 17 ;
+ lv2:name "Value 12" ;
+ lv2:symbol "port17" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 18 ;
+ lv2:name "Value 13" ;
+ lv2:symbol "port18" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 19 ;
+ lv2:name "Value 14" ;
+ lv2:symbol "port19" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 2 ;
+ lv2:minimum 0 ;
+ lv2:name "Match Range" ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 20 ;
+ lv2:name "Value 15" ;
+ lv2:symbol "port20" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 21 ;
+ lv2:name "Value 16" ;
+ lv2:symbol "port21" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 22 ;
+ lv2:name "Value 17" ;
+ lv2:symbol "port22" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 23 ;
+ lv2:name "Value 18" ;
+ lv2:symbol "port23" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 24 ;
+ lv2:name "Value 19" ;
+ lv2:symbol "port24" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 25 ;
+ lv2:name "Value 20" ;
+ lv2:symbol "port25" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 26 ;
+ lv2:name "Value 21" ;
+ lv2:symbol "port26" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 27 ;
+ lv2:name "Value 22" ;
+ lv2:symbol "port27" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 28 ;
+ lv2:name "Value 23" ;
+ lv2:symbol "port28" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 29 ;
+ lv2:name "Value 24" ;
+ lv2:symbol "port29" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 3 ;
+ lv2:maximum 2 ;
+ lv2:minimum 0 ;
+ lv2:name "Mode (0 = Extend, 1 = Wrap, 2 = Clip)" ;
+ lv2:portProperty lv2:integer ;
+ lv2:symbol "port3" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 30 ;
+ lv2:name "Value 25" ;
+ lv2:symbol "port30" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 31 ;
+ lv2:name "Value 26" ;
+ lv2:symbol "port31" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 32 ;
+ lv2:name "Value 27" ;
+ lv2:symbol "port32" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 33 ;
+ lv2:name "Value 28" ;
+ lv2:symbol "port33" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 34 ;
+ lv2:name "Value 29" ;
+ lv2:symbol "port34" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 35 ;
+ lv2:name "Value 30" ;
+ lv2:symbol "port35" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 36 ;
+ lv2:name "Value 31" ;
+ lv2:symbol "port36" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 37 ;
+ lv2:name "Value 32" ;
+ lv2:symbol "port37" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 38 ;
+ lv2:name "Value 33" ;
+ lv2:symbol "port38" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 39 ;
+ lv2:name "Value 34" ;
+ lv2:symbol "port39" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 50 ;
+ lv2:index 4 ;
+ lv2:maximum 50 ;
+ lv2:minimum 1 ;
+ lv2:name "Steps (1 - 50)" ;
+ lv2:portProperty lv2:integer ;
+ lv2:symbol "port4" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 40 ;
+ lv2:name "Value 35" ;
+ lv2:symbol "port40" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 41 ;
+ lv2:name "Value 36" ;
+ lv2:symbol "port41" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 42 ;
+ lv2:name "Value 37" ;
+ lv2:symbol "port42" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 43 ;
+ lv2:name "Value 38" ;
+ lv2:symbol "port43" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 44 ;
+ lv2:name "Value 39" ;
+ lv2:symbol "port44" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 45 ;
+ lv2:name "Value 40" ;
+ lv2:symbol "port45" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 46 ;
+ lv2:name "Value 41" ;
+ lv2:symbol "port46" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 47 ;
+ lv2:name "Value 42" ;
+ lv2:symbol "port47" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 48 ;
+ lv2:name "Value 43" ;
+ lv2:symbol "port48" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 49 ;
+ lv2:name "Value 44" ;
+ lv2:symbol "port49" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 5 ;
+ lv2:name "Value 0" ;
+ lv2:symbol "port5" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 50 ;
+ lv2:name "Value 45" ;
+ lv2:symbol "port50" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 51 ;
+ lv2:name "Value 46" ;
+ lv2:symbol "port51" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 52 ;
+ lv2:name "Value 47" ;
+ lv2:symbol "port52" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 53 ;
+ lv2:name "Value 48" ;
+ lv2:symbol "port53" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 54 ;
+ lv2:name "Value 49" ;
+ lv2:symbol "port54" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 55 ;
+ lv2:name "Input" ;
+ lv2:symbol "port55" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 56 ;
+ lv2:name "Quantised Output" ;
+ lv2:symbol "port56" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 57 ;
+ lv2:name "Output Changed" ;
+ lv2:symbol "port57" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 6 ;
+ lv2:name "Value 1" ;
+ lv2:symbol "port6" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 7 ;
+ lv2:name "Value 2" ;
+ lv2:symbol "port7" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 8 ;
+ lv2:name "Value 3" ;
+ lv2:symbol "port8" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 9 ;
+ lv2:name "Value 4" ;
+ lv2:symbol "port9" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:2028> ;
+ dc:rights "GPL" ;
+ doap:name "Quantiser (50 Steps)" ;
+ lv2:documentation """
+<p>Quantises a signal to a set of arbitrary values within a range.</p>
+
+<p>Match Range determines the distance from the quantised value that the input
+can deviate before being altered. This allows small variations in input to get
+through unmolested. If it is set to 0 the input is quantised to the nearest
+exact match.</p>
+
+<p>Mode is one of Extend (0), Wrap (1) or Clip (2).</p>
+
+<p>Steps is the number of quantisation steps to use (up to a maximum of
+50).</p>
+
+<p>For example, given the following settings:</p>
+<ul>
+ <li>Range Minimum = 0.0</li>
+ <li>Range Maximum = 12.0</li>
+ <li>Match Range = 0.0</li>
+ <li>Steps = 4</li>
+ <li>Quantisation Values 3, 5, 7 and 10</li>
+</ul>
+
+<p>and an input that is a line from -24 to 24, the output will be:</p>
+<ul>
+ <li>Extend: -26, -21, -19, -17, -14, -9, -7, -5, -2, 3, 5, 7, 10, 15, 17, 19,
+ 22</li>
+ <li>Wrap: 10, 3, 5, 7, 10, 3, 5, 7, 10, 3, 5, 7, 10, 3, 5, 7, 10</li>
+ <li>Clip: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 7, 10, 10, 10, 10, 10</li>
+</ul>
+
+<p>The quantisation values should all be within the range minimum and maximum
+for it to work!</p>
+""" ;
+ a lv2:Plugin .
diff --git a/blip.lv2/random.ttl b/blip.lv2/random.ttl
new file mode 100644
index 0000000..9e44e4a
--- /dev/null
+++ b/blip.lv2/random.ttl
@@ -0,0 +1,59 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:random
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:maximum 0.5 ;
+ lv2:minimum 0.000001 ;
+ lv2:default 440.0 ;
+ lv2:name "Frequency (Hz)" ;
+ lv2:portProperty <http://lv2plug.in/ns/dev/extportinfo#logarithmic> ,
+ lv2:sampleRate ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 1 ;
+ lv2:index 1 ;
+ lv2:maximum 1 ;
+ lv2:minimum 0 ;
+ lv2:name "Wave Smoothness" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Output" ;
+ lv2:symbol "port2" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1661> ,
+ <urn:ladspa:1662> ,
+ <urn:ladspa:1663> ,
+ <urn:ladspa:1664> ;
+ dc:rights "GPL" ;
+ doap:name "Random Wave Generator" ;
+ lv2:documentation """
+<p>Generates a random waveform of varying frequency and smoothness. The
+frequency determines how often the output changes. The smoothness, how quickly
+a transition occurs.</p>
+
+<p>The output varies between &#177;1, with an even distribution.</p>
+""" ;
+ a lv2:Plugin , lv2:OscillatorPlugin .
diff --git a/blip.lv2/ratio.ttl b/blip.lv2/ratio.ttl
new file mode 100644
index 0000000..712a27c
--- /dev/null
+++ b/blip.lv2/ratio.ttl
@@ -0,0 +1,48 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:ratio
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Numerator" ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Denominator" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Ratio Output" ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:2034> ,
+ <urn:ladspa:2035> ,
+ <urn:ladspa:2036> ,
+ <urn:ladspa:2037> ;
+ dc:rights "GPL" ;
+ doap:name "Signal Ratio" ;
+ lv2:documentation """
+<p>Get the ratio between two signals.</p>
+<p>To avoid divisions by zero, 0 is treated as a really small number.</p>
+""" ;
+ a lv2:Plugin , lv2:UtilityPlugin .
diff --git a/blip.lv2/sawtooth.ttl b/blip.lv2/sawtooth.ttl
new file mode 100644
index 0000000..097ffde
--- /dev/null
+++ b/blip.lv2/sawtooth.ttl
@@ -0,0 +1,43 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:sawtooth
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:maximum 0.5 ;
+ lv2:minimum 0.000001 ;
+ lv2:default 440.0 ;
+ lv2:name "Frequency" ;
+ lv2:portProperty <http://lv2plug.in/ns/dev/extportinfo#logarithmic> ,
+ lv2:sampleRate ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Output" ;
+ lv2:symbol "port1" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1642> ,
+ <urn:ladspa:1643> ;
+ dc:rights "GPL" ;
+ doap:name "Sawtooth Oscillator" ;
+ lv2:documentation """
+<p>Generates an alias-free sawtooth wave at given input frequency.</p>
+""" ;
+ a lv2:Plugin , lv2:OscillatorPlugin .
diff --git a/blip.lv2/sequencer_16.ttl b/blip.lv2/sequencer_16.ttl
new file mode 100644
index 0000000..12eeb5c
--- /dev/null
+++ b/blip.lv2/sequencer_16.ttl
@@ -0,0 +1,191 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:sequencer_16
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Gate (Open > 0)" ;
+ lv2:symbol "port0" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Step Trigger" ;
+ lv2:symbol "port1" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 10 ;
+ lv2:name "Value Step 5" ;
+ lv2:symbol "port10" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 11 ;
+ lv2:name "Value Step 6" ;
+ lv2:symbol "port11" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 12 ;
+ lv2:name "Value Step 7" ;
+ lv2:symbol "port12" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 13 ;
+ lv2:name "Value Step 8" ;
+ lv2:symbol "port13" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 14 ;
+ lv2:name "Value Step 9" ;
+ lv2:symbol "port14" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 15 ;
+ lv2:name "Value Step 10" ;
+ lv2:symbol "port15" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 16 ;
+ lv2:name "Value Step 11" ;
+ lv2:symbol "port16" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 17 ;
+ lv2:name "Value Step 12" ;
+ lv2:symbol "port17" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 18 ;
+ lv2:name "Value Step 13" ;
+ lv2:symbol "port18" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 19 ;
+ lv2:name "Value Step 14" ;
+ lv2:symbol "port19" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 16 ;
+ lv2:index 2 ;
+ lv2:maximum 16 ;
+ lv2:minimum 1 ;
+ lv2:name "Loop Steps (1 - 16)" ;
+ lv2:portProperty lv2:integer ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 20 ;
+ lv2:name "Value Step 15" ;
+ lv2:symbol "port20" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 21 ;
+ lv2:name "Value Out" ;
+ lv2:symbol "port21" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 3 ;
+ lv2:maximum 1 ;
+ lv2:minimum 0 ;
+ lv2:name "Reset to Value on Gate Close?" ;
+ lv2:portProperty lv2:integer ;
+ lv2:symbol "port3" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 4 ;
+ lv2:name "Closed Gate Value" ;
+ lv2:symbol "port4" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 5 ;
+ lv2:name "Value Step 0" ;
+ lv2:symbol "port5" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 6 ;
+ lv2:name "Value Step 1" ;
+ lv2:symbol "port6" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 7 ;
+ lv2:name "Value Step 2" ;
+ lv2:symbol "port7" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 8 ;
+ lv2:name "Value Step 3" ;
+ lv2:symbol "port8" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 9 ;
+ lv2:name "Value Step 4" ;
+ lv2:symbol "port9" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1677> ;
+ dc:rights "GPL" ;
+ doap:name "Analogue Style 16 Step Sequencer" ;
+ lv2:documentation """
+<p>Simulates an analogue step sequencer. The sequencer stores a number of
+values which are stepped through using a trigger when the gate is open, looping
+after a given number of steps. This variant has 16 steps.</p>
+
+<p>When the gate is closed, the sequencer returns to the start. Output when
+the gate is closed can be set to a default value. If not, it will just output
+the last value reached before the gate was closed.</p>
+""" ;
+ a lv2:Plugin .
diff --git a/blip.lv2/sequencer_32.ttl b/blip.lv2/sequencer_32.ttl
new file mode 100644
index 0000000..7a29477
--- /dev/null
+++ b/blip.lv2/sequencer_32.ttl
@@ -0,0 +1,303 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:sequencer_32
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Gate (Open > 0)" ;
+ lv2:symbol "port0" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Step Trigger" ;
+ lv2:symbol "port1" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 10 ;
+ lv2:name "Value Step 5" ;
+ lv2:symbol "port10" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 11 ;
+ lv2:name "Value Step 6" ;
+ lv2:symbol "port11" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 12 ;
+ lv2:name "Value Step 7" ;
+ lv2:symbol "port12" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 13 ;
+ lv2:name "Value Step 8" ;
+ lv2:symbol "port13" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 14 ;
+ lv2:name "Value Step 9" ;
+ lv2:symbol "port14" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 15 ;
+ lv2:name "Value Step 10" ;
+ lv2:symbol "port15" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 16 ;
+ lv2:name "Value Step 11" ;
+ lv2:symbol "port16" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 17 ;
+ lv2:name "Value Step 12" ;
+ lv2:symbol "port17" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 18 ;
+ lv2:name "Value Step 13" ;
+ lv2:symbol "port18" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 19 ;
+ lv2:name "Value Step 14" ;
+ lv2:symbol "port19" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 32 ;
+ lv2:index 2 ;
+ lv2:maximum 32 ;
+ lv2:minimum 1 ;
+ lv2:name "Loop Steps (1 - 32)" ;
+ lv2:portProperty lv2:integer ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 20 ;
+ lv2:name "Value Step 15" ;
+ lv2:symbol "port20" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 21 ;
+ lv2:name "Value Step 16" ;
+ lv2:symbol "port21" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 22 ;
+ lv2:name "Value Step 17" ;
+ lv2:symbol "port22" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 23 ;
+ lv2:name "Value Step 18" ;
+ lv2:symbol "port23" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 24 ;
+ lv2:name "Value Step 19" ;
+ lv2:symbol "port24" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 25 ;
+ lv2:name "Value Step 20" ;
+ lv2:symbol "port25" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 26 ;
+ lv2:name "Value Step 21" ;
+ lv2:symbol "port26" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 27 ;
+ lv2:name "Value Step 22" ;
+ lv2:symbol "port27" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 28 ;
+ lv2:name "Value Step 23" ;
+ lv2:symbol "port28" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 29 ;
+ lv2:name "Value Step 24" ;
+ lv2:symbol "port29" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 3 ;
+ lv2:maximum 1 ;
+ lv2:minimum 0 ;
+ lv2:name "Reset to Value on Gate Close?" ;
+ lv2:portProperty lv2:integer ;
+ lv2:symbol "port3" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 30 ;
+ lv2:name "Value Step 25" ;
+ lv2:symbol "port30" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 31 ;
+ lv2:name "Value Step 26" ;
+ lv2:symbol "port31" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 32 ;
+ lv2:name "Value Step 27" ;
+ lv2:symbol "port32" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 33 ;
+ lv2:name "Value Step 28" ;
+ lv2:symbol "port33" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 34 ;
+ lv2:name "Value Step 29" ;
+ lv2:symbol "port34" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 35 ;
+ lv2:name "Value Step 30" ;
+ lv2:symbol "port35" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 36 ;
+ lv2:name "Value Step 31" ;
+ lv2:symbol "port36" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 37 ;
+ lv2:name "Value Out" ;
+ lv2:symbol "port37" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 4 ;
+ lv2:name "Closed Gate Value" ;
+ lv2:symbol "port4" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 5 ;
+ lv2:name "Value Step 0" ;
+ lv2:symbol "port5" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 6 ;
+ lv2:name "Value Step 1" ;
+ lv2:symbol "port6" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 7 ;
+ lv2:name "Value Step 2" ;
+ lv2:symbol "port7" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 8 ;
+ lv2:name "Value Step 3" ;
+ lv2:symbol "port8" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 9 ;
+ lv2:name "Value Step 4" ;
+ lv2:symbol "port9" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1676> ;
+ dc:rights "GPL" ;
+ doap:name "Analogue Style 32 Step Sequencer" ;
+ lv2:documentation """
+<p>Simulates an analogue step sequencer. The sequencer stores a number of
+values which are stepped through using a trigger when the gate is open, looping
+after a given number of steps. This variant has 32 steps.</p>
+
+<p>When the gate is closed, the sequencer returns to the start. Output when
+the gate is closed can be set to a default value. If not, it will just output
+the last value reached before the gate was closed.</p>
+""" ;
+ a lv2:Plugin .
diff --git a/blip.lv2/sequencer_64.ttl b/blip.lv2/sequencer_64.ttl
new file mode 100644
index 0000000..5e8efe8
--- /dev/null
+++ b/blip.lv2/sequencer_64.ttl
@@ -0,0 +1,527 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:sequencer_64
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Gate (Open > 0)" ;
+ lv2:symbol "port0" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Step Trigger" ;
+ lv2:symbol "port1" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 10 ;
+ lv2:name "Value Step 5" ;
+ lv2:symbol "port10" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 11 ;
+ lv2:name "Value Step 6" ;
+ lv2:symbol "port11" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 12 ;
+ lv2:name "Value Step 7" ;
+ lv2:symbol "port12" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 13 ;
+ lv2:name "Value Step 8" ;
+ lv2:symbol "port13" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 14 ;
+ lv2:name "Value Step 9" ;
+ lv2:symbol "port14" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 15 ;
+ lv2:name "Value Step 10" ;
+ lv2:symbol "port15" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 16 ;
+ lv2:name "Value Step 11" ;
+ lv2:symbol "port16" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 17 ;
+ lv2:name "Value Step 12" ;
+ lv2:symbol "port17" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 18 ;
+ lv2:name "Value Step 13" ;
+ lv2:symbol "port18" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 19 ;
+ lv2:name "Value Step 14" ;
+ lv2:symbol "port19" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 64 ;
+ lv2:index 2 ;
+ lv2:maximum 64 ;
+ lv2:minimum 1 ;
+ lv2:name "Loop Steps (1 - 64)" ;
+ lv2:portProperty lv2:integer ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 20 ;
+ lv2:name "Value Step 15" ;
+ lv2:symbol "port20" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 21 ;
+ lv2:name "Value Step 16" ;
+ lv2:symbol "port21" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 22 ;
+ lv2:name "Value Step 17" ;
+ lv2:symbol "port22" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 23 ;
+ lv2:name "Value Step 18" ;
+ lv2:symbol "port23" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 24 ;
+ lv2:name "Value Step 19" ;
+ lv2:symbol "port24" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 25 ;
+ lv2:name "Value Step 20" ;
+ lv2:symbol "port25" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 26 ;
+ lv2:name "Value Step 21" ;
+ lv2:symbol "port26" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 27 ;
+ lv2:name "Value Step 22" ;
+ lv2:symbol "port27" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 28 ;
+ lv2:name "Value Step 23" ;
+ lv2:symbol "port28" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 29 ;
+ lv2:name "Value Step 24" ;
+ lv2:symbol "port29" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0 ;
+ lv2:index 3 ;
+ lv2:maximum 1 ;
+ lv2:minimum 0 ;
+ lv2:name "Reset to Value on Gate Close?" ;
+ lv2:portProperty lv2:integer ;
+ lv2:symbol "port3" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 30 ;
+ lv2:name "Value Step 25" ;
+ lv2:symbol "port30" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 31 ;
+ lv2:name "Value Step 26" ;
+ lv2:symbol "port31" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 32 ;
+ lv2:name "Value Step 27" ;
+ lv2:symbol "port32" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 33 ;
+ lv2:name "Value Step 28" ;
+ lv2:symbol "port33" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 34 ;
+ lv2:name "Value Step 29" ;
+ lv2:symbol "port34" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 35 ;
+ lv2:name "Value Step 30" ;
+ lv2:symbol "port35" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 36 ;
+ lv2:name "Value Step 31" ;
+ lv2:symbol "port36" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 37 ;
+ lv2:name "Value Step 32" ;
+ lv2:symbol "port37" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 38 ;
+ lv2:name "Value Step 33" ;
+ lv2:symbol "port38" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 39 ;
+ lv2:name "Value Step 34" ;
+ lv2:symbol "port39" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 4 ;
+ lv2:name "Closed Gate Value" ;
+ lv2:symbol "port4" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 40 ;
+ lv2:name "Value Step 35" ;
+ lv2:symbol "port40" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 41 ;
+ lv2:name "Value Step 36" ;
+ lv2:symbol "port41" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 42 ;
+ lv2:name "Value Step 37" ;
+ lv2:symbol "port42" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 43 ;
+ lv2:name "Value Step 38" ;
+ lv2:symbol "port43" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 44 ;
+ lv2:name "Value Step 39" ;
+ lv2:symbol "port44" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 45 ;
+ lv2:name "Value Step 40" ;
+ lv2:symbol "port45" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 46 ;
+ lv2:name "Value Step 41" ;
+ lv2:symbol "port46" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 47 ;
+ lv2:name "Value Step 42" ;
+ lv2:symbol "port47" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 48 ;
+ lv2:name "Value Step 43" ;
+ lv2:symbol "port48" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 49 ;
+ lv2:name "Value Step 44" ;
+ lv2:symbol "port49" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 5 ;
+ lv2:name "Value Step 0" ;
+ lv2:symbol "port5" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 50 ;
+ lv2:name "Value Step 45" ;
+ lv2:symbol "port50" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 51 ;
+ lv2:name "Value Step 46" ;
+ lv2:symbol "port51" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 52 ;
+ lv2:name "Value Step 47" ;
+ lv2:symbol "port52" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 53 ;
+ lv2:name "Value Step 48" ;
+ lv2:symbol "port53" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 54 ;
+ lv2:name "Value Step 49" ;
+ lv2:symbol "port54" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 55 ;
+ lv2:name "Value Step 50" ;
+ lv2:symbol "port55" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 56 ;
+ lv2:name "Value Step 51" ;
+ lv2:symbol "port56" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 57 ;
+ lv2:name "Value Step 52" ;
+ lv2:symbol "port57" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 58 ;
+ lv2:name "Value Step 53" ;
+ lv2:symbol "port58" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 59 ;
+ lv2:name "Value Step 54" ;
+ lv2:symbol "port59" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 6 ;
+ lv2:name "Value Step 1" ;
+ lv2:symbol "port6" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 60 ;
+ lv2:name "Value Step 55" ;
+ lv2:symbol "port60" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 61 ;
+ lv2:name "Value Step 56" ;
+ lv2:symbol "port61" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 62 ;
+ lv2:name "Value Step 57" ;
+ lv2:symbol "port62" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 63 ;
+ lv2:name "Value Step 58" ;
+ lv2:symbol "port63" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 64 ;
+ lv2:name "Value Step 59" ;
+ lv2:symbol "port64" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 65 ;
+ lv2:name "Value Step 60" ;
+ lv2:symbol "port65" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 66 ;
+ lv2:name "Value Step 61" ;
+ lv2:symbol "port66" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 67 ;
+ lv2:name "Value Step 62" ;
+ lv2:symbol "port67" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 68 ;
+ lv2:name "Value Step 63" ;
+ lv2:symbol "port68" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 69 ;
+ lv2:name "Value Out" ;
+ lv2:symbol "port69" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 7 ;
+ lv2:name "Value Step 2" ;
+ lv2:symbol "port7" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 8 ;
+ lv2:name "Value Step 3" ;
+ lv2:symbol "port8" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 9 ;
+ lv2:name "Value Step 4" ;
+ lv2:symbol "port9" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1675> ;
+ dc:rights "GPL" ;
+ doap:name "Analogue Style 64 Step Sequencer" ;
+ lv2:documentation """
+<p>Simulates an analogue step sequencer. The sequencer stores a number of
+values which are stepped through using a trigger when the gate is open, looping
+after a given number of steps. This variant has 64 steps.</p>
+
+<p>When the gate is closed, the sequencer returns to the start. Output when
+the gate is closed can be set to a default value. If not, it will just output
+the last value reached before the gate was closed.</p>
+""" ;
+ a lv2:Plugin .
diff --git a/blip.lv2/square.ttl b/blip.lv2/square.ttl
new file mode 100644
index 0000000..709e83e
--- /dev/null
+++ b/blip.lv2/square.ttl
@@ -0,0 +1,43 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:square
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:maximum 0.5 ;
+ lv2:minimum 0.000001 ;
+ lv2:default 440.0 ;
+ lv2:name "Frequency" ;
+ lv2:portProperty <http://lv2plug.in/ns/dev/extportinfo#logarithmic> ,
+ lv2:sampleRate ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Output" ;
+ lv2:symbol "port1" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1643> ,
+ <urn:ladspa:1644> ;
+ dc:rights "GPL" ;
+ doap:name "Square Oscillator" ;
+ lv2:documentation """
+<p>Generates an alias-free square wave at given input frequency.</p>
+""" ;
+ a lv2:Plugin , lv2:OscillatorPlugin .
diff --git a/blip.lv2/sum.ttl b/blip.lv2/sum.ttl
new file mode 100644
index 0000000..c6021ed
--- /dev/null
+++ b/blip.lv2/sum.ttl
@@ -0,0 +1,46 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:sum
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "First Input" ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Second Input" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Summed Output" ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1665> ,
+ <urn:ladspa:1666> ,
+ <urn:ladspa:1667> ;
+ dc:rights "GPL" ;
+ doap:name "Signal Sum" ;
+ lv2:documentation """
+<p>Add two signals.</p>
+""" ;
+ a lv2:Plugin , lv2:UtilityPlugin .
diff --git a/blip.lv2/sync_pulse.ttl b/blip.lv2/sync_pulse.ttl
new file mode 100644
index 0000000..3807222
--- /dev/null
+++ b/blip.lv2/sync_pulse.ttl
@@ -0,0 +1,59 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:sync_pulse
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:default 16 ;
+ lv2:index 0 ;
+ lv2:maximum 64 ;
+ lv2:minimum 0 ;
+ lv2:name "Frequency" ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0.5 ;
+ lv2:index 1 ;
+ lv2:maximum 1 ;
+ lv2:minimum 0 ;
+ lv2:name "Pulse Width" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Gate" ;
+ lv2:symbol "port2" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 3 ;
+ lv2:name "Output" ;
+ lv2:symbol "port3" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:2023> ,
+ <urn:ladspa:2024> ;
+ dc:rights "GPL" ;
+ doap:name "Clock Pulse Oscillator with Gate" ;
+ lv2:documentation """
+<p>Same as the <a href="http://drobilla.net/plugins/blip/sync_square">Clock
+Oscillator</a>, but with pulse-width modulation.</p>
+""" ;
+ a lv2:Plugin , lv2:OscillatorPlugin .
diff --git a/blip.lv2/sync_square.ttl b/blip.lv2/sync_square.ttl
new file mode 100644
index 0000000..80cd65b
--- /dev/null
+++ b/blip.lv2/sync_square.ttl
@@ -0,0 +1,52 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:sync_square
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:default 16 ;
+ lv2:index 0 ;
+ lv2:maximum 64 ;
+ lv2:minimum 0 ;
+ lv2:name "Frequency" ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 1 ;
+ lv2:name "Gate" ;
+ lv2:symbol "port1" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Output" ;
+ lv2:symbol "port2" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1678> ,
+ <urn:ladspa:1679> ;
+ dc:rights "GPL" ;
+ doap:name "Clock Oscillator with Gate" ;
+ lv2:documentation """
+<p>Generates a non-bandlimited simple square waveform for use as a clock.
+Useful for triggering the sequencers, or anything else that uses a clock
+signal.</p>
+
+<p>When the gate is closed, it outputs silence, and the phase is reset.</p>
+""" ;
+ a lv2:Plugin , lv2:OscillatorPlugin .
diff --git a/blip.lv2/tracker.ttl b/blip.lv2/tracker.ttl
new file mode 100644
index 0000000..9cb32e0
--- /dev/null
+++ b/blip.lv2/tracker.ttl
@@ -0,0 +1,115 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:tracker
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:name "Gate" ;
+ lv2:symbol "port0" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 100 ;
+ lv2:index 1 ;
+ lv2:maximum 0.5 ;
+ lv2:minimum "2.08333e-05"^^xsd:double ;
+ lv2:name "Attack Rate (Hz) when Gate High" ;
+ lv2:portProperty <http://lv2plug.in/ns/dev/extportinfo#logarithmic> ,
+ lv2:sampleRate ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 100 ;
+ lv2:index 2 ;
+ lv2:maximum 0.5 ;
+ lv2:minimum "2.08333e-05"^^xsd:double ;
+ lv2:name "Decay Rate (Hz) when Gate High" ;
+ lv2:portProperty <http://lv2plug.in/ns/dev/extportinfo#logarithmic> ,
+ lv2:sampleRate ;
+ lv2:symbol "port2" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 100 ;
+ lv2:index 3 ;
+ lv2:maximum 0.5 ;
+ lv2:minimum "2.08333e-05"^^xsd:double ;
+ lv2:name "Attack Rate (Hz) when Gate Low" ;
+ lv2:portProperty <http://lv2plug.in/ns/dev/extportinfo#logarithmic> ,
+ lv2:sampleRate ;
+ lv2:symbol "port3" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 100 ;
+ lv2:index 4 ;
+ lv2:maximum 0.5 ;
+ lv2:minimum "2.08333e-05"^^xsd:double ;
+ lv2:name "Decay Rate (Hz) when Gate Low" ;
+ lv2:portProperty <http://lv2plug.in/ns/dev/extportinfo#logarithmic> ,
+ lv2:sampleRate ;
+ lv2:symbol "port4" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 5 ;
+ lv2:name "Input" ;
+ lv2:symbol "port5" ;
+ a lv2:AudioPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 6 ;
+ lv2:name "Output" ;
+ lv2:symbol "port6" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:2025> ,
+ <urn:ladspa:2026> ;
+ dc:rights "GPL" ;
+ doap:name "Signal Tracker" ;
+ lv2:documentation """
+<p>This tracks an incoming signal and outputs the result.</p>
+<p>The rate controls tell the plugin how quickly to respond to a change in
+input. Low values will mean a slower response - a setting of 0 will hold the
+last value, and a very high value will track the input exactly.</p>
+<p>Attack rate is how quickly an upward change is tracked, and Decay for
+downward changes. There are two pairs of these - the one used depends on the
+level of the Gate.</p>
+<p>Example uses:</p>
+<ul>
+ <li>
+ <em>An envelope tracker</em>- use the &#8216;Gate Low&#8217; track rates with
+ the Gate held low, and run the output through a full-wave rectifier (an ABS()
+ operator) to get an estimate of the level of a signal.</li>
+ <li>
+ <em>Sample and Hold</em>- run a narrow pulse wave into the gate, set the
+ &#8216;Gate High&#8217; rates to maximum, and the &#8216;Gate Low&#8217;
+ rates set to 0.</li>
+ <li>
+ <em>Track and Hold</em>- run a variable pulse wave into the gate, set the
+ &#8216;Gate High&#8217; rates to 0, and the &#8216;Gate Low&#8217; rates set
+ high. Varying the pulsewidth will vary the time the input is tracked, and
+ when it is held.</li>
+</ul>
+""" ;
+ a lv2:Plugin .
diff --git a/blip.lv2/triangle.ttl b/blip.lv2/triangle.ttl
new file mode 100644
index 0000000..105fb82
--- /dev/null
+++ b/blip.lv2/triangle.ttl
@@ -0,0 +1,57 @@
+@prefix blip: <http://drobilla.net/plugins/blip/> .
+@prefix dc: <http://purl.org/dc/elements/1.1/> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+
+blip:triangle
+ lv2:microVersion 0 ;
+ lv2:minorVersion 0 ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:port [
+ lv2:index 0 ;
+ lv2:maximum 0.5 ;
+ lv2:minimum 0.000001 ;
+ lv2:default 440.0 ;
+ lv2:name "Frequency" ;
+ lv2:portProperty <http://lv2plug.in/ns/dev/extportinfo#logarithmic> ,
+ lv2:sampleRate ;
+ lv2:symbol "port0" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:default 0.5 ;
+ lv2:index 1 ;
+ lv2:maximum 1 ;
+ lv2:minimum 0 ;
+ lv2:name "Slope" ;
+ lv2:symbol "port1" ;
+ a lv2:ControlPort ,
+ lv2:InputPort ,
+ lv2:Port
+ ] , [
+ lv2:index 2 ;
+ lv2:name "Output" ;
+ lv2:symbol "port2" ;
+ a lv2:AudioPort ,
+ lv2:OutputPort ,
+ lv2:Port
+ ] ;
+ dc:creator "Mike Rawes <mike_rawes[at]yahoo.co.uk>" ;
+ dc:replaces <urn:ladspa:1649> ,
+ <urn:ladspa:1650> ,
+ <urn:ladspa:1651> ,
+ <urn:ladspa:1652> ;
+ dc:rights "GPL" ;
+ doap:name "Variable Slope Triangle Oscillator" ;
+ lv2:documentation """
+<p>Generates an alias-free variable slope triangle wave at given input
+frequency and slope. The slope changes the wave shape from sawtooth to
+triangle.</p>
+""" ;
+ a lv2:Plugin , lv2:OscillatorPlugin .
diff --git a/src/adsr.c b/src/adsr.c
new file mode 100644
index 0000000..ef4b27e
--- /dev/null
+++ b/src/adsr.c
@@ -0,0 +1,256 @@
+/*
+ An LV2 plugin to generate ADSR envelopes.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "common.h"
+
+#define ADSR_SIGNAL 0
+#define ADSR_TRIGGER 1
+#define ADSR_ATTACK 2
+#define ADSR_DECAY 3
+#define ADSR_SUSTAIN 4
+#define ADSR_RELEASE 5
+#define ADSR_OUTPUT 6
+
+typedef enum {
+ IDLE,
+ ATTACK,
+ DECAY,
+ SUSTAIN,
+ RELEASE
+} ADSRState;
+
+typedef struct {
+ float* signal;
+ float* trigger;
+ float* attack;
+ float* decay;
+ float* sustain;
+ float* release;
+ float* output;
+ float srate;
+ float inv_srate;
+ float from_level;
+ float level;
+ ADSRState state;
+ uint32_t samples;
+} Adsr;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Adsr* plugin = (Adsr*)instance;
+
+ switch (port) {
+ case ADSR_SIGNAL:
+ plugin->signal = data;
+ break;
+ case ADSR_TRIGGER:
+ plugin->trigger = data;
+ break;
+ case ADSR_ATTACK:
+ plugin->attack = data;
+ break;
+ case ADSR_DECAY:
+ plugin->decay = data;
+ break;
+ case ADSR_SUSTAIN:
+ plugin->sustain = data;
+ break;
+ case ADSR_RELEASE:
+ plugin->release = data;
+ break;
+ case ADSR_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Adsr* plugin = (Adsr*)malloc(sizeof(Adsr));
+
+ plugin->srate = (float)sample_rate;
+ plugin->inv_srate = 1.0f / plugin->srate;
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Adsr* plugin = (Adsr*)instance;
+
+ plugin->from_level = 0.0f;
+ plugin->level = 0.0f;
+ plugin->state = IDLE;
+ plugin->samples = 0;
+}
+
+static void
+runAdsr(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Adsr* plugin = (Adsr*)instance;
+
+ /* Driving signal */
+ float* signal = plugin->signal;
+
+ /* Trigger Threshold */
+ float trigger = *(plugin->trigger);
+
+ /* Attack Time (s) */
+ float attack = *(plugin->attack);
+
+ /* Decay Time (s) */
+ float decay = *(plugin->decay);
+
+ /* Sustain Level */
+ float sustain = f_clip(*(plugin->sustain), 0.0f, 1.0f);
+
+ /* Release Time (s) */
+ float release = *(plugin->release);
+
+ /* Envelope Out */
+ float* output = plugin->output;
+
+ float srate = plugin->srate;
+ float inv_srate = plugin->inv_srate;
+ float from_level = plugin->from_level;
+ float level = plugin->level;
+ ADSRState state = plugin->state;
+ uint32_t samples = plugin->samples;
+
+ float elapsed;
+
+ /* Convert times into rates */
+ attack = attack > 0.0f ? inv_srate / attack : srate;
+ decay = decay > 0.0f ? inv_srate / decay : srate;
+ release = release > 0.0f ? inv_srate / release : srate;
+
+ for (uint32_t s = 0; s < sample_count; s++) {
+ /* Determine if attack or release happened */
+ if ((state == IDLE) || (state == RELEASE)) {
+ if (signal[s] > trigger) {
+ if (attack < srate) {
+ state = ATTACK;
+ } else {
+ state = decay < srate ? DECAY : SUSTAIN;
+ level = 1.0f;
+ }
+ samples = 0;
+ }
+ } else {
+ if (signal[s] <= trigger) {
+ state = release < srate ? RELEASE : IDLE;
+ samples = 0;
+ }
+ }
+
+ if (samples == 0) {
+ from_level = level;
+ }
+
+ /* Calculate level of envelope from current state */
+ switch (state) {
+ case IDLE:
+ level = 0;
+ break;
+ case ATTACK:
+ samples++;
+ elapsed = (float)samples * attack;
+ if (elapsed > 1.0f) {
+ state = decay < srate ? DECAY : SUSTAIN;
+ level = 1.0f;
+ samples = 0;
+ } else {
+ level = from_level + elapsed * (1.0f - from_level);
+ }
+ break;
+ case DECAY:
+ samples++;
+ elapsed = (float)samples * decay;
+ if (elapsed > 1.0f) {
+ state = SUSTAIN;
+ level = sustain;
+ samples = 0;
+ } else {
+ level = from_level + elapsed * (sustain - from_level);
+ }
+ break;
+ case SUSTAIN:
+ level = sustain;
+ break;
+ case RELEASE:
+ samples++;
+ elapsed = (float)samples * release;
+ if (elapsed > 1.0f) {
+ state = IDLE;
+ level = 0.0f;
+ samples = 0;
+ } else {
+ level = from_level - elapsed * from_level;
+ }
+ break;
+ default:
+ /* Should never happen */
+ level = 0.0f;
+ }
+
+ output[s] = level;
+ }
+
+ plugin->from_level = from_level;
+ plugin->level = level;
+ plugin->state = state;
+ plugin->samples = samples;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/adsr",
+ instantiate,
+ connect_port,
+ activate,
+ runAdsr,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/adsr_gt.c b/src/adsr_gt.c
new file mode 100644
index 0000000..f9aa225
--- /dev/null
+++ b/src/adsr_gt.c
@@ -0,0 +1,264 @@
+/*
+ An LV2 plugin to generate ADSR envelopes Gate and Trigger variant.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "common.h"
+
+#define ADSR_GATE 0
+#define ADSR_TRIGGER 1
+#define ADSR_ATTACK 2
+#define ADSR_DECAY 3
+#define ADSR_SUSTAIN 4
+#define ADSR_RELEASE 5
+#define ADSR_OUTPUT 6
+
+typedef enum {
+ IDLE,
+ ATTACK,
+ DECAY,
+ SUSTAIN,
+ RELEASE
+} ADSRState;
+
+typedef struct {
+ float* gate;
+ float* trigger;
+ float* attack;
+ float* decay;
+ float* sustain;
+ float* release;
+ float* output;
+ float srate;
+ float inv_srate;
+ float last_trigger;
+ float from_level;
+ float level;
+ ADSRState state;
+ uint32_t samples;
+} Adsr;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Adsr* plugin = (Adsr*)instance;
+
+ switch (port) {
+ case ADSR_GATE:
+ plugin->gate = data;
+ break;
+ case ADSR_TRIGGER:
+ plugin->trigger = data;
+ break;
+ case ADSR_ATTACK:
+ plugin->attack = data;
+ break;
+ case ADSR_DECAY:
+ plugin->decay = data;
+ break;
+ case ADSR_SUSTAIN:
+ plugin->sustain = data;
+ break;
+ case ADSR_RELEASE:
+ plugin->release = data;
+ break;
+ case ADSR_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Adsr* plugin = (Adsr*)malloc(sizeof(Adsr));
+
+ plugin->srate = (float)sample_rate;
+ plugin->inv_srate = 1.0f / plugin->srate;
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Adsr* plugin = (Adsr*)instance;
+
+ plugin->last_trigger = 0.0f;
+ plugin->from_level = 0.0f;
+ plugin->level = 0.0f;
+ plugin->state = IDLE;
+ plugin->samples = 0;
+}
+
+static void
+runAdsr(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Adsr* plugin = (Adsr*)instance;
+
+ /* Gate */
+ float* gate = plugin->gate;
+
+ /* Trigger */
+ float* trigger = plugin->trigger;
+
+ /* Attack Time (s) */
+ float attack = *(plugin->attack);
+
+ /* Decay Time (s) */
+ float decay = *(plugin->decay);
+
+ /* Sustain Level */
+ float sustain = f_clip(*(plugin->sustain), 0.0f, 1.0f);
+
+ /* Release Time (s) */
+ float release = *(plugin->release);
+
+ /* Envelope Out */
+ float* output = plugin->output;
+
+ float srate = plugin->srate;
+ float inv_srate = plugin->inv_srate;
+ float last_trigger = plugin->last_trigger;
+ float from_level = plugin->from_level;
+ float level = plugin->level;
+ ADSRState state = plugin->state;
+ uint32_t samples = plugin->samples;
+
+ float elapsed;
+
+ /* Convert times into rates */
+ attack = attack > 0.0f ? inv_srate / attack : srate;
+ decay = decay > 0.0f ? inv_srate / decay : srate;
+ release = release > 0.0f ? inv_srate / release : srate;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ /* Attack on trigger, if gate is open */
+ if (trigger[s] > 0.0f
+ && !(last_trigger > 0.0f)
+ && gate[s] > 0.0f) {
+ if (attack < srate) {
+ state = ATTACK;
+ } else {
+ state = decay < srate ? DECAY : SUSTAIN;
+ level = 1.0f;
+ }
+ samples = 0;
+ }
+
+ /* Release if gate closed */
+ if (state != IDLE
+ && state != RELEASE
+ && !(gate[s] > 0.0f)) {
+ state = release < srate ? RELEASE : IDLE;
+ samples = 0;
+ }
+
+ if (samples == 0) {
+ from_level = level;
+ }
+
+ /* Calculate level of envelope from current state */
+ switch (state) {
+ case IDLE:
+ level = 0;
+ break;
+ case ATTACK:
+ samples++;
+ elapsed = (float)samples * attack;
+ if (elapsed > 1.0f) {
+ state = decay < srate ? DECAY : SUSTAIN;
+ level = 1.0f;
+ samples = 0;
+ } else {
+ level = from_level + elapsed * (1.0f - from_level);
+ }
+ break;
+ case DECAY:
+ samples++;
+ elapsed = (float)samples * decay;
+ if (elapsed > 1.0f) {
+ state = SUSTAIN;
+ level = sustain;
+ samples = 0;
+ } else {
+ level = from_level + elapsed * (sustain - from_level);
+ }
+ break;
+ case SUSTAIN:
+ level = sustain;
+ break;
+ case RELEASE:
+ samples++;
+ elapsed = (float)samples * release;
+ if (elapsed > 1.0f) {
+ state = IDLE;
+ level = 0.0f;
+ samples = 0;
+ } else {
+ level = from_level - elapsed * from_level;
+ }
+ break;
+ default:
+ /* Should never happen */
+ level = 0.0f;
+ }
+
+ output[s] = level;
+ last_trigger = trigger[s];
+ }
+
+ plugin->last_trigger = last_trigger;
+ plugin->from_level = from_level;
+ plugin->level = level;
+ plugin->state = state;
+ plugin->samples = samples;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/adsr_gt",
+ instantiate,
+ connect_port,
+ activate,
+ runAdsr,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/amp.c b/src/amp.c
new file mode 100644
index 0000000..4c528f9
--- /dev/null
+++ b/src/amp.c
@@ -0,0 +1,142 @@
+/*
+ An LV2 plugin representing a simple mono amplifier.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "math_func.h"
+
+#define AMP_GAIN 0
+#define AMP_INPUT 1
+#define AMP_OUTPUT 2
+
+typedef struct {
+ const float* gain;
+ const float* input;
+ float* output;
+} Amp;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Amp* plugin = (Amp*)instance;
+
+ switch (port) {
+ case AMP_GAIN:
+ plugin->gain = data;
+ break;
+ case AMP_INPUT:
+ plugin->input = data;
+ break;
+ case AMP_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Amp* plugin = (Amp*)malloc(sizeof(Amp));
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+runAmp_gaia_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Amp* plugin = (Amp*)instance;
+
+ /* Gain (dB) */
+ const float* gain = plugin->gain;
+
+ /* Input */
+ const float* input = plugin->input;
+
+ /* Output */
+ float* output = plugin->output;
+
+ float gn;
+ float in;
+ float scale;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ gn = gain[s];
+ in = input[s];
+
+ scale = (float)EXPF(M_LN10 * gn * 0.05f);
+
+ output[s] = scale * in;
+ }
+}
+
+static void
+runAmp_gcia_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Amp* plugin = (Amp*)instance;
+
+ /* Gain (dB) */
+ const float gain = *(plugin->gain);
+
+ /* Input */
+ const float* input = plugin->input;
+
+ /* Output */
+ float* output = plugin->output;
+
+ float in;
+ float scale = (float)EXPF(M_LN10 * gain * 0.05f);
+ for (uint32_t s = 0; s < sample_count; s++) {
+ in = input[s];
+
+ output[s] = scale * in;
+ }
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/amp",
+ instantiate,
+ connect_port,
+ NULL,
+ runAmp_gcia_oa,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/branch.c b/src/branch.c
new file mode 100644
index 0000000..70329a2
--- /dev/null
+++ b/src/branch.c
@@ -0,0 +1,133 @@
+/*
+ An LV2 plugin to split a signal into two.
+ Copyright 2011 David Robillard
+
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+
+#define BRANCH_INPUT 0
+#define BRANCH_OUTPUT1 1
+#define BRANCH_OUTPUT2 2
+
+typedef struct {
+ float* input;
+ float* output1;
+ float* output2;
+} Branch;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Branch* plugin = (Branch*)instance;
+
+ switch (port) {
+ case BRANCH_INPUT:
+ plugin->input = data;
+ break;
+ case BRANCH_OUTPUT1:
+ plugin->output1 = data;
+ break;
+ case BRANCH_OUTPUT2:
+ plugin->output2 = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Branch* plugin = (Branch*)malloc(sizeof(Branch));
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+runBranch_ia_oaoa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Branch* plugin = (Branch*)instance;
+
+ /* Input (array of floats of length sample_count) */
+ float* input = plugin->input;
+
+ /* First Output (array of floats of length sample_count) */
+ float* output1 = plugin->output1;
+
+ /* Second Output (array of floats of length sample_count) */
+ float* output2 = plugin->output2;
+
+ float in;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in = input[s];
+
+ output1[s] = in;
+ output2[s] = in;
+ }
+}
+
+static void
+runBranch_ic_ococ(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Branch* plugin = (Branch*)instance;
+
+ /* Input (float value) */
+ float input = *(plugin->input);
+
+ /* First Output (pointer to float value) */
+ float* output1 = plugin->output1;
+
+ /* Second Output (pointer to float value) */
+ float* output2 = plugin->output2;
+
+ output1[0] = input;
+ output2[0] = input;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/branch",
+ instantiate,
+ connect_port,
+ NULL,
+ runBranch_ic_ococ,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/dahdsr.c b/src/dahdsr.c
new file mode 100644
index 0000000..01115bb
--- /dev/null
+++ b/src/dahdsr.c
@@ -0,0 +1,685 @@
+/*
+ An LV2 plugin to generate DAHDSR envelopes Gate and (re)trigger
+ Copyright 2011 David Robillard
+ Copyright 2004 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "common.h"
+
+#define DAHDSR_GATE 0
+#define DAHDSR_TRIGGER 1
+#define DAHDSR_DELAY 2
+#define DAHDSR_ATTACK 3
+#define DAHDSR_HOLD 4
+#define DAHDSR_DECAY 5
+#define DAHDSR_SUSTAIN 6
+#define DAHDSR_RELEASE 7
+#define DAHDSR_OUTPUT 8
+
+typedef enum {
+ IDLE,
+ DELAY,
+ ATTACK,
+ HOLD,
+ DECAY,
+ SUSTAIN,
+ RELEASE
+} DAHDSRState;
+
+typedef struct {
+ float* gate;
+ float* trigger;
+ float* delay;
+ float* attack;
+ float* hold;
+ float* decay;
+ float* sustain;
+ float* release;
+ float* output;
+ float srate;
+ float inv_srate;
+ float last_gate;
+ float last_trigger;
+ float from_level;
+ float level;
+ DAHDSRState state;
+ uint32_t samples;
+} Dahdsr;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Dahdsr* plugin = (Dahdsr*)instance;
+
+ switch (port) {
+ case DAHDSR_GATE:
+ plugin->gate = data;
+ break;
+ case DAHDSR_TRIGGER:
+ plugin->trigger = data;
+ break;
+ case DAHDSR_DELAY:
+ plugin->delay = data;
+ break;
+ case DAHDSR_ATTACK:
+ plugin->attack = data;
+ break;
+ case DAHDSR_HOLD:
+ plugin->hold = data;
+ break;
+ case DAHDSR_DECAY:
+ plugin->decay = data;
+ break;
+ case DAHDSR_SUSTAIN:
+ plugin->sustain = data;
+ break;
+ case DAHDSR_RELEASE:
+ plugin->release = data;
+ break;
+ case DAHDSR_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Dahdsr* plugin = (Dahdsr*)malloc(sizeof(Dahdsr));
+
+ plugin->srate = (float)sample_rate;
+ plugin->inv_srate = 1.0f / plugin->srate;
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Dahdsr* plugin = (Dahdsr*)instance;
+
+ plugin->last_gate = 0.0f;
+ plugin->last_trigger = 0.0f;
+ plugin->from_level = 0.0f;
+ plugin->level = 0.0f;
+ plugin->state = IDLE;
+ plugin->samples = 0;
+}
+
+static void
+runDahdsr_Audio(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Dahdsr* plugin = (Dahdsr*)instance;
+
+ /* Gate */
+ float* gate = plugin->gate;
+
+ /* Trigger */
+ float* trigger = plugin->trigger;
+
+ /* Delay Time (s) */
+ float* delay = plugin->delay;
+
+ /* Attack Time (s) */
+ float* attack = plugin->attack;
+
+ /* Hold Time (s) */
+ float* hold = plugin->hold;
+
+ /* Decay Time (s) */
+ float* decay = plugin->decay;
+
+ /* Sustain Level */
+ float* sustain = plugin->sustain;
+
+ /* Release Time (s) */
+ float* release = plugin->release;
+
+ /* Envelope Out */
+ float* output = plugin->output;
+
+ /* Instance Data */
+ float srate = plugin->srate;
+ float inv_srate = plugin->inv_srate;
+ float last_gate = plugin->last_gate;
+ float last_trigger = plugin->last_trigger;
+ float from_level = plugin->from_level;
+ float level = plugin->level;
+ DAHDSRState state = plugin->state;
+ uint32_t samples = plugin->samples;
+
+ float gat, trg, del, att, hld, dec, sus, rel;
+ float elapsed;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ /* Convert times into rates */
+ del = delay[s] > 0.0f ? inv_srate / delay[s] : srate;
+ att = attack[s] > 0.0f ? inv_srate / attack[s] : srate;
+ hld = hold[s] > 0.0f ? inv_srate / hold[s] : srate;
+ dec = decay[s] > 0.0f ? inv_srate / decay[s] : srate;
+ rel = release[s] > 0.0f ? inv_srate / release[s] : srate;
+
+ gat = gate[s];
+ trg = trigger[s];
+ sus = f_clip(sustain[s], 0.0f, 1.0f);
+
+ /* Initialise delay phase if gate is opened and was closed, or
+ we received a trigger */
+ if ((trg > 0.0f && !(last_trigger > 0.0f))
+ || (gat > 0.0f && !(last_gate > 0.0f))) {
+ if (del < srate) {
+ state = DELAY;
+ } else if (att < srate) {
+ state = ATTACK;
+ } else {
+ state = hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE)));
+ level = 1.0f;
+ }
+ samples = 0;
+ }
+
+ /* Release if gate was open and now closed */
+ if (state != IDLE && state != RELEASE
+ && last_gate > 0.0f && !(gat > 0.0f)) {
+ state = rel < srate ? RELEASE : IDLE;
+ samples = 0;
+ }
+
+ if (samples == 0) {
+ from_level = level;
+ }
+
+ /* Calculate level of envelope from current state */
+ switch (state) {
+ case IDLE:
+ level = 0;
+ break;
+ case DELAY:
+ samples++;
+ elapsed = (float)samples * del;
+ if (elapsed > 1.0f) {
+ state = att < srate ? ATTACK
+ : (hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE))));
+ samples = 0;
+ }
+ break;
+ case ATTACK:
+ samples++;
+ elapsed = (float)samples * att;
+ if (elapsed > 1.0f) {
+ state = hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE)));
+ level = 1.0f;
+ samples = 0;
+ } else {
+ level = from_level + elapsed * (1.0f - from_level);
+ }
+ break;
+ case HOLD:
+ samples++;
+ elapsed = (float)samples * hld;
+ if (elapsed > 1.0f) {
+ state = dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE));
+ samples = 0;
+ }
+ break;
+ case DECAY:
+ samples++;
+ elapsed = (float)samples * dec;
+ if (elapsed > 1.0f) {
+ state = gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE);
+ level = sus;
+ samples = 0;
+ } else {
+ level = from_level + elapsed * (sus - from_level);
+ }
+ break;
+ case SUSTAIN:
+ level = sus;
+ break;
+ case RELEASE:
+ samples++;
+ elapsed = (float)samples * rel;
+ if (elapsed > 1.0f) {
+ state = IDLE;
+ level = 0.0f;
+ samples = 0;
+ } else {
+ level = from_level - elapsed * from_level;
+ }
+ break;
+ default:
+ /* Should never happen */
+ level = 0.0f;
+ }
+
+ output[s] = level;
+
+ last_gate = gate[s];
+ last_trigger = trigger[s];
+ }
+
+ plugin->last_gate = last_gate;
+ plugin->last_trigger = last_trigger;
+ plugin->from_level = from_level;
+ plugin->level = level;
+ plugin->state = state;
+ plugin->samples = samples;
+}
+
+static void
+runDahdsr_Control(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Dahdsr* plugin = (Dahdsr*)instance;
+
+ /* Gate */
+ float* gate = plugin->gate;
+
+ /* Trigger */
+ float* trigger = plugin->trigger;
+
+ /* Delay Time (s) */
+ float delay = *(plugin->delay);
+
+ /* Attack Time (s) */
+ float attack = *(plugin->attack);
+
+ /* Hold Time (s) */
+ float hold = *(plugin->hold);
+
+ /* Decay Time (s) */
+ float decay = *(plugin->decay);
+
+ /* Sustain Level */
+ float sustain = *(plugin->sustain);
+
+ /* Release Time (s) */
+ float release = *(plugin->release);
+
+ /* Envelope Out */
+ float* output = plugin->output;
+
+ /* Instance Data */
+ float srate = plugin->srate;
+ float inv_srate = plugin->inv_srate;
+ float last_gate = plugin->last_gate;
+ float last_trigger = plugin->last_trigger;
+ float from_level = plugin->from_level;
+ float level = plugin->level;
+ DAHDSRState state = plugin->state;
+ uint32_t samples = plugin->samples;
+
+ float gat, trg, del, att, hld, dec, sus, rel;
+ float elapsed;
+
+ /* Convert times into rates */
+ del = delay > 0.0f ? inv_srate / delay : srate;
+ att = attack > 0.0f ? inv_srate / attack : srate;
+ hld = hold > 0.0f ? inv_srate / hold : srate;
+ dec = decay > 0.0f ? inv_srate / decay : srate;
+ rel = release > 0.0f ? inv_srate / release : srate;
+
+ sus = f_clip(sustain, 0.0f, 1.0f);
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ gat = gate[s];
+ trg = trigger[s];
+
+ /* Initialise delay phase if gate is opened and was closed, or
+ we received a trigger */
+ if ((trg > 0.0f && !(last_trigger > 0.0f))
+ || (gat > 0.0f && !(last_gate > 0.0f))) {
+ if (del < srate) {
+ state = DELAY;
+ } else if (att < srate) {
+ state = ATTACK;
+ } else {
+ state = hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE)));
+ level = 1.0f;
+ }
+ samples = 0;
+ }
+
+ /* Release if gate was open and now closed */
+ if (state != IDLE && state != RELEASE
+ && last_gate > 0.0f && !(gat > 0.0f)) {
+ state = rel < srate ? RELEASE : IDLE;
+ samples = 0;
+ }
+
+ if (samples == 0) {
+ from_level = level;
+ }
+
+ /* Calculate level of envelope from current state */
+ switch (state) {
+ case IDLE:
+ level = 0;
+ break;
+ case DELAY:
+ samples++;
+ elapsed = (float)samples * del;
+ if (elapsed > 1.0f) {
+ state = att < srate ? ATTACK
+ : (hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE))));
+ samples = 0;
+ }
+ break;
+ case ATTACK:
+ samples++;
+ elapsed = (float)samples * att;
+ if (elapsed > 1.0f) {
+ state = hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE)));
+ level = 1.0f;
+ samples = 0;
+ } else {
+ level = from_level + elapsed * (1.0f - from_level);
+ }
+ break;
+ case HOLD:
+ samples++;
+ elapsed = (float)samples * hld;
+ if (elapsed > 1.0f) {
+ state = dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE));
+ samples = 0;
+ }
+ break;
+ case DECAY:
+ samples++;
+ elapsed = (float)samples * dec;
+ if (elapsed > 1.0f) {
+ state = gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE);
+ level = sus;
+ samples = 0;
+ } else {
+ level = from_level + elapsed * (sus - from_level);
+ }
+ break;
+ case SUSTAIN:
+ level = sus;
+ break;
+ case RELEASE:
+ samples++;
+ elapsed = (float)samples * rel;
+ if (elapsed > 1.0f) {
+ state = IDLE;
+ level = 0.0f;
+ samples = 0;
+ } else {
+ level = from_level - elapsed * from_level;
+ }
+ break;
+ default:
+ /* Should never happen */
+ level = 0.0f;
+ }
+
+ output[s] = level;
+
+ last_gate = gat;
+ last_trigger = trg;
+ }
+
+ plugin->last_gate = last_gate;
+ plugin->last_trigger = last_trigger;
+ plugin->from_level = from_level;
+ plugin->level = level;
+ plugin->state = state;
+ plugin->samples = samples;
+}
+
+static void
+runDahdsr_CGT_Control(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Dahdsr* plugin = (Dahdsr*)instance;
+
+ /* Gate */
+ float gate = *(plugin->gate);
+
+ /* Trigger */
+ float trigger = *(plugin->trigger);
+
+ /* Delay Time (s) */
+ float delay = *(plugin->delay);
+
+ /* Attack Time (s) */
+ float attack = *(plugin->attack);
+
+ /* Hold Time (s) */
+ float hold = *(plugin->hold);
+
+ /* Decay Time (s) */
+ float decay = *(plugin->decay);
+
+ /* Sustain Level */
+ float sustain = *(plugin->sustain);
+
+ /* Release Time (s) */
+ float release = *(plugin->release);
+
+ /* Envelope Out */
+ float* output = plugin->output;
+
+ /* Instance Data */
+ float srate = plugin->srate;
+ float inv_srate = plugin->inv_srate;
+ float last_gate = plugin->last_gate;
+ float last_trigger = plugin->last_trigger;
+ float from_level = plugin->from_level;
+ float level = plugin->level;
+ DAHDSRState state = plugin->state;
+ uint32_t samples = plugin->samples;
+
+ float gat, trg, del, att, hld, dec, sus, rel;
+ float elapsed;
+
+ /* Convert times into rates */
+ del = delay > 0.0f ? inv_srate / delay : srate;
+ att = attack > 0.0f ? inv_srate / attack : srate;
+ hld = hold > 0.0f ? inv_srate / hold : srate;
+ dec = decay > 0.0f ? inv_srate / decay : srate;
+ rel = release > 0.0f ? inv_srate / release : srate;
+
+ gat = gate;
+ trg = trigger;
+ sus = f_clip(sustain, 0.0f, 1.0f);
+
+ /* Initialise delay phase if gate is opened and was closed, or
+ we received a trigger */
+ if ((trg > 0.0f && !(last_trigger > 0.0f))
+ || (gat > 0.0f && !(last_gate > 0.0f))) {
+ if (del < srate) {
+ state = DELAY;
+ } else if (att < srate) {
+ state = ATTACK;
+ } else {
+ state = hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE)));
+ level = 1.0f;
+ }
+ samples = 0;
+ }
+
+ /* Release if gate was open and now closed */
+ if (state != IDLE && state != RELEASE
+ && last_gate > 0.0f && !(gat > 0.0f)) {
+ state = rel < srate ? RELEASE : IDLE;
+ samples = 0;
+ }
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ if (samples == 0) {
+ from_level = level;
+ }
+
+ /* Calculate level of envelope from current state */
+ switch (state) {
+ case IDLE:
+ level = 0;
+ break;
+ case DELAY:
+ samples++;
+ elapsed = (float)samples * del;
+ if (elapsed > 1.0f) {
+ state = att < srate ? ATTACK
+ : (hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE))));
+ samples = 0;
+ }
+ break;
+ case ATTACK:
+ samples++;
+ elapsed = (float)samples * att;
+ if (elapsed > 1.0f) {
+ state = hld < srate ? HOLD
+ : (dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE)));
+ level = 1.0f;
+ samples = 0;
+ } else {
+ level = from_level + elapsed * (1.0f - from_level);
+ }
+ break;
+ case HOLD:
+ samples++;
+ elapsed = (float)samples * hld;
+ if (elapsed > 1.0f) {
+ state = dec < srate ? DECAY
+ : (gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE));
+ samples = 0;
+ }
+ break;
+ case DECAY:
+ samples++;
+ elapsed = (float)samples * dec;
+ if (elapsed > 1.0f) {
+ state = gat > 0.0f ? SUSTAIN
+ : (rel < srate ? RELEASE
+ : IDLE);
+ level = sus;
+ samples = 0;
+ } else {
+ level = from_level + elapsed * (sus - from_level);
+ }
+ break;
+ case SUSTAIN:
+ level = sus;
+ break;
+ case RELEASE:
+ samples++;
+ elapsed = (float)samples * rel;
+ if (elapsed > 1.0f) {
+ state = IDLE;
+ level = 0.0f;
+ samples = 0;
+ } else {
+ level = from_level - elapsed * from_level;
+ }
+ break;
+ default:
+ /* Should never happen */
+ level = 0.0f;
+ }
+
+ output[s] = level;
+ }
+
+ plugin->last_gate = gat;
+ plugin->last_trigger = trg;
+ plugin->from_level = from_level;
+ plugin->level = level;
+ plugin->state = state;
+ plugin->samples = samples;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/dahdsr",
+ instantiate,
+ connect_port,
+ activate,
+ runDahdsr_Control,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/difference.c b/src/difference.c
new file mode 100644
index 0000000..afa9183
--- /dev/null
+++ b/src/difference.c
@@ -0,0 +1,180 @@
+/*
+ An LV2 plugin to calculate the difference of two signals.
+ Copyright 2011 David Robillard
+ Copyright 2004 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+
+#define DIFFERENCE_INPUT 0
+#define DIFFERENCE_MINUS 1
+#define DIFFERENCE_OUTPUT 2
+
+typedef struct {
+ float* input;
+ float* minus;
+ float* output;
+} Difference;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Difference* plugin = (Difference*)instance;
+
+ switch (port) {
+ case DIFFERENCE_INPUT:
+ plugin->input = data;
+ break;
+ case DIFFERENCE_MINUS:
+ plugin->minus = data;
+ break;
+ case DIFFERENCE_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Difference* plugin = (Difference*)malloc(sizeof(Difference));
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+runDifference_iama_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Difference* plugin = (Difference*)instance;
+
+ /* Input (array of floats of length sample_count) */
+ float* input = plugin->input;
+
+ /* Input to Subtract (array of floats of length sample_count) */
+ float* minus = plugin->minus;
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float in;
+ float mi;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in = input[s];
+ mi = minus[s];
+
+ output[s] = in - mi;
+ }
+}
+
+static void
+runDifference_iamc_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Difference* plugin = (Difference*)instance;
+
+ /* Input (array of floats of length sample_count) */
+ float* input = plugin->input;
+
+ /* Input to Subtract (float value) */
+ float minus = *(plugin->minus);
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float in;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in = input[s];
+
+ output[s] = in - minus;
+ }
+}
+
+static void
+runDifference_icma_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Difference* plugin = (Difference*)instance;
+
+ /* Input (float value) */
+ float input = *(plugin->input);
+
+ /* Input to Subtract (array of floats of length sample_count) */
+ float* minus = plugin->minus;
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float mi;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ mi = minus[s];
+
+ output[s] = input - mi;
+ }
+}
+
+static void
+runDifference_icmc_oc(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Difference* plugin = (Difference*)instance;
+
+ /* Input (float value) */
+ float input = *(plugin->input);
+
+ /* Input to Subtract (float value) */
+ float minus = *(plugin->minus);
+
+ /* Output Frequency (pointer to float value) */
+ float* output = plugin->output;
+
+ output[0] = input - minus;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/difference",
+ instantiate,
+ connect_port,
+ NULL,
+ runDifference_icmc_oc,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/fmod.c b/src/fmod.c
new file mode 100644
index 0000000..ce3a8f4
--- /dev/null
+++ b/src/fmod.c
@@ -0,0 +1,192 @@
+/*
+ An LV2 plugin to modulate a frequency by a signal.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "math_func.h"
+
+#define FMOD_FREQUENCY 0
+#define FMOD_MODULATOR 1
+#define FMOD_OUTPUT 2
+
+typedef struct {
+ float* frequency;
+ float* modulator;
+ float* output;
+} Fmod;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Fmod* plugin = (Fmod*)instance;
+
+ switch (port) {
+ case FMOD_FREQUENCY:
+ plugin->frequency = data;
+ break;
+ case FMOD_MODULATOR:
+ plugin->modulator = data;
+ break;
+ case FMOD_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Fmod* plugin = (Fmod*)malloc(sizeof(Fmod));
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+runFmod_fama_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Fmod* plugin = (Fmod*)instance;
+
+ /* Frequency to Modulate (array of floats of length sample_count) */
+ float* frequency = plugin->frequency;
+
+ /* LFO Input (array of floats of length sample_count) */
+ float* modulator = plugin->modulator;
+
+ /* Output Frequency (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float freq;
+ float mod;
+ float scale;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ freq = frequency[s];
+ mod = modulator[s];
+
+ scale = (float)EXPF(M_LN2 * mod);
+
+ output[s] = scale * freq;
+ }
+}
+
+static void
+runFmod_famc_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Fmod* plugin = (Fmod*)instance;
+
+ /* Frequency to Modulate (array of floats of length sample_count) */
+ float* frequency = plugin->frequency;
+
+ /* Shift (Octaves) (float value) */
+ float modulator = *(plugin->modulator);
+
+ /* Output Frequency (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float freq;
+ float scale = (float)EXPF(M_LN2 * modulator);
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ freq = frequency[s];
+
+ output[s] = scale * freq;
+ }
+}
+
+static void
+runFmod_fcma_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Fmod* plugin = (Fmod*)instance;
+
+ /* Frequency to Modulate (float value) */
+ float frequency = *(plugin->frequency);
+
+ /* LFO Input (array of floats of length sample_count) */
+ float* modulator = plugin->modulator;
+
+ /* Output Frequency (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float mod;
+ float scale;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ mod = modulator[s];
+
+ scale = (float)EXPF(M_LN2 * mod);
+
+ output[s] = scale * frequency;
+ }
+}
+
+static void
+runFmod_fcmc_oc(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Fmod* plugin = (Fmod*)instance;
+
+ /* Frequency to Modulate (float value) */
+ float frequency = *(plugin->frequency);
+
+ /* Shift (Octaves) (float value) */
+ float modulator = *(plugin->modulator);
+
+ /* Output Frequency (pointer to float value) */
+ float* output = plugin->output;
+
+ float scale;
+
+ scale = (float)EXPF(M_LN2 * modulator);
+
+ output[0] = scale * frequency;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/fmod",
+ instantiate,
+ connect_port,
+ NULL,
+ runFmod_fcmc_oc,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/include/common.h b/src/include/common.h
new file mode 100644
index 0000000..0f30aa1
--- /dev/null
+++ b/src/include/common.h
@@ -0,0 +1,54 @@
+/*
+ Common definitions.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef blip_common_h
+#define blip_common_h
+
+#include "math_func.h"
+
+/* Handy constants and macros */
+
+#ifndef SMALLEST_FLOAT
+/** Smallest generated non-zero float, used for pre-empting denormals */
+#define SMALLEST_FLOAT (1.0 / (float)0xFFFFFFFF)
+#endif
+
+/*
+ * Clip without branch (from http://musicdsp.org)
+ */
+
+static inline float
+f_min (float x, float a)
+{
+ return a - (a - x + FABSF (a - x)) * 0.5f;
+}
+
+static inline float
+f_max (float x, float b)
+{
+ return (x - b + FABSF (x - b)) * 0.5f + b;
+}
+
+static inline float
+f_clip (float x, float a, float b)
+{
+ return 0.5f * (FABSF (x - a) + a + b - FABSF (x - b));
+}
+
+#endif /* blip_common_h */
diff --git a/src/include/interpolate.h b/src/include/interpolate.h
new file mode 100644
index 0000000..d61fb3e
--- /dev/null
+++ b/src/include/interpolate.h
@@ -0,0 +1,75 @@
+#ifndef blip_interpolate_h
+#define blip_interpolate_h
+
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include <config.h>
+#include "math_func.h"
+
+/**
+ Interpolate between p0 and n0 taking the previous (p1) and next (n1) points
+ into account, using a 3rd order polynomial (a.k.a. cubic spline).
+ @param interval Normalised time interval between intepolated sample and p0
+ @param p1 Sample two previous to interpolated one
+ @param p0 Previous sample to interpolated one
+ @param n0 Sample following interpolated one
+ @param n1 Sample following n0
+ @return Interpolated sample.
+
+ Adapted from Steve Harris' plugin code
+ swh-plugins-0.2.7/ladspa-util.h::cube_interp
+ http://plugin.org.uk/releases/0.2.7/
+*/
+static inline float
+interpolate_cubic(float interval,
+ float p1,
+ float p0,
+ float n0,
+ float n1)
+{
+ return p0 + 0.5f * interval * (n0 - p1 +
+ interval * (4.0f * n0 + 2.0f * p1 - 5.0f * p0 - n1 +
+ interval * (3.0f * (p0 - n0) - p1 + n1)));
+}
+
+/**
+ Interpolate between p0 and n0 taking the previous (p1) and next (n1) points
+ into account, using a 5th order polynomial.
+ @param interval Normalised time interval between intepolated sample and p0
+ @param p1 Sample two previous to interpolated one
+ @param p0 Previous sample to interpolated one
+ @param n0 Sample following interpolated one
+ @param n1 Sample following n0
+ @return Interpolated sample.
+
+ Adapted from http://www.musicdsp.org/archive.php?classid=5#62
+*/
+static inline float
+interpolate_quintic(float interval,
+ float p1,
+ float p0,
+ float n0,
+ float n1)
+{
+ return p0 + 0.5f * interval * (n0 - p1 +
+ interval * (n0 - 2.0f * p0 + p1 +
+ interval * ( 9.0f * (n0 - p0) + 3.0f * (p1 - n1) +
+ interval * (15.0f * (p0 - n0) + 5.0f * (n1 - p1) +
+ interval * ( 6.0f * (n0 - p0) + 2.0f * (p1 - n1))))));
+}
+
+/**
+ Linear interpolation
+*/
+static inline float
+f_lerp (float value,
+ float v1,
+ float v2)
+{
+ value -= LRINTF (value - 0.5f);
+ value *= (v2 - v1);
+ value += v1;
+
+ return value;
+}
+
+#endif /* blip_interpolate_h */
diff --git a/src/include/lp4pole_filter.h b/src/include/lp4pole_filter.h
new file mode 100644
index 0000000..adc5cba
--- /dev/null
+++ b/src/include/lp4pole_filter.h
@@ -0,0 +1,137 @@
+/*
+ Header for lp4pole_filter struct, and functions to run instance.
+ Copyright 2011 David Robillard
+ Copyright 2003 Mike Rawes
+
+ Originally originally appeared in CSound as Timo Tossavainen's (sp?)
+ implementation from the Stilson/Smith CCRMA paper.
+
+ See http://musicdsp.org/archive.php?classid=3#26
+
+ Originally appeared in the arts softsynth by Stefan Westerfeld:
+ http://www.arts-project.org/
+
+ First ported to LADSPA by Reiner Klenk (pdq808[at]t-online.de)
+
+ Tuning and stability issues (output NaN) and additional audio-rate
+ variant added by Mike Rawes (mike_rawes[at]yahoo.co.uk)
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef blip_lp4pole_filter_h
+#define blip_lp4pole_filter_h
+
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "common.h"
+
+typedef struct {
+ float f;
+ float coeff;
+ float fb;
+ float in1;
+ float in2;
+ float in3;
+ float in4;
+ float inv_nyquist;
+ float out1;
+ float out2;
+ float out3;
+ float out4;
+ float max_abs_in;
+} LP4PoleFilter;
+
+/**
+ Allocate a new LP4PoleFilter instance.
+ @param sample_rate Intended playback (DAC) rate
+ @return Allocated LP4PoleFilter instance
+*/
+LP4PoleFilter* lp4pole_new(double sample_rate);
+
+/**
+ Cleanup an existing LP4PoleFilter instance.
+ @param lpf Pointer to LP4PoleFilter instance allocated with initFilter
+*/
+void lp4pole_cleanup(LP4PoleFilter* lpf);
+
+/**
+ Initialise filter.
+ @param lpf Pointer to LP4PoleFilter instance allocated with initFilter
+*/
+void lp4pole_init(LP4PoleFilter* lpf);
+
+/**
+ Set up filter coefficients for given LP4Pole instance.
+ @param lpf Pointer to LP4PoleFilter instance
+ @param cutoff Cutoff frequency in Hz
+ @param resonance Resonance [Min=0.0, Max=4.0]
+*/
+static inline void
+lp4pole_set_params(LP4PoleFilter* lpf,
+ float cutoff,
+ float resonance)
+{
+ float fsqd;
+ float tuning;
+
+ /* Normalise cutoff and find tuning - Magic numbers found empirically :) */
+ lpf->f = cutoff * lpf->inv_nyquist;
+ tuning = f_clip(3.13f - (lpf->f * 4.24703592f), 1.56503274f, 3.13f);
+
+ /* Clip to bounds */
+ lpf->f = f_clip(lpf->f * tuning, lpf->inv_nyquist, 1.16f);
+
+ fsqd = lpf->f * lpf->f;
+ lpf->coeff = fsqd * fsqd * 0.35013f;
+
+ lpf->fb = f_clip(resonance, -1.3f, 4.0f) * (1.0f - 0.15f * fsqd);
+
+ lpf->f = 1.0f - lpf->f;
+}
+
+/**
+ Run given LP4PoleFilter instance for a single sample.
+ @param lpf Pointer to LP4PoleFilter instance
+ @param in Input sample
+ @return Filtered sample
+*/
+static inline float
+lp4pole_run(LP4PoleFilter* lpf,
+ float in)
+{
+ float abs_in = fabsf(16.0f * in); /* ~24dB unclipped headroom */
+
+ lpf->max_abs_in = f_max(lpf->max_abs_in, abs_in);
+
+ in -= lpf->out4 * lpf->fb;
+ in *= lpf->coeff;
+
+ lpf->out1 = in + 0.3f * lpf->in1 + lpf->f * lpf->out1; /* Pole 1 */
+ lpf->in1 = in;
+ lpf->out2 = lpf->out1 + 0.3f * lpf->in2 + lpf->f * lpf->out2; /* Pole 2 */
+ lpf->in2 = lpf->out1;
+ lpf->out3 = lpf->out2 + 0.3f * lpf->in3 + lpf->f * lpf->out3; /* Pole 3 */
+ lpf->in3 = lpf->out2;
+ lpf->out4 = lpf->out3 + 0.3f * lpf->in4 + lpf->f * lpf->out4; /* Pole 4 */
+ lpf->in4 = lpf->out3;
+
+ /* Simple hard clip to prevent NaN */
+ lpf->out4 = f_clip(lpf->out4, -lpf->max_abs_in, lpf->max_abs_in);
+
+ lpf->max_abs_in *= 0.999f;
+
+ return lpf->out4;
+}
+
+#endif /* blip_lp4pole_filter_h */
diff --git a/src/include/math_func.h b/src/include/math_func.h
new file mode 100644
index 0000000..c44075d
--- /dev/null
+++ b/src/include/math_func.h
@@ -0,0 +1,36 @@
+/*
+ * Provide double fallbacks for environments lacking sinf and
+ * friends (e.g. Solaris)
+ */
+
+#ifndef math_func_h
+#define math_func_h
+
+#include <math.h>
+#include "config.h"
+
+#ifdef HAVE_SINF
+/* Use float functions */
+#define SINF(x) sinf(x)
+#define COSF(x) cosf(x)
+#define FABSF(x) fabsf(x)
+#define FLOORF(x) floorf(x)
+#define EXPF(x) expf(x)
+#define POWF(x,p) powf(x,p)
+#define COPYSIGNF(s,d) copysignf(s,d)
+#define LRINTF(x) lrintf(x)
+
+#else
+/* Use double functions */
+#define SINF(x) sin(x)
+#define COSF(x) cos(x)
+#define FABSF(x) fabs(x)
+#define FLOORF(x) floor(x)
+#define EXPF(x) exp(x)
+#define POWF(x,p) pow(x)
+#define COPYSIGNF(s,d) copysign(s,d)
+#define LRINTF(x) lrint(x)
+
+#endif
+
+#endif
diff --git a/src/include/wavedata.h b/src/include/wavedata.h
new file mode 100644
index 0000000..82bc70f
--- /dev/null
+++ b/src/include/wavedata.h
@@ -0,0 +1,192 @@
+/*
+ Structures to represent a set of wavetables.
+ Copyright 2011 David Robillard
+ Copyright 2003 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef blip_wavedata_h
+#define blip_wavedata_h
+
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include <config.h>
+#include "math_func.h"
+#include "interpolate.h"
+#include "common.h"
+
+/* Functions identifying wavedata dlls */
+#define BLOP_DLSYM_SAWTOOTH "blip_get_sawtooth"
+#define BLOP_DLSYM_SQUARE "blip_get_square"
+#define BLOP_DLSYM_PARABOLA "blip_get_parabola"
+
+/*
+ * Structure holding a single segment of sample data
+ * along with information relating to playback.
+ */
+typedef struct {
+ unsigned long sample_count; /* Sample count */
+ float* samples_lf; /* Sample data played back at amplitude
+ inversely proportional to frequency */
+ float* samples_hf; /* Sample data played back at amplitude
+ proportional to frequency */
+ unsigned long harmonics; /* Max harmonic content of sample data */
+
+ float phase_scale_factor; /* Phase scale factor for playback */
+ float min_frequency; /* Minimum playback frequency */
+ float max_frequency; /* Maximum playback frequency */
+ float range_scale_factor; /* Blend scale factor for cross fading */
+} Wavetable;
+
+/*
+ * Structure holding the wavetable data and playback state
+ */
+typedef struct {
+ void* data_handle; /* Data DLL handle */
+ unsigned long table_count; /* Number of wavetables in wavedata */
+ Wavetable** tables; /* One or more wavetables, plus pair of
+ extra tables for frequency extremes */
+ unsigned long* lookup; /* Wavetable lookup vector */
+ unsigned long lookup_max; /* For clipping lookup indices */
+
+ float sample_rate; /* Sample rate */
+ float nyquist; /* Nyquist rate (sample_rate / 2) */
+
+ /* Playback state */
+ float frequency; /* Current playback frequency */
+ float abs_freq; /* Absolute playback frequency */
+ float xfade; /* Crossfade factor for fading */
+ Wavetable* table; /* Wavetable to playback */
+} Wavedata;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int wavedata_load(Wavedata* w,
+ const char* wdat_descriptor_name,
+ unsigned long sample_rate);
+
+void wavedata_unload(Wavedata* w);
+
+/*****************************************************************************
+ * Description: Get interpolated sample from current wavetable in wavedata
+ * at given phase offset
+ *
+ * Arguments: w Wavedata containing playback state and data
+ * phase Phase offset [0.0, sample_rate]
+ *
+ * Returns: Interpolated sample
+ *
+ * Notes: Cubic (or quintic) interpolation requires four consecutive
+ * samples for operation:
+ *
+ * phase
+ * :
+ * p1 p0 : n0 n1
+ * | | x | |
+ * : :
+ * <-o->
+ * :
+ * interval
+ *
+ * Phase values less than one make p0 the first sample in
+ * the table - p1 will be the last sample, as a previous
+ * sample does not exist. To avoid checking for this case,
+ * a copy of the last sample is stored before the first
+ * sample in each table.
+ * Likewise, if the phase means p0 is the last sample, n0
+ * and n1 will be the first and second samples respectively.
+ * Copies of these samples are stored after the last sample
+ * in each table.
+ *
+ *****************************************************************************/
+static inline float
+wavedata_get_sample(Wavedata* w,
+ float phase)
+{
+ float* samples_hf = w->table->samples_hf;
+ float* samples_lf = w->table->samples_lf;
+ float p1, p0, n0, n1;
+ float phase_f;
+ long int index;
+
+ /* Scale phase to map to position in wavetable */
+ phase *= w->table->phase_scale_factor;
+
+ /* Get position of first contributing sample (p1) */
+ index = LRINTF((float)phase - 0.5f);
+ phase_f = (float)index;
+
+ index %= w->table->sample_count;
+
+ /* Cross-fade table pairs */
+ /* Previous two samples */
+ p1 = w->xfade * (samples_lf[index] - samples_hf[index]) + samples_hf[index];
+ index++;
+ p0 = w->xfade * (samples_lf[index] - samples_hf[index]) + samples_hf[index];
+ index++;
+ /* Next two samples */
+ n0 = w->xfade * (samples_lf[index] - samples_hf[index]) + samples_hf[index];
+ index++;
+ n1 = w->xfade * (samples_lf[index] - samples_hf[index]) + samples_hf[index];
+
+ /* Return interpolated sample */
+ return interpolate_cubic(phase - phase_f, p1, p0, n0, n1);
+}
+
+/*****************************************************************************
+ * Description: Get wavetable to use for playback frequency.
+ *
+ * Arguments: w Wavedata object (contains all table info)
+ * frequency Playback frequency
+ *
+ * Notes: The lookup vector used to determine the wavetable
+ * is indexed by harmonic number.
+ *
+ * The maximum playback frequency for a wavetable is
+ * determined by its harmonic content and the sample rate,
+ * and equals sample_rate / 2 / max_harmonic_in_table.
+ *
+ *****************************************************************************/
+static inline void
+wavedata_get_table(Wavedata* w,
+ float frequency)
+{
+ unsigned long harmonic;
+
+ w->frequency = frequency;
+ w->abs_freq = (float)FABSF((float)frequency);
+
+ /* Get highest harmonic possible in frequency */
+ harmonic = LRINTF(w->nyquist / w->abs_freq - 0.5f);
+
+ /* Clip so lookup is within bounds */
+ if (harmonic > w->lookup_max) {
+ harmonic = w->lookup_max;
+ }
+
+ /* Set playback table */
+ w->table = w->tables[w->lookup[harmonic]];
+
+ /* Get cross fade factor */
+ w->xfade = f_max(w->table->max_frequency - w->abs_freq, 0.0f) * w->table->range_scale_factor;
+ w->xfade = f_min(w->xfade, 1.0f);
+}
+
+#ifdef __cplusplus
+} /* extern "C" { */
+#endif
+
+#endif /* blip_wavedata_h */
diff --git a/src/include/wdatutil.h b/src/include/wdatutil.h
new file mode 100644
index 0000000..d7bca80
--- /dev/null
+++ b/src/include/wdatutil.h
@@ -0,0 +1,141 @@
+/*
+ Code to generate wavedata dl containing pre-calculated wavetables.
+ Copyright 2011 David Robillard
+ Copyright 2003 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef blip_wdatutil_h
+#define blip_wdatutil_h
+
+#include <stdio.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "math_func.h"
+#include "wavedata.h"
+
+#define WAVE_TYPE_COUNT 3
+
+extern char* wave_names[];
+extern char* wave_descriptions[];
+extern unsigned long wave_first_harmonics[];
+extern unsigned long wave_harmonic_intervals[];
+
+/** Get actual maximum harmonic from given harmonic, h, and wavetype, w */
+#define ACTUAL_HARM(h, w) h - (h - wave_first_harmonics[w]) % wave_harmonic_intervals[w]
+
+/** Get minimum harmonic content in given wavetype, w */
+#define MIN_HARM(w) wave_first_harmonics[w]
+
+/** Get minimum extra harmonic content possible in given wavetype, w */
+#define MIN_EXTRA_HARM(w) wave_harmonic_intervals[w]
+
+/** Get frequency from MIDI note, n */
+#define FREQ_FROM_NOTE(n) 6.875f * POWF(2.0f, (float)(n + 3) / 12.0f)
+
+/** Get max harmonic from given frequency, f, at sample rate, r */
+#define HARM_FROM_FREQ(f, r) (unsigned long)((float)r / f / 2.0f)
+
+/*
+ * A single wavetable will have a range of pitches at which their samples
+ * may be played back.
+ *
+ * The upper bound is determined by the maximum harmonic present in the
+ * waveform - above this frequency, the higher harmonics will alias.
+ *
+ * The lower bound is chosen to be the higher bound of the previous wavetable
+ * (or a pre-defined limit if there is no such table).
+ */
+
+typedef enum {
+ SAW,
+ SQUARE,
+ PARABOLA
+} Wavetype;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+ * Description: Allocate new wavedata struct
+ *
+ * Arguments: sample_rate Sample rate to use when generating data
+ *
+ * Returns: Pointer to wavedata on success
+ * NULL (0) on failure
+ *
+ * Notes: No wavetables are allocated. Use wavedata_add_table
+ ******************************************************************************/
+Wavedata* wavedata_new(unsigned long sample_rate);
+
+/*******************************************************************************
+ * Description: Destroy allocated wavedata and any tables
+ *
+ * Arguments: w Wavedata struct to cleanup
+ ******************************************************************************/
+void wavedata_cleanup(Wavedata* w);
+
+/*******************************************************************************
+ * Description: Add new wavetable information to wavedata file object
+ *
+ * Arguments: w Wavedata to add table to
+ * sample_count Number of samples in wavetable
+ * harmonics Maximum harmonics present in table
+ *
+ * Returns: 0 on success
+ * -1 otherwise
+ ******************************************************************************/
+int wavedata_add_table(Wavedata* w,
+ unsigned long sample_count,
+ unsigned long harmonics);
+
+/*******************************************************************************
+ * Description: Initialise all wavetables in wavedata with a waveform
+ * generated from Fourier series.
+ *
+ * Arguments: w Wavedata to generate data for
+ * wavetype Wavetype to generate
+ * gibbs_comp Compensation for Gibbs' effect:
+ * 0.0: none (wave will overshoot)
+ * 1.0: full (wave will not overshoot)
+ *
+ * Notes: Compensation for Gibbs' Effect will reduce the degree
+ * of overshoot and ripple at the transitions. A value of 1.0
+ * will pretty much eliminate it.
+ ******************************************************************************/
+void wavedata_generate_tables(Wavedata* w,
+ Wavetype wavetype,
+ float gibbs_comp);
+
+/*******************************************************************************
+ * Description: Write wavedata as a c header file
+ *
+ * Arguments: w Wavedata to write
+ * wdat_fp Pointer to output file
+ * prefix Prefix to use in declarations. If this is null
+ * declarations are prefixed with 'wdat'.
+ *
+ * Returns: 0 on success
+ * -1 otherwise
+ ******************************************************************************/
+int wavedata_write(Wavedata* w,
+ FILE* wdat_fp,
+ char* prefix);
+
+#ifdef __cplusplus
+} /* extern "C" { */
+#endif
+
+#endif /* blip_wdatutil_h */
diff --git a/src/interpolator.c b/src/interpolator.c
new file mode 100644
index 0000000..0324239
--- /dev/null
+++ b/src/interpolator.c
@@ -0,0 +1,142 @@
+/*
+ An LV2 plugin to generate a smooth audio signal from a control source.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+
+#define INTERPOLATOR_INPUT 0
+#define INTERPOLATOR_OUTPUT 1
+
+/**
+ Mutated spline interpolator using only two previous samples and one next.
+ @param interval Normalised time interval between inteprolated sample and p0
+ @param p1 Sample two previous to interpolated one
+ @param p0 Previous sample to interpolated one
+ @param n0 Sample following interpolated one
+ @return Interpolated sample.
+*/
+static inline float
+interpolate(float interval,
+ float p1,
+ float p0,
+ float n0)
+{
+ return p0 + 0.5f * interval * (n0 - p1 +
+ interval * (4.0f * n0 + 2.0f * p1 - 5.0f * p0 - n0 +
+ interval * (3.0f * (p0 - n0) - p1 + n0)));
+}
+
+typedef struct {
+ float* input;
+ float* output;
+ float p1;
+ float p0;
+} Interpolator;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Interpolator* plugin = (Interpolator*)instance;
+
+ switch (port) {
+ case INTERPOLATOR_INPUT:
+ plugin->input = data;
+ break;
+ case INTERPOLATOR_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Interpolator* plugin = (Interpolator*)malloc(sizeof(Interpolator));
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Interpolator* plugin = (Interpolator*)instance;
+
+ plugin->p1 = 0.0f;
+ plugin->p0 = 0.0f;
+}
+
+static void
+runInterpolator(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Interpolator* plugin = (Interpolator*)instance;
+
+ /* Control Input (float value) */
+ float input = *(plugin->input);
+
+ /* Interpolated Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* We use two previous values and the input as the 'next' one */
+ float p1 = plugin->p1;
+ float p0 = plugin->p0;
+
+ float interval;
+ float inv_scount = 1.0f / (float)sample_count;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ interval = (float)s * inv_scount;
+
+ output[s] = interpolate(interval, p1, p0, input);
+ }
+
+ plugin->p1 = p0;
+ plugin->p0 = input;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/interpolator",
+ instantiate,
+ connect_port,
+ activate,
+ runInterpolator,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/lp4pole.c b/src/lp4pole.c
new file mode 100644
index 0000000..d72cb98
--- /dev/null
+++ b/src/lp4pole.c
@@ -0,0 +1,182 @@
+/*
+ An LV2 plugin simulating a 4 pole low pass resonant filter.
+ Copyright 2011 David Robillard
+ Copyright 2003 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "lp4pole_filter.h"
+#include "common.h"
+
+#define LP4POLE_CUTOFF 0
+#define LP4POLE_RESONANCE 1
+#define LP4POLE_INPUT 2
+#define LP4POLE_OUTPUT 3
+
+typedef struct {
+ float* cutoff;
+ float* resonance;
+ float* input;
+ float* output;
+ LP4PoleFilter* lpf;
+} Lp4pole;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ Lp4pole* plugin = (Lp4pole*)instance;
+
+ lp4pole_cleanup(plugin->lpf);
+
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Lp4pole* plugin = (Lp4pole*)instance;
+
+ switch (port) {
+ case LP4POLE_CUTOFF:
+ plugin->cutoff = data;
+ break;
+ case LP4POLE_RESONANCE:
+ plugin->resonance = data;
+ break;
+ case LP4POLE_INPUT:
+ plugin->input = data;
+ break;
+ case LP4POLE_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Lp4pole* plugin = (Lp4pole*)malloc(sizeof(Lp4pole));
+
+ if (plugin) {
+ plugin->lpf = lp4pole_new(sample_rate);
+ if (!plugin->lpf) {
+ free(plugin);
+ plugin = 0;
+ }
+ }
+ return (LV2_Handle)plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Lp4pole* plugin = (Lp4pole*)instance;
+
+ lp4pole_init(plugin->lpf);
+}
+
+static void
+runLp4pole_faraia_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Lp4pole* plugin = (Lp4pole*)instance;
+
+ /* Cutoff Frequency (array of floats of length sample_count) */
+ float* cutoff = plugin->cutoff;
+
+ /* Resonance (array of floats of length sample_count) */
+ float* resonance = plugin->resonance;
+
+ /* Input (array of floats of length sample_count) */
+ float* input = plugin->input;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ LP4PoleFilter* lpf = plugin->lpf;
+
+ float in;
+ float co;
+ float res;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ co = cutoff[s];
+ res = resonance[s];
+ in = input[s];
+
+ lp4pole_set_params(lpf, co, res);
+
+ output[s] = lp4pole_run(lpf, in);
+ }
+}
+
+static void
+runLp4pole_fcrcia_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Lp4pole* plugin = (Lp4pole*)instance;
+
+ /* Cutoff Frequency (float value) */
+ float cutoff = *(plugin->cutoff);
+
+ /* Resonance (float value) */
+ float resonance = *(plugin->resonance);
+
+ /* Input (array of floats of length sample_count) */
+ float* input = plugin->input;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ LP4PoleFilter* lpf = plugin->lpf;
+
+ float in;
+
+ lp4pole_set_params(lpf, cutoff, resonance);
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in = input[s];
+ output[s] = lp4pole_run(lpf, in);
+ }
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/lp4pole",
+ instantiate,
+ connect_port,
+ activate,
+ runLp4pole_fcrcia_oa,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/lp4pole_filter.c b/src/lp4pole_filter.c
new file mode 100644
index 0000000..7d54691
--- /dev/null
+++ b/src/lp4pole_filter.c
@@ -0,0 +1,55 @@
+/*
+ lp4pole filter admin.
+ Copyright 2011 David Robillard
+ Copyright 2003 Mike Rawes
+
+ See lp4pole_filter.h for history
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "lp4pole_filter.h"
+
+LP4PoleFilter*
+lp4pole_new(double sample_rate)
+{
+ LP4PoleFilter* lpf;
+
+ lpf = (LP4PoleFilter*)malloc(sizeof(LP4PoleFilter));
+
+ if (lpf) {
+ lpf->inv_nyquist = 2.0f / sample_rate;
+ lp4pole_init(lpf);
+ }
+
+ return lpf;
+}
+
+void
+lp4pole_cleanup(LP4PoleFilter* lpf)
+{
+ if (lpf) {
+ free(lpf);
+ }
+}
+
+void
+lp4pole_init(LP4PoleFilter* lpf)
+{
+ lpf->in1 = lpf->in2 = lpf->in3 = lpf->in4 = 0.0f;
+ lpf->out1 = lpf->out2 = lpf->out3 = lpf->out4 = 0.0f;
+ lpf->max_abs_in = 0.0f;
+}
diff --git a/src/product.c b/src/product.c
new file mode 100644
index 0000000..5c0b488
--- /dev/null
+++ b/src/product.c
@@ -0,0 +1,156 @@
+/*
+ An LV2 plugin to calculate the product of two signals.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+
+#define PRODUCT_INPUT1 0
+#define PRODUCT_INPUT2 1
+#define PRODUCT_OUTPUT 2
+
+typedef struct {
+ float* input1;
+ float* input2;
+ float* output;
+} Product;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Product* plugin = (Product*)instance;
+
+ switch (port) {
+ case PRODUCT_INPUT1:
+ plugin->input1 = data;
+ break;
+ case PRODUCT_INPUT2:
+ plugin->input2 = data;
+ break;
+ case PRODUCT_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Product* plugin = (Product*)malloc(sizeof(Product));
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+runProduct_iaia_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Product* plugin = (Product*)instance;
+
+ /* First Input (array of floats of length sample_count) */
+ float* input1 = plugin->input1;
+
+ /* Second Input (array of floats of length sample_count) */
+ float* input2 = plugin->input2;
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float in1;
+ float in2;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in1 = input1[s];
+ in2 = input2[s];
+
+ output[s] = in1 * in2;
+ }
+}
+
+static void
+runProduct_iaic_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Product* plugin = (Product*)instance;
+
+ /* First Input (array of floats of length sample_count) */
+ float* input1 = plugin->input1;
+
+ /* Second Input (float value) */
+ float input2 = *(plugin->input2);
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float in1;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in1 = input1[s];
+
+ output[s] = in1 * input2;
+ }
+}
+
+static void
+runProduct_icic_oc(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Product* plugin = (Product*)instance;
+
+ /* First Input (float value) */
+ float input1 = *(plugin->input1);
+
+ /* Second Input (float value) */
+ float input2 = *(plugin->input2);
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ output[0] = input1 * input2;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/product",
+ instantiate,
+ connect_port,
+ NULL,
+ runProduct_icic_oc,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/pulse.c b/src/pulse.c
new file mode 100644
index 0000000..17c8525
--- /dev/null
+++ b/src/pulse.c
@@ -0,0 +1,288 @@
+/*
+ An LV2 plugin to generate a bandlimited variable pulse waveform.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "wavedata.h"
+
+#define PULSE_FREQUENCY 0
+#define PULSE_PULSEWIDTH 1
+#define PULSE_OUTPUT 2
+
+typedef struct {
+ float* frequency;
+ float* pulsewidth;
+ float* output;
+ float phase;
+ Wavedata wdat;
+} Pulse;
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Pulse* plugin = (Pulse*)instance;
+
+ switch (port) {
+ case PULSE_FREQUENCY:
+ plugin->frequency = data;
+ break;
+ case PULSE_PULSEWIDTH:
+ plugin->pulsewidth = data;
+ break;
+ case PULSE_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Pulse* plugin = (Pulse*)malloc(sizeof(Pulse));
+
+ if (wavedata_load(&plugin->wdat, BLOP_DLSYM_SAWTOOTH, sample_rate)) {
+ free(plugin);
+ return 0;
+ }
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ Pulse* plugin = (Pulse*)instance;
+
+ wavedata_unload(&plugin->wdat);
+ free(instance);
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Pulse* plugin = (Pulse*)instance;
+
+ plugin->phase = 0.0f;
+}
+
+static void
+runPulse_fapa_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Pulse* plugin = (Pulse*)instance;
+
+ /* Frequency (array of float of length sample_count) */
+ float* frequency = plugin->frequency;
+
+ /* Pulse Width (array of float of length sample_count) */
+ float* pulsewidth = plugin->pulsewidth;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ Wavedata* wdat = &plugin->wdat;
+ float phase = plugin->phase;
+
+ float freq;
+ float pwidth;
+ float phase_shift;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ freq = frequency[s];
+ pwidth = f_clip(pulsewidth[s], 0.0f, 1.0f);
+ phase_shift = pwidth * wdat->sample_rate;
+
+ /* Lookup which table to use from frequency */
+ wavedata_get_table(wdat, freq);
+
+ /* Get samples from sawtooth and phase shifted inverted sawtooth,
+ with approriate DC offset */
+ output[s] = wavedata_get_sample(wdat, phase)
+ - wavedata_get_sample(wdat, phase + phase_shift)
+ + 1.0f - (2.0f * pwidth);
+
+ /* Update phase, wrapping if necessary */
+ phase += wdat->frequency;
+ if (phase < 0.0f) {
+ phase += wdat->sample_rate;
+ } else if (phase > wdat->sample_rate) {
+ phase -= wdat->sample_rate;
+ }
+ }
+ plugin->phase = phase;
+}
+
+static void
+runPulse_fapc_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Pulse* plugin = (Pulse*)instance;
+
+ /* Frequency (array of float of length sample_count) */
+ float* frequency = plugin->frequency;
+
+ /* Pulse Width (float value) */
+ float pulsewidth = f_clip(*(plugin->pulsewidth), 0.0f, 1.0f);
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ Wavedata* wdat = &plugin->wdat;
+ float phase = plugin->phase;
+
+ float freq;
+ float dc_shift = 1.0 - (2.0 * pulsewidth);
+ float phase_shift = pulsewidth * wdat->sample_rate;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ freq = frequency[s];
+
+ /* Lookup which table to use from frequency */
+ wavedata_get_table(wdat, freq);
+
+ /* Get samples from sawtooth and phase shifted inverted sawtooth,
+ with approriate DC offset */
+ output[s] = wavedata_get_sample(wdat, phase)
+ - wavedata_get_sample(wdat, phase + phase_shift)
+ + dc_shift;
+
+ /* Update phase, wrapping if necessary */
+ phase += wdat->frequency;
+ if (phase < 0.0f) {
+ phase += wdat->sample_rate;
+ } else if (phase > wdat->sample_rate) {
+ phase -= wdat->sample_rate;
+ }
+ }
+ plugin->phase = phase;
+}
+
+static void
+runPulse_fcpa_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Pulse* plugin = (Pulse*)instance;
+
+ /* Frequency (float value) */
+ float frequency = *(plugin->frequency);
+
+ /* Pulse Width (array of float of length sample_count) */
+ float* pulsewidth = plugin->pulsewidth;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ Wavedata* wdat = &plugin->wdat;
+ float phase = plugin->phase;
+
+ float pwidth;
+ float phase_shift;
+
+ wavedata_get_table(wdat, frequency);
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ pwidth = f_clip(pulsewidth[s], 0.0f, 1.0f);
+ phase_shift = pwidth * wdat->sample_rate;
+
+ /* Get samples from sawtooth and phase shifted inverted sawtooth,
+ with approriate DC offset */
+ output[s] = wavedata_get_sample(wdat, phase)
+ - wavedata_get_sample(wdat, phase + phase_shift)
+ + 1.0f - (2.0f * pwidth);
+
+ /* Update phase, wrapping if necessary */
+ phase += wdat->frequency;
+ if (phase < 0.0f) {
+ phase += wdat->sample_rate;
+ } else if (phase > wdat->sample_rate) {
+ phase -= wdat->sample_rate;
+ }
+ }
+ plugin->phase = phase;
+}
+
+static void
+runPulse_fcpc_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Pulse* plugin = (Pulse*)instance;
+
+ /* Frequency (float value) */
+ float frequency = *(plugin->frequency);
+
+ /* Pulse Width (float value) */
+ float pulsewidth = f_clip(*(plugin->pulsewidth), 0.0f, 1.0f);
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ Wavedata* wdat = &plugin->wdat;
+ float phase = plugin->phase;
+
+ float dc_shift = 1.0f - (2.0f * pulsewidth);
+ float phase_shift = pulsewidth * wdat->sample_rate;
+
+ wavedata_get_table(wdat, frequency);
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ /* Get samples from sawtooth and phase shifted inverted sawtooth,
+ with approriate DC offset */
+ output[s] = wavedata_get_sample(wdat, phase)
+ - wavedata_get_sample(wdat, phase + phase_shift)
+ + dc_shift;
+
+ /* Update phase, wrapping if necessary */
+ phase += wdat->frequency;
+ if (phase < 0.0f) {
+ phase += wdat->sample_rate;
+ } else if (phase > wdat->sample_rate) {
+ phase -= wdat->sample_rate;
+ }
+ }
+ plugin->phase = phase;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/pulse",
+ instantiate,
+ connect_port,
+ activate,
+ runPulse_fcpc_oa,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/quantiser.c b/src/quantiser.c
new file mode 100644
index 0000000..ce28866
--- /dev/null
+++ b/src/quantiser.c
@@ -0,0 +1,474 @@
+/*
+ An LV2 plugin to quantise an input to a set of fixed values.
+ Copyright 2011 David Robillard
+ Copyright 2003 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "math_func.h"
+#include "common.h"
+
+#define QUANTISER_RANGE_MIN 0
+#define QUANTISER_RANGE_MAX 1
+#define QUANTISER_MATCH_RANGE 2
+#define QUANTISER_MODE 3
+#define QUANTISER_COUNT 4
+#define QUANTISER_VALUE_START 5
+#define QUANTISER_INPUT (QUANTISER_MAX_INPUTS + 5)
+#define QUANTISER_OUTPUT (QUANTISER_MAX_INPUTS + 6)
+#define QUANTISER_OUTPUT_CHANGED (QUANTISER_MAX_INPUTS + 7)
+
+typedef struct {
+ float* min;
+ float* max;
+ float* match_range;
+ float* mode;
+ float* count;
+ float* values[QUANTISER_MAX_INPUTS];
+ float* input;
+ float* output_changed;
+ float* output;
+ float svalues[QUANTISER_MAX_INPUTS + 2];
+ float temp[QUANTISER_MAX_INPUTS + 2];
+ float last_found;
+} Quantiser;
+
+/*
+ * f <= m <= l
+*/
+static inline void
+merge(float* v,
+ int f,
+ int m,
+ int l,
+ float* temp)
+{
+ int f1 = f;
+ int l1 = m;
+ int f2 = m + 1;
+ int l2 = l;
+ int i = f1;
+
+ while ((f1 <= l1) && (f2 <= l2)) {
+ if (v[f1] < v[f2]) {
+ temp[i] = v[f1];
+ f1++;
+ } else {
+ temp[i] = v[f2];
+ f2++;
+ }
+ i++;
+ }
+ while (f1 <= l1) {
+ temp[i] = v[f1];
+ f1++;
+ i++;
+ }
+ while (f2 <= l2) {
+ temp[i] = v[f2];
+ f2++;
+ i++;
+ }
+ for (i = f; i <= l; i++) {
+ v[i] = temp[i];
+ }
+}
+
+/*
+ * Recursive Merge Sort
+ * Sort elements in unsorted vector v
+*/
+static inline void
+msort(float* v,
+ int f,
+ int l,
+ float* temp)
+{
+ int m;
+
+ if (f < l) {
+ m = (f + l) / 2;
+ msort(v, f, m, temp);
+ msort(v, m + 1, l, temp);
+ merge(v, f, m, l, temp);
+ }
+}
+
+/*
+ * Binary search for nearest match to sought value in
+ * ordered vector v of given size
+*/
+static inline int
+fuzzy_bsearch(float* v,
+ int size,
+ float sought)
+{
+ int f = 0;
+ int l = size - 1;
+ int m = ((l - f) / 2);
+
+ while ((l - f) > 1) {
+ if (v[m] < sought) {
+ f = (l - f) / 2 + f;
+ } else {
+ l = (l - f) / 2 + f;
+ }
+
+ m = ((l - f) / 2 + f);
+ }
+
+ if (sought < v[m]) {
+ if (m > 0) {
+ if (FABSF(v[m] - sought) > FABSF(v[m - 1] - sought)) {
+ m--;
+ }
+ }
+ } else if (m < size - 1) {
+ if (FABSF(v[m] - sought) > FABSF(v[m + 1] - sought)) {
+ m++;
+ }
+ }
+
+ return m;
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Quantiser* plugin = (Quantiser*)instance;
+
+ switch (port) {
+ case QUANTISER_RANGE_MIN:
+ plugin->min = data;
+ break;
+ case QUANTISER_RANGE_MAX:
+ plugin->max = data;
+ break;
+ case QUANTISER_MATCH_RANGE:
+ plugin->match_range = data;
+ break;
+ case QUANTISER_MODE:
+ plugin->mode = data;
+ break;
+ case QUANTISER_COUNT:
+ plugin->count = data;
+ break;
+ case QUANTISER_INPUT:
+ plugin->input = data;
+ break;
+ case QUANTISER_OUTPUT:
+ plugin->output = data;
+ break;
+ case QUANTISER_OUTPUT_CHANGED:
+ plugin->output_changed = data;
+ break;
+ default:
+ if (port >= QUANTISER_VALUE_START && port < QUANTISER_OUTPUT) {
+ plugin->values[port - QUANTISER_VALUE_START] = data;
+ }
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Quantiser* plugin = (Quantiser*)malloc(sizeof(Quantiser));
+
+ return (LV2_Handle)plugin;
+}
+
+#if 0
+static void
+runQuantiser_audio(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Quantiser* plugin = (Quantiser*)instance;
+
+ /* Range Min (float value) */
+ float min = *(plugin->min);
+
+ /* Range Max (float value) */
+ float max = *(plugin->max);
+
+ /* Match Range (float value) */
+ float match_range = *(plugin->match_range);
+
+ /* Mode (float value) */
+ float mode = *(plugin->mode);
+
+ /* Count (float value) */
+ float count = *(plugin->count);
+
+ /* Input (array of float of length sample_count) */
+ float* input = plugin->input;
+
+ /* Values */
+ float* values[QUANTISER_MAX_INPUTS];
+
+ /* Output (array of float of length sample_count) */
+ float* output = plugin->output;
+
+ /* Output Changed (array of float of length sample_count) */
+ float* output_changed = plugin->output_changed;
+
+ for (uint32_t s = 0; s < sample_count; s++) {
+ output[s] = input[s];
+ }
+}
+
+#endif
+
+static void
+runQuantiser_control(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Quantiser* plugin = (Quantiser*)instance;
+
+ /* Range Min (float value) */
+ float min = *(plugin->min);
+
+ /* Range Max (float value) */
+ float max = *(plugin->max);
+
+ /* Match Range (float value) */
+ float match_range = FABSF(*(plugin->match_range));
+
+ /* Mode (float value) */
+ float mode = *(plugin->mode);
+
+ /* Count (float value) */
+ float count = *(plugin->count);
+
+ /* Input (array of float of length sample_count) */
+ float* input = plugin->input;
+
+ /* Output (array of float of length sample_count) */
+ float* output = plugin->output;
+
+ /* Output Changed (array of float of length sample_count) */
+ float* output_changed = plugin->output_changed;
+
+ /* Instance Data */
+ float* temp = plugin->temp;
+ float* values = plugin->svalues;
+ float last_found = plugin->last_found;
+
+ int md = LRINTF(mode);
+ int n = LRINTF(count);
+ int i;
+ float in;
+ float out_changed;
+ float range;
+ float offset;
+ float found;
+ int found_index = 0;
+
+ /* Clip count if out of range */
+ n = n < 1 ? 1 : (n > QUANTISER_MAX_INPUTS ? QUANTISER_MAX_INPUTS : n);
+
+ /* Swap min and max if wrong way around */
+ if (min > max) {
+ range = min;
+ min = max;
+ max = range;
+ }
+ range = max - min;
+
+ /* Copy and sort required values */
+ for (i = 0; i < n; i++) {
+ values[i + 1] = *(plugin->values[i]);
+ }
+
+ msort(values, 1, n, temp);
+
+ /* Add wrapped extremes */
+ values[0] = values[n] - range;
+ values[n + 1] = values[1] + range;
+
+ if (md < 1) {
+ /* Extend mode */
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in = input[s];
+
+ if (range > 0.0f) {
+ if ((in < min) || (in > max)) {
+ offset = FLOORF((in - max) / range) + 1.0f;
+ offset *= range;
+ in -= offset;
+
+ /* Quantise */
+ found_index = fuzzy_bsearch(values, n + 2, in);
+
+ /* Wrapped */
+ if (found_index == 0) {
+ found_index = n;
+ offset -= range;
+ } else if (found_index == n + 1) {
+ found_index = 1;
+ offset += range;
+ }
+
+ found = values[found_index];
+
+ /* Allow near misses */
+ if (match_range > 0.0f) {
+ if (in < (found - match_range)) {
+ found -= match_range;
+ } else if (in > (found + match_range)) {
+ found += match_range;
+ }
+ }
+ found += offset;
+ } else {
+ /* Quantise */
+ found_index = fuzzy_bsearch(values, n + 2, in);
+ if (found_index == 0) {
+ found_index = n;
+ found = values[n] - range;
+ } else if (found_index == n + 1) {
+ found_index = 1;
+ found = values[1] + range;
+ } else {
+ found = values[found_index];
+ }
+
+ if (match_range > 0.0f) {
+ if (in < (found - match_range)) {
+ found -= match_range;
+ } else if (in > (found + match_range)) {
+ found += match_range;
+ }
+ }
+ }
+ } else {
+ /* Min and max the same, so only one value to quantise to */
+ found = min;
+ }
+
+ /* Has quantised output changed? */
+ if (FABSF(found - last_found) > 2.0001f * match_range) {
+ out_changed = 1.0f;
+ last_found = found;
+ } else {
+ out_changed = 0.0f;
+ }
+
+ output[s] = found;
+ output_changed[s] = out_changed;
+ }
+ } else if (md == 1) {
+ /* Wrap mode */
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in = input[s];
+
+ if (range > 0.0f) {
+ if ((in < min) || (in > max)) {
+ in -= (FLOORF((in - max) / range) + 1.0f) * range;
+ }
+
+ /* Quantise */
+ found_index = fuzzy_bsearch(values, n + 2, in);
+ if (found_index == 0) {
+ found_index = n;
+ } else if (found_index == n + 1) {
+ found_index = 1;
+ }
+
+ found = values[found_index];
+
+ /* Allow near misses */
+ if (match_range > 0.0f) {
+ if (in < (found - match_range)) {
+ found -= match_range;
+ } else if (in > (found + match_range)) {
+ found += match_range;
+ }
+ }
+ } else {
+ /* Min and max the same, so only one value to quantise to */
+ found = min;
+ }
+
+ /* Has quantised output changed? */
+ if (FABSF(found - last_found) > match_range) {
+ out_changed = 1.0f;
+ last_found = found;
+ } else {
+ out_changed = 0.0f;
+ }
+
+ output[s] = found;
+ output_changed[s] = out_changed;
+ }
+ } else {
+ /* Clip mode */
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in = input[s];
+
+ if (range > 0.0f) {
+ /* Clip to range */
+ if (in < min) {
+ found_index = 1;
+ } else if (in > max) {
+ found_index = n;
+ } else {
+ /* Quantise */
+ found_index = fuzzy_bsearch(values + 1, n, in) + 1;
+ }
+
+ found = values[found_index];
+
+ /* Allow near misses */
+ if (match_range > 0.0f) {
+ if (in < (found - match_range)) {
+ found -= match_range;
+ } else if (in > (found + match_range)) {
+ found += match_range;
+ }
+ }
+ } else {
+ /* Min and max the same, so only one value to quantise to */
+ found = min;
+ }
+
+ /* Has quantised output changed? */
+ if (FABSF(found - last_found) > match_range) {
+ out_changed = 1.0f;
+ last_found = found;
+ } else {
+ out_changed = 0.0f;
+ }
+
+ output[s] = found;
+ output_changed[s] = out_changed;
+ }
+ }
+ plugin->last_found = last_found;
+}
diff --git a/src/random.c b/src/random.c
new file mode 100644
index 0000000..9aab30a
--- /dev/null
+++ b/src/random.c
@@ -0,0 +1,348 @@
+/*
+ An LV2 plugin to generate a random wave of varying frequency and smoothness.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include <time.h>
+#include "math_func.h"
+#include "common.h"
+
+#define RANDOM_FREQUENCY 0
+#define RANDOM_SMOOTH 1
+#define RANDOM_OUTPUT 2
+
+typedef struct {
+ float* frequency;
+ float* smooth;
+ float* output;
+ float nyquist;
+ float inv_nyquist;
+ float phase;
+ float value1;
+ float value2;
+} Random;
+
+float inv_rand_max;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Random* plugin = (Random*)instance;
+
+ switch (port) {
+ case RANDOM_FREQUENCY:
+ plugin->frequency = data;
+ break;
+ case RANDOM_SMOOTH:
+ plugin->smooth = data;
+ break;
+ case RANDOM_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Random* plugin = (Random*)malloc(sizeof(Random));
+
+ srand((int)time((time_t*)0));
+
+ inv_rand_max = 2.0f / (float)RAND_MAX;
+
+ plugin->nyquist = (float)sample_rate / 2.0f;
+ plugin->inv_nyquist = 1.0f / plugin->nyquist;
+
+ plugin->value1 = rand() * inv_rand_max - 1.0f;
+ plugin->value2 = rand() * inv_rand_max - 1.0f;
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Random* plugin = (Random*)instance;
+
+ plugin->phase = 0.0f;
+}
+
+static void
+runRandom_fasa_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Random* plugin = (Random*)instance;
+
+ /* Frequency (Hz) (array of floats of length sample_count) */
+ float* frequency = plugin->frequency;
+
+ /* Wave smoothness (array of floats of length sample_count) */
+ float* smooth = plugin->smooth;
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ float nyquist = plugin->nyquist;
+ float inv_nyquist = plugin->inv_nyquist;
+ float phase = plugin->phase;
+ float value1 = plugin->value1;
+ float value2 = plugin->value2;
+
+ float freq;
+ float smth;
+ float interval;
+ float result;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ freq = f_clip(frequency[s], 0.0f, nyquist);
+
+ smth = f_clip(smooth[s], 0.0f, 1.0f);
+ interval = (1.0f - smth) * 0.5f;
+
+ if (phase < interval) {
+ result = 1.0f;
+ } else if (phase > (1.0f - interval)) {
+ result = -1.0f;
+ } else if (interval > 0.0f) {
+ result = COSF((phase - interval) / smth * M_PI);
+ } else {
+ result = COSF(phase * M_PI);
+ }
+
+ result *= (value2 - value1) * 0.5f;
+ result -= (value2 + value1) * 0.5f;
+
+ output[s] = result;
+
+ phase += freq * inv_nyquist;
+ if (phase > 1.0f) {
+ phase -= 1.0f;
+ value1 = value2;
+ value2 = (float)rand() * inv_rand_max - 1.0f;
+ }
+ }
+
+ plugin->phase = phase;
+ plugin->value1 = value1;
+ plugin->value2 = value2;
+}
+
+static void
+runRandom_fasc_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Random* plugin = (Random*)instance;
+
+ /* Frequency (Hz) (array of floats of length sample_count) */
+ float* frequency = plugin->frequency;
+
+ /* Wave smoothness (float value) */
+ float smooth = f_clip(*(plugin->smooth), 0.0f, 1.0f);
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ float nyquist = plugin->nyquist;
+ float inv_nyquist = plugin->inv_nyquist;
+ float phase = plugin->phase;
+ float value1 = plugin->value1;
+ float value2 = plugin->value2;
+
+ float freq;
+ float interval = (1.0f - smooth) * 0.5f;
+ float result;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ freq = f_clip(frequency[s], 0.0f, nyquist);
+
+ if (phase < interval) {
+ result = 1.0f;
+ } else if (phase > (1.0f - interval)) {
+ result = -1.0f;
+ } else if (interval > 0.0f) {
+ result = COSF((phase - interval) / smooth * M_PI);
+ } else {
+ result = COSF(phase * M_PI);
+ }
+
+ result *= (value2 - value1) * 0.5f;
+ result -= (value2 + value1) * 0.5f;
+
+ output[s] = result;
+
+ phase += freq * inv_nyquist;
+ if (phase > 1.0f) {
+ phase -= 1.0f;
+ value1 = value2;
+ value2 = (float)rand() * inv_rand_max - 1.0f;
+ }
+ }
+
+ plugin->phase = phase;
+ plugin->value1 = value1;
+ plugin->value2 = value2;
+}
+
+static void
+runRandom_fcsa_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Random* plugin = (Random*)instance;
+
+ /* Frequency (Hz) (float value) */
+ float frequency = *(plugin->frequency);
+
+ /* Wave smoothness (array of floats of length sample_count) */
+ float* smooth = plugin->smooth;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ float nyquist = plugin->nyquist;
+ float inv_nyquist = plugin->inv_nyquist;
+ float phase = plugin->phase;
+ float value1 = plugin->value1;
+ float value2 = plugin->value2;
+
+ float phase_scale = f_clip(frequency, 0.0f, nyquist) * inv_nyquist;
+ float smth;
+ float interval;
+ float result;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ smth = f_clip(smooth[s], 0.0f, 1.0f);
+ interval = (1.0f - smth) * 0.5f;
+
+ if (phase < interval) {
+ result = 1.0f;
+ } else if (phase > (1.0f - interval)) {
+ result = -1.0f;
+ } else if (interval > 0.0f) {
+ result = COSF((phase - interval) / smth * M_PI);
+ } else {
+ result = COSF(phase * M_PI);
+ }
+
+ result *= (value2 - value1) * 0.5f;
+ result -= (value2 + value1) * 0.5f;
+
+ output[s] = result;
+
+ phase += phase_scale;
+ if (phase > 1.0f) {
+ phase -= 1.0f;
+ value1 = value2;
+ value2 = (float)rand() * inv_rand_max - 1.0f;
+ }
+ }
+
+ plugin->phase = phase;
+ plugin->value1 = value1;
+ plugin->value2 = value2;
+}
+
+static void
+runRandom_fcsc_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Random* plugin = (Random*)instance;
+
+ /* Frequency (Hz) (float value) */
+ float frequency = *(plugin->frequency);
+
+ /* Wave smoothness (float value) */
+ float smooth = f_clip(*(plugin->smooth), 0.0f, 1.0f);
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ float nyquist = plugin->nyquist;
+ float inv_nyquist = plugin->inv_nyquist;
+ float phase = plugin->phase;
+ float value1 = plugin->value1;
+ float value2 = plugin->value2;
+
+ float phase_scale = f_clip(frequency, 0.0f, nyquist) * inv_nyquist;
+ float interval = (1.0f - smooth) * 0.5f;
+ float result;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ if (phase < interval) {
+ result = 1.0f;
+ } else if (phase > (1.0f - interval)) {
+ result = -1.0f;
+ } else if (interval > 0.0f) {
+ result = COSF((phase - interval) / smooth * M_PI);
+ } else {
+ result = COSF(phase * M_PI);
+ }
+
+ result *= (value2 - value1) * 0.5f;
+ result -= (value2 + value1) * 0.5f;
+
+ output[s] = result;
+
+ phase += phase_scale;
+ if (phase > 1.0f) {
+ phase -= 1.0f;
+ value1 = value2;
+ value2 = (float)rand() * inv_rand_max - 1.0f;
+ }
+ }
+
+ plugin->phase = phase;
+ plugin->value1 = value1;
+ plugin->value2 = value2;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/random",
+ instantiate,
+ connect_port,
+ activate,
+ runRandom_fcsc_oa,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/ratio.c b/src/ratio.c
new file mode 100644
index 0000000..33fc4e9
--- /dev/null
+++ b/src/ratio.c
@@ -0,0 +1,189 @@
+/*
+ An LV2 plugin to calculate the ratio of two signals.
+ Copyright 2011 David Robillard
+ Copyright 2004 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "math_func.h"
+#include "common.h"
+
+#define RATIO_NUMERATOR 0
+#define RATIO_DENOMINATOR 1
+#define RATIO_OUTPUT 2
+
+typedef struct {
+ float* numerator;
+ float* denominator;
+ float* output;
+} Ratio;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Ratio* plugin = (Ratio*)instance;
+
+ switch (port) {
+ case RATIO_NUMERATOR:
+ plugin->numerator = data;
+ break;
+ case RATIO_DENOMINATOR:
+ plugin->denominator = data;
+ break;
+ case RATIO_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Ratio* plugin = (Ratio*)malloc(sizeof(Ratio));
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+runRatio_nada_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Ratio* plugin = (Ratio*)instance;
+
+ /* Numerator (array of floats of length sample_count) */
+ float* numerator = plugin->numerator;
+
+ /* Denominator (array of floats of length sample_count) */
+ float* denominator = plugin->denominator;
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float n;
+ float d;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ n = numerator[s];
+ d = denominator[s];
+
+ d = COPYSIGNF(f_max(FABSF(d), 1e-16f), d);
+
+ output[s] = n / d;
+ }
+}
+
+static void
+runRatio_nadc_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Ratio* plugin = (Ratio*)instance;
+
+ /* Numerator (array of floats of length sample_count) */
+ float* numerator = plugin->numerator;
+
+ /* Denominator (float value) */
+ float denominator = *(plugin->denominator);
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float n;
+
+ denominator = COPYSIGNF(f_max(FABSF(denominator), 1e-16f), denominator);
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ n = numerator[s];
+
+ output[s] = n / denominator;
+ }
+}
+
+static void
+runRatio_ncda_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Ratio* plugin = (Ratio*)instance;
+
+ /* Numerator (float value) */
+ float numerator = *(plugin->numerator);
+
+ /* Denominator (array of floats of length sample_count) */
+ float* denominator = plugin->denominator;
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float d;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ d = denominator[s];
+ d = COPYSIGNF(f_max(FABSF(d), 1e-16f), d);
+
+ output[s] = numerator / d;
+ }
+}
+
+static void
+runRatio_ncdc_oc(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Ratio* plugin = (Ratio*)instance;
+
+ /* Numerator (float value) */
+ float numerator = *(plugin->numerator);
+
+ /* Denominator (float value) */
+ float denominator = *(plugin->denominator);
+
+ /* Output Frequency (pointer to float value) */
+ float* output = plugin->output;
+
+ denominator = COPYSIGNF(f_max(FABSF(denominator), 1e-16f), denominator);
+
+ output[0] = numerator / denominator;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/ratio",
+ instantiate,
+ connect_port,
+ NULL,
+ runRatio_ncdc_oc,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/sawtooth.c b/src/sawtooth.c
new file mode 100644
index 0000000..2e1a3ec
--- /dev/null
+++ b/src/sawtooth.c
@@ -0,0 +1,171 @@
+/*
+ An LV2 plugin to generate a bandlimited sawtooth waveform.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "wavedata.h"
+
+#define SAWTOOTH_FREQUENCY 0
+#define SAWTOOTH_OUTPUT 1
+
+typedef struct {
+ float* frequency;
+ float* output;
+ float phase;
+ Wavedata wdat;
+} Sawtooth;
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Sawtooth* plugin = (Sawtooth*)instance;
+
+ switch (port) {
+ case SAWTOOTH_FREQUENCY:
+ plugin->frequency = data;
+ break;
+ case SAWTOOTH_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Sawtooth* plugin = (Sawtooth*)malloc(sizeof(Sawtooth));
+
+ if (wavedata_load(&plugin->wdat, BLOP_DLSYM_SAWTOOTH, sample_rate)) {
+ free(plugin);
+ return 0;
+ }
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ Sawtooth* plugin = (Sawtooth*)instance;
+
+ wavedata_unload(&plugin->wdat);
+ free(instance);
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Sawtooth* plugin = (Sawtooth*)instance;
+
+ plugin->phase = 0.0f;
+}
+
+static void
+runSawtooth_fa_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Sawtooth* plugin = (Sawtooth*)instance;
+
+ /* Frequency (array of float of length sample_count) */
+ float* frequency = plugin->frequency;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ Wavedata* wdat = &plugin->wdat;
+ float phase = plugin->phase;
+
+ float freq;
+
+ for (uint32_t s = 0; s < sample_count; s++) {
+ freq = frequency[s];
+
+ /* Lookup table to play */
+ wavedata_get_table(wdat, freq);
+
+ output[s] = wavedata_get_sample(wdat, phase);
+
+ /* Update phase, wrapping if necessary */
+ phase += wdat->frequency;
+ if (phase < 0.0f) {
+ phase += wdat->sample_rate;
+ } else if (phase > wdat->sample_rate) {
+ phase -= wdat->sample_rate;
+ }
+ }
+ plugin->phase = phase;
+}
+
+static void
+runSawtooth_fc_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Sawtooth* plugin = (Sawtooth*)instance;
+
+ /* Frequency (float value) */
+ float frequency = *(plugin->frequency);
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ Wavedata* wdat = &plugin->wdat;
+ float phase = plugin->phase;
+
+ wavedata_get_table(wdat, frequency);
+
+ for (uint32_t s = 0; s < sample_count; s++) {
+ output[s] = wavedata_get_sample(wdat, phase);
+
+ /* Update phase, wrapping if necessary */
+ phase += wdat->frequency;
+ if (phase < 0.0f) {
+ phase += wdat->sample_rate;
+ } else if (phase > wdat->sample_rate) {
+ phase -= wdat->sample_rate;
+ }
+ }
+ plugin->phase = phase;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/sawtooth",
+ instantiate,
+ connect_port,
+ activate,
+ runSawtooth_fc_oa,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/sequencer.c b/src/sequencer.c
new file mode 100644
index 0000000..7b39a50
--- /dev/null
+++ b/src/sequencer.c
@@ -0,0 +1,193 @@
+/*
+ An LV2 plugin to simulate an analogue style step sequencer.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "math_func.h"
+#include "common.h"
+
+#define SEQUENCER_GATE 0
+#define SEQUENCER_TRIGGER 1
+#define SEQUENCER_LOOP_POINT 2
+#define SEQUENCER_RESET 3
+#define SEQUENCER_VALUE_GATE_CLOSED 4
+#define SEQUENCER_VALUE_START 5
+#define SEQUENCER_OUTPUT (SEQUENCER_MAX_INPUTS + 5)
+
+typedef struct {
+ float* gate;
+ float* trigger;
+ float* loop_steps;
+ float* reset;
+ float* value_gate_closed;
+ float* values[SEQUENCER_MAX_INPUTS];
+ float* output;
+ float srate;
+ float inv_srate;
+ float last_gate;
+ float last_trigger;
+ float last_value;
+ unsigned int step_index;
+} Sequencer;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Sequencer* plugin = (Sequencer*)instance;
+
+ switch (port) {
+ case SEQUENCER_GATE:
+ plugin->gate = data;
+ break;
+ case SEQUENCER_TRIGGER:
+ plugin->trigger = data;
+ break;
+ case SEQUENCER_LOOP_POINT:
+ plugin->loop_steps = data;
+ break;
+ case SEQUENCER_OUTPUT:
+ plugin->output = data;
+ break;
+ case SEQUENCER_RESET:
+ plugin->reset = data;
+ break;
+ case SEQUENCER_VALUE_GATE_CLOSED:
+ plugin->value_gate_closed = data;
+ break;
+ default:
+ if (port >= SEQUENCER_VALUE_START && port < SEQUENCER_OUTPUT) {
+ plugin->values[port - SEQUENCER_VALUE_START] = data;
+ }
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Sequencer* plugin = (Sequencer*)malloc(sizeof(Sequencer));
+
+ plugin->srate = (float)sample_rate;
+ plugin->inv_srate = 1.0f / plugin->srate;
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Sequencer* plugin = (Sequencer*)instance;
+
+ plugin->last_gate = 0.0f;
+ plugin->last_trigger = 0.0f;
+ plugin->last_value = 0.0f;
+ plugin->step_index = 0;
+}
+
+static void
+runSequencer(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Sequencer* plugin = (Sequencer*)instance;
+
+ /* Gate */
+ float* gate = plugin->gate;
+
+ /* Step Trigger */
+ float* trigger = plugin->trigger;
+
+ /* Loop Steps */
+ float loop_steps = *(plugin->loop_steps);
+
+ /* Reset to Value on Gate Close */
+ float reset = *(plugin->reset);
+
+ /* Value used when gate closed */
+ float value_gate_closed = *(plugin->value_gate_closed);
+
+ /* Step Values */
+ float values[SEQUENCER_MAX_INPUTS];
+
+ /* Output */
+ float* output = plugin->output;
+
+ float last_gate = plugin->last_gate;
+ float last_trigger = plugin->last_trigger;
+ float last_value = plugin->last_value;
+
+ unsigned int step_index = plugin->step_index;
+ unsigned int loop_index = LRINTF(loop_steps);
+ int rst = LRINTF(reset);
+ int i;
+
+ loop_index = loop_index == 0 ? 1 : loop_index;
+ loop_index = (loop_index > SEQUENCER_MAX_INPUTS)
+ ? SEQUENCER_MAX_INPUTS
+ : loop_index;
+
+ for (i = 0; i < SEQUENCER_MAX_INPUTS; i++) {
+ values[i] = *(plugin->values[i]);
+ }
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ if (gate[s] > 0.0f) {
+ if (trigger[s] > 0.0f && !(last_trigger > 0.0f)) {
+ if (last_gate > 0.0f) {
+ step_index++;
+ if (step_index >= loop_index) {
+ step_index = 0;
+ }
+ } else {
+ step_index = 0;
+ }
+ }
+
+ output[s] = values[step_index];
+
+ last_value = values[step_index];
+ } else {
+ if (rst) {
+ output[s] = value_gate_closed;
+ } else {
+ output[s] = last_value;
+ }
+
+ step_index = 0;
+ }
+ last_gate = gate[s];
+ last_trigger = trigger[s];
+ }
+
+ plugin->last_gate = last_gate;
+ plugin->last_trigger = last_trigger;
+ plugin->last_value = last_value;
+ plugin->step_index = step_index;
+}
diff --git a/src/square.c b/src/square.c
new file mode 100644
index 0000000..001a47e
--- /dev/null
+++ b/src/square.c
@@ -0,0 +1,172 @@
+/*
+ An LV2 plugin to generate a bandlimited square waveform.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "wavedata.h"
+
+#define SQUARE_FREQUENCY 0
+#define SQUARE_OUTPUT 1
+
+typedef struct {
+ float* frequency;
+ float* output;
+ float phase;
+ Wavedata wdat;
+} Square;
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Square* plugin = (Square*)instance;
+
+ switch (port) {
+ case SQUARE_FREQUENCY:
+ plugin->frequency = data;
+ break;
+ case SQUARE_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Square* plugin = (Square*)malloc(sizeof(Square));
+
+ if (wavedata_load(&plugin->wdat, BLOP_DLSYM_SQUARE, sample_rate)) {
+ free(plugin);
+ return NULL;
+ }
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ Square* plugin = (Square*)instance;
+
+ wavedata_unload(&plugin->wdat);
+ free(instance);
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Square* plugin = (Square*)instance;
+
+ plugin->phase = 0.0f;
+}
+
+static void
+runSquare_fa_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Square* plugin = (Square*)instance;
+
+ /* Frequency (array of float of length sample_count) */
+ float* frequency = plugin->frequency;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ Wavedata* wdat = &plugin->wdat;
+ float phase = plugin->phase;
+
+ float freq;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ freq = frequency[s];
+
+ /* Get table to play */
+ wavedata_get_table(wdat, freq);
+
+ /* Get interpolated sample */
+ output[s] = wavedata_get_sample(wdat, phase);
+
+ /* Update phase, wrapping if necessary */
+ phase += wdat->frequency;
+ if (phase < 0.0f) {
+ phase += wdat->sample_rate;
+ } else if (phase > wdat->sample_rate) {
+ phase -= wdat->sample_rate;
+ }
+ }
+ plugin->phase = phase;
+}
+
+static void
+runSquare_fc_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Square* plugin = (Square*)instance;
+
+ /* Frequency (float value) */
+ float frequency = *(plugin->frequency);
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ Wavedata* wdat = &plugin->wdat;
+ float phase = plugin->phase;
+
+ wavedata_get_table(wdat, frequency);
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ output[s] = wavedata_get_sample(wdat, phase);
+
+ /* Update phase, wrapping if necessary */
+ phase += wdat->frequency;
+ if (phase < 0.0f) {
+ phase += wdat->sample_rate;
+ } else if (phase > wdat->sample_rate) {
+ phase -= wdat->sample_rate;
+ }
+ }
+ plugin->phase = phase;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/square",
+ instantiate,
+ connect_port,
+ activate,
+ runSquare_fc_oa,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/sum.c b/src/sum.c
new file mode 100644
index 0000000..5f94796
--- /dev/null
+++ b/src/sum.c
@@ -0,0 +1,156 @@
+/*
+ An LV2 plugin to calculate the sum of two signals.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+
+#define SUM_INPUT1 0
+#define SUM_INPUT2 1
+#define SUM_OUTPUT 2
+
+typedef struct {
+ float* input1;
+ float* input2;
+ float* output;
+} Sum;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Sum* plugin = (Sum*)instance;
+
+ switch (port) {
+ case SUM_INPUT1:
+ plugin->input1 = data;
+ break;
+ case SUM_INPUT2:
+ plugin->input2 = data;
+ break;
+ case SUM_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Sum* plugin = (Sum*)malloc(sizeof(Sum));
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+runSum_iaia_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Sum* plugin = (Sum*)instance;
+
+ /* First Input (array of floats of length sample_count) */
+ float* input1 = plugin->input1;
+
+ /* Second Input (array of floats of length sample_count) */
+ float* input2 = plugin->input2;
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float in1;
+ float in2;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in1 = input1[s];
+ in2 = input2[s];
+
+ output[s] = in1 + in2;
+ }
+}
+
+static void
+runSum_iaic_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Sum* plugin = (Sum*)instance;
+
+ /* First Input (array of floats of length sample_count) */
+ float* input1 = plugin->input1;
+
+ /* Second Input (float value) */
+ float input2 = *(plugin->input2);
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ float in1;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in1 = input1[s];
+
+ output[s] = in1 + input2;
+ }
+}
+
+static void
+runSum_icic_oc(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Sum* plugin = (Sum*)instance;
+
+ /* First Input (float value) */
+ float input1 = *(plugin->input1);
+
+ /* Second Input (float value) */
+ float input2 = *(plugin->input2);
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ output[0] = input1 + input2;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/sum",
+ instantiate,
+ connect_port,
+ NULL,
+ runSum_icic_oc,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/sync_pulse.c b/src/sync_pulse.c
new file mode 100644
index 0000000..4dc9dad
--- /dev/null
+++ b/src/sync_pulse.c
@@ -0,0 +1,205 @@
+/*
+ An LV2 plugin to generate a non-bandlimited variable-pulse waveform with gate
+ for trigger and sync.
+ Copyright 2011 David Robillard
+ Copyright 2003 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "common.h"
+
+#define SYNCPULSE_FREQUENCY 0
+#define SYNCPULSE_PULSEWIDTH 1
+#define SYNCPULSE_GATE 2
+#define SYNCPULSE_OUTPUT 3
+
+typedef struct {
+ float* frequency;
+ float* pulsewidth;
+ float* gate;
+ float* output;
+ float srate;
+ float phase;
+} SyncPulse;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ SyncPulse* plugin = (SyncPulse*)instance;
+
+ switch (port) {
+ case SYNCPULSE_FREQUENCY:
+ plugin->frequency = data;
+ break;
+ case SYNCPULSE_PULSEWIDTH:
+ plugin->pulsewidth = data;
+ break;
+ case SYNCPULSE_GATE:
+ plugin->gate = data;
+ break;
+ case SYNCPULSE_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ SyncPulse* plugin = (SyncPulse*)malloc(sizeof(SyncPulse));
+
+ plugin->srate = (float)sample_rate;
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ SyncPulse* plugin = (SyncPulse*)instance;
+
+ plugin->phase = 0.0f;
+}
+
+static void
+runSyncPulse_fapaga_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ SyncPulse* plugin = (SyncPulse*)instance;
+
+ /* Frequency (array of float of length sample_count) */
+ float* frequency = plugin->frequency;
+
+ /* Pulse Width (array of float of length sample_count) */
+ float* pulsewidth = plugin->pulsewidth;
+
+ /* Gate (array of float of length sample_count) */
+ float* gate = plugin->gate;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ float phase = plugin->phase;
+ float srate = plugin->srate;
+
+ float freq;
+ float pwidth;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ if (gate[s] > 0.0f) {
+ freq = frequency[s];
+ pwidth = f_clip(pulsewidth[s], 0.0f, 1.0f) * srate;
+
+ if (phase < pwidth) {
+ output[s] = 1.0f;
+ } else {
+ output[s] = -1.0f;
+ }
+
+ phase += freq;
+ if (phase < 0.0f) {
+ phase += srate;
+ } else if (phase > srate) {
+ phase -= srate;
+ }
+ } else {
+ output[s] = 0.0f;
+ phase = 0.0f;
+ }
+ }
+
+ plugin->phase = phase;
+}
+
+static void
+runSyncPulse_fcpcga_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ SyncPulse* plugin = (SyncPulse*)instance;
+
+ /* Frequency (float value) */
+ float frequency = *(plugin->frequency);
+
+ /* Pulse Width (float value) */
+ float pulsewidth = f_clip(*(plugin->pulsewidth), 0.0f, 1.0f);
+
+ /* Gate (array of float of length sample_count) */
+ float* gate = plugin->gate;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance Data */
+ float phase = plugin->phase;
+ float srate = plugin->srate;
+
+ pulsewidth *= srate;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ if (gate[s] > 0.0f) {
+ if (phase < pulsewidth) {
+ output[s] = 1.0f;
+ } else {
+ output[s] = -1.0f;
+ }
+
+ phase += frequency;
+ if (phase < 0.0f) {
+ phase += srate;
+ } else if (phase > srate) {
+ phase -= srate;
+ }
+ } else {
+ output[s] = 0.0f;
+ phase = 0.0f;
+ }
+ }
+
+ plugin->phase = phase;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/sync_pulse",
+ instantiate,
+ connect_port,
+ activate,
+ runSyncPulse_fcpcga_oa,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/sync_square.c b/src/sync_square.c
new file mode 100644
index 0000000..df33a09
--- /dev/null
+++ b/src/sync_square.c
@@ -0,0 +1,193 @@
+/*
+ An LV2 plugin to generate a non-bandlimited square waveform with gate for
+ trigger and sync.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+
+#define SYNCSQUARE_FREQUENCY 0
+#define SYNCSQUARE_GATE 1
+#define SYNCSQUARE_OUTPUT 2
+
+typedef struct {
+ float* frequency;
+ float* gate;
+ float* output;
+ float srate;
+ float nyquist;
+ float phase;
+} SyncSquare;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ SyncSquare* plugin = (SyncSquare*)instance;
+
+ switch (port) {
+ case SYNCSQUARE_FREQUENCY:
+ plugin->frequency = data;
+ break;
+ case SYNCSQUARE_GATE:
+ plugin->gate = data;
+ break;
+ case SYNCSQUARE_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ SyncSquare* plugin = (SyncSquare*)malloc(sizeof(SyncSquare));
+
+ plugin->srate = (float)sample_rate;
+ plugin->nyquist = (float)(sample_rate / 2);
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ SyncSquare* plugin = (SyncSquare*)instance;
+
+ plugin->phase = 0.0f;
+}
+
+static void
+runSyncSquare_faga_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ SyncSquare* plugin = (SyncSquare*)instance;
+
+ /* Frequency (array of float of length sample_count) */
+ float* frequency = plugin->frequency;
+
+ /* Gate (array of float of length sample_count) */
+ float* gate = plugin->gate;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ float phase = plugin->phase;
+ float srate = plugin->srate;
+ float nyquist = plugin->nyquist;
+
+ float freq;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ if (gate[s] > 0.0f) {
+ freq = frequency[s];
+
+ if (phase < nyquist) {
+ output[s] = 1.0f;
+ } else {
+ output[s] = -1.0f;
+ }
+
+ phase += freq;
+ if (phase < 0.0f) {
+ phase += srate;
+ } else if (phase > srate) {
+ phase -= srate;
+ }
+ } else {
+ output[s] = 0.0f;
+ phase = 0.0f;
+ }
+ }
+
+ plugin->phase = phase;
+}
+
+static void
+runSyncSquare_fcga_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ SyncSquare* plugin = (SyncSquare*)instance;
+
+ /* Frequency (float value) */
+ float frequency = *(plugin->frequency);
+
+ /* Gate (array of float of length sample_count) */
+ float* gate = plugin->gate;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance Data */
+ float phase = plugin->phase;
+ float srate = plugin->srate;
+ float nyquist = plugin->nyquist;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ if (gate[s] > 0.0f) {
+ if (phase < nyquist) {
+ output[s] = 1.0f;
+ } else {
+ output[s] = -1.0f;
+ }
+
+ phase += frequency;
+ if (phase < 0.0f) {
+ phase += srate;
+ } else if (phase > srate) {
+ phase -= srate;
+ }
+ } else {
+ output[s] = 0.0f;
+ phase = 0.0f;
+ }
+ }
+
+ plugin->phase = phase;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/sync_square",
+ instantiate,
+ connect_port,
+ activate,
+ runSyncSquare_fcga_oa,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/tracker.c b/src/tracker.c
new file mode 100644
index 0000000..4460a34
--- /dev/null
+++ b/src/tracker.c
@@ -0,0 +1,229 @@
+/*
+ An LV2 plugin to shape a signal in various ways.
+ Copyright 2011 David Robillard
+ Copyright 2003 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "common.h"
+
+#define TRACKER_GATE 0
+#define TRACKER_HATTACK 1
+#define TRACKER_HDECAY 2
+#define TRACKER_LATTACK 3
+#define TRACKER_LDECAY 4
+#define TRACKER_INPUT 5
+#define TRACKER_OUTPUT 6
+
+typedef struct {
+ float* gate;
+ float* hattack;
+ float* hdecay;
+ float* lattack;
+ float* ldecay;
+ float* input;
+ float* output;
+ float coeff;
+ float last_value;
+} Tracker;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Tracker* plugin = (Tracker*)instance;
+
+ switch (port) {
+ case TRACKER_GATE:
+ plugin->gate = data;
+ break;
+ case TRACKER_HATTACK:
+ plugin->hattack = data;
+ break;
+ case TRACKER_HDECAY:
+ plugin->hdecay = data;
+ break;
+ case TRACKER_LATTACK:
+ plugin->lattack = data;
+ break;
+ case TRACKER_LDECAY:
+ plugin->ldecay = data;
+ break;
+ case TRACKER_INPUT:
+ plugin->input = data;
+ break;
+ case TRACKER_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Tracker* plugin = (Tracker*)malloc(sizeof(Tracker));
+
+ plugin->coeff = 2.0f * M_PI / (float)sample_rate;
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Tracker* plugin = (Tracker*)instance;
+
+ plugin->last_value = 0.0f;
+}
+
+static void
+runTracker_gaaadaia_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Tracker* plugin = (Tracker*)instance;
+
+ /* Gate (array of floats of length sample_count) */
+ float* gate = plugin->gate;
+
+ /* Gate High Attack Rate (array of floats of length sample_count) */
+ float* hattack = plugin->hattack;
+
+ /* Gate High Decay Rate (array of floats of length sample_count) */
+ float* hdecay = plugin->hdecay;
+
+ /* Gate Low Attack Rate (array of floats of length sample_count) */
+ float* lattack = plugin->lattack;
+
+ /* Gate Low Decay Rate (array of floats of length sample_count) */
+ float* ldecay = plugin->ldecay;
+
+ /* Input (array of floats of length sample_count) */
+ float* input = plugin->input;
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ /* Instance Data */
+ float coeff = plugin->coeff;
+ float last_value = plugin->last_value;
+
+ float rate;
+ float in;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in = input[s];
+
+ if (gate[s] > 0.0f) {
+ rate = in > last_value ? hattack[s] : hdecay[s];
+ } else {
+ rate = in > last_value ? lattack[s] : ldecay[s];
+ }
+
+ rate = f_min(1.0f, rate * coeff);
+ last_value = last_value * (1.0f - rate) + in * rate;
+
+ output[s] = last_value;
+ }
+
+ plugin->last_value = last_value;
+}
+
+static void
+runTracker_gaacdcia_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Tracker* plugin = (Tracker*)instance;
+
+ /* Gate (array of floats of length sample_count) */
+ float* gate = plugin->gate;
+
+ /* Gate High Attack Rate (float value) */
+ float hattack = *(plugin->hattack);
+
+ /* Gate High Decay Rate (float value) */
+ float hdecay = *(plugin->hdecay);
+
+ /* Gate Low Attack Rate (float value) */
+ float lattack = *(plugin->lattack);
+
+ /* Gate Low Decay Rate (float value) */
+ float ldecay = *(plugin->ldecay);
+
+ /* Input (array of floats of length sample_count) */
+ float* input = plugin->input;
+
+ /* Output (array of floats of length sample_count) */
+ float* output = plugin->output;
+
+ /* Instance Data */
+ float coeff = plugin->coeff;
+ float last_value = plugin->last_value;
+
+ float in;
+ float rate;
+
+ hattack = f_min(1.0f, hattack * coeff);
+ hdecay = f_min(1.0f, hdecay * coeff);
+ lattack = f_min(1.0f, lattack * coeff);
+ ldecay = f_min(1.0f, ldecay * coeff);
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ in = input[s];
+
+ if (gate[s] > 0.0f) {
+ rate = in > last_value ? hattack : hdecay;
+ } else {
+ rate = in > last_value ? lattack : ldecay;
+ }
+
+ last_value = last_value * (1.0f - rate) + in * rate;
+
+ output[s] = last_value;
+ }
+
+ plugin->last_value = last_value;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/tracker",
+ instantiate,
+ connect_port,
+ activate,
+ runTracker_gaacdcia_oa,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/triangle.c b/src/triangle.c
new file mode 100644
index 0000000..718369a
--- /dev/null
+++ b/src/triangle.c
@@ -0,0 +1,307 @@
+/*
+ An LV2 plugin to generate a bandlimited slope-variable triangle waveform.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "wavedata.h"
+
+#define TRIANGLE_FREQUENCY 0
+#define TRIANGLE_SLOPE 1
+#define TRIANGLE_OUTPUT 2
+
+typedef struct {
+ float* frequency;
+ float* slope;
+ float* output;
+ float phase;
+ float min_slope;
+ float max_slope;
+ Wavedata wdat;
+} Triangle;
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Triangle* plugin = (Triangle*)instance;
+
+ switch (port) {
+ case TRIANGLE_FREQUENCY:
+ plugin->frequency = data;
+ break;
+ case TRIANGLE_SLOPE:
+ plugin->slope = data;
+ break;
+ case TRIANGLE_OUTPUT:
+ plugin->output = data;
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Triangle* plugin = (Triangle*)malloc(sizeof(Triangle));
+
+ if (wavedata_load(&plugin->wdat, BLOP_DLSYM_PARABOLA, sample_rate)) {
+ free(plugin);
+ return 0;
+ }
+
+ plugin->min_slope = 2.0f / plugin->wdat.sample_rate;
+ plugin->max_slope = 1.0f - plugin->min_slope;
+
+ return (LV2_Handle)plugin;
+}
+
+static void
+cleanup(LV2_Handle instance)
+{
+ Triangle* plugin = (Triangle*)instance;
+
+ wavedata_unload(&plugin->wdat);
+ free(instance);
+}
+
+static void
+activate(LV2_Handle instance)
+{
+ Triangle* plugin = (Triangle*)instance;
+
+ plugin->phase = 0.0f;
+}
+
+static void
+runTriangle_fasa_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Triangle* plugin = (Triangle*)instance;
+
+ /* Frequency (array of float of length sample_count) */
+ float* frequency = plugin->frequency;
+
+ /* Slope (array of float of length sample_count) */
+ float* slope = plugin->slope;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ Wavedata* wdat = &plugin->wdat;
+ float phase = plugin->phase;
+ float min_slope = plugin->min_slope;
+ float max_slope = plugin->max_slope;
+
+ float freq;
+ float slp;
+ float phase_shift;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ freq = frequency[s];
+ slp = f_clip(slope[s], min_slope, max_slope);
+ phase_shift = slp * wdat->sample_rate;
+
+ /* Lookup which table to use from frequency */
+ wavedata_get_table(wdat, freq);
+
+ /* Get samples from parabola and phase shifted inverted parabola,
+ and scale to compensate */
+ output[s] = (wavedata_get_sample(wdat, phase)
+ - wavedata_get_sample(wdat, phase + phase_shift))
+ / (8.0f * (slp - (slp * slp)));
+
+ /* Update phase, wrapping if necessary */
+ phase += wdat->frequency;
+ if (phase < 0.0f) {
+ phase += wdat->sample_rate;
+ } else if (phase > wdat->sample_rate) {
+ phase -= wdat->sample_rate;
+ }
+ }
+ plugin->phase = phase;
+}
+
+static void
+runTriangle_fasc_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Triangle* plugin = (Triangle*)instance;
+
+ /* Frequency (array of float of length sample_count) */
+ float* frequency = plugin->frequency;
+
+ /* Slope (float value) */
+ float slope = *(plugin->slope);
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ Wavedata* wdat = &plugin->wdat;
+ float phase = plugin->phase;
+ float min_slope = plugin->min_slope;
+ float max_slope = plugin->max_slope;
+
+ float freq;
+ float phase_shift;
+ float scale;
+
+ slope = f_clip(slope, min_slope, max_slope);
+ scale = 1.0f / (8.0f * (slope - (slope * slope)));
+ phase_shift = slope * wdat->sample_rate;
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ freq = frequency[s];
+
+ /* Lookup which table to use from frequency */
+ wavedata_get_table(wdat, freq);
+
+ /* Get samples from parabola and phase shifted inverted parabola,
+ and scale to compensate */
+ output[s] = (wavedata_get_sample(wdat, phase)
+ - wavedata_get_sample(wdat, phase + phase_shift)) * scale;
+
+ /* Update phase, wrapping if necessary */
+ phase += wdat->frequency;
+ if (phase < 0.0f) {
+ phase += wdat->sample_rate;
+ } else if (phase > wdat->sample_rate) {
+ phase -= wdat->sample_rate;
+ }
+ }
+ plugin->phase = phase;
+}
+
+static void
+runTriangle_fcsa_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Triangle* plugin = (Triangle*)instance;
+
+ /* Frequency (float value) */
+ float frequency = *(plugin->frequency);
+
+ /* Slope (array of float of length sample_count) */
+ float* slope = plugin->slope;
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ Wavedata* wdat = &plugin->wdat;
+ float phase = plugin->phase;
+ float min_slope = plugin->min_slope;
+ float max_slope = plugin->max_slope;
+
+ float slp;
+ float phase_shift;
+
+ wavedata_get_table(wdat, frequency);
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ slp = f_clip(slope[s], min_slope, max_slope);
+ phase_shift = slp * wdat->sample_rate;
+
+ /* Get samples from parabola and phase shifted inverted parabola,
+ and scale to compensate */
+ output[s] = (wavedata_get_sample(wdat, phase)
+ - wavedata_get_sample(wdat, phase + phase_shift))
+ / (8.0f * (slp - (slp * slp)));
+
+ /* Update phase, wrapping if necessary */
+ phase += wdat->frequency;
+ if (phase < 0.0f) {
+ phase += wdat->sample_rate;
+ } else if (phase > wdat->sample_rate) {
+ phase -= wdat->sample_rate;
+ }
+ }
+ plugin->phase = phase;
+}
+
+static void
+runTriangle_fcsc_oa(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Triangle* plugin = (Triangle*)instance;
+
+ /* Frequency (float value) */
+ float frequency = *(plugin->frequency);
+
+ /* Slope (float value) */
+ float slope = *(plugin->slope);
+
+ /* Output (pointer to float value) */
+ float* output = plugin->output;
+
+ /* Instance data */
+ Wavedata* wdat = &plugin->wdat;
+ float phase = plugin->phase;
+ float min_slope = plugin->min_slope;
+ float max_slope = plugin->max_slope;
+
+ float scale;
+ float phase_shift;
+
+ slope = f_clip(slope, min_slope, max_slope);
+ scale = 1.0f / (8.0f * (slope - (slope * slope)));
+ phase_shift = slope * wdat->sample_rate;
+
+ wavedata_get_table(wdat, frequency);
+
+ for (uint32_t s = 0; s < sample_count; ++s) {
+ /* Get samples from parabola and phase shifted inverted parabola,
+ and scale to compensate */
+ output[s] = (wavedata_get_sample(wdat, phase)
+ - wavedata_get_sample(wdat, phase + phase_shift)) * scale;
+
+ /* Update phase, wrapping if necessary */
+ phase += wdat->frequency;
+ if (phase < 0.0f) {
+ phase += wdat->sample_rate;
+ } else if (phase > wdat->sample_rate) {
+ phase -= wdat->sample_rate;
+ }
+ }
+ plugin->phase = phase;
+}
+
+static const LV2_Descriptor descriptor = {
+ "http://drobilla.net/plugins/blip/triangle",
+ instantiate,
+ connect_port,
+ activate,
+ runTriangle_fcsc_oa,
+ NULL,
+ cleanup,
+ NULL,
+};
+
+LV2_SYMBOL_EXPORT const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0: return &descriptor;
+ default: return NULL;
+ }
+}
diff --git a/src/wavedata.c b/src/wavedata.c
new file mode 100644
index 0000000..8f7e359
--- /dev/null
+++ b/src/wavedata.c
@@ -0,0 +1,141 @@
+/*
+ Oscillator wave data generation.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include <config.h>
+#include "wavedata.h"
+
+#ifndef WAVEDATA_SUBDIR
+#warning *** No wavedata subdir given, using default 'blip_files'
+#define WAVEDATA_SUBDIR "blip_files"
+#endif
+
+int
+wavedata_load(Wavedata* w,
+ const char* wdat_descriptor_name,
+ unsigned long sample_rate)
+{
+ const char* subdir = WAVEDATA_SUBDIR;
+ char* ladspa_path;
+ const char* start;
+ const char* end;
+ int extra;
+ size_t subdirlen = strlen(WAVEDATA_SUBDIR);
+ size_t length;
+ size_t pathlen;
+ char* path;
+ char* filename;
+ DIR* dp;
+ struct dirent* ep;
+ struct stat sb;
+ void* handle;
+ int (*desc_func)(Wavedata*, unsigned long);
+ int retval = -1;
+
+ /* Get LADPSA_PATH, if available */
+ ladspa_path = getenv("LV2_PATH");
+ if (!ladspa_path) {
+ ladspa_path = "/usr/lib/ladspa:/usr/local/lib/ladspa";
+ }
+
+ start = ladspa_path;
+ while (*start != '\0') {
+ while (*start == ':') {
+ start++;
+ }
+ end = start;
+ while (*end != ':' && *end != '\0') {
+ end++;
+ }
+ if (end - start > 0) {
+ extra = (*(end - 1) == '/') ? 0 : 1;
+ path = (char*)malloc(end - start + extra + subdirlen + 1 + 1);
+ if (path) {
+ strncpy(path, start, end - start);
+ if (extra == 1) {
+ path[end - start] = '/';
+ }
+
+ path[end - start + extra] = '\0';
+
+ if (subdirlen > 0) {
+ strncat(path, subdir, subdirlen);
+ path[end - start + extra + subdirlen] = '/';
+ path[end - start + extra + subdirlen + 1] = '\0';
+ } else {
+ path[end - start + extra + subdirlen] = '\0';
+ }
+
+ dp = opendir(path);
+ if (dp) {
+ pathlen = strlen(path);
+ while ((ep = readdir(dp))) {
+ /* Stat file to get type */
+ length = pathlen + strlen(ep->d_name);
+ filename = (char*)malloc(length + 1);
+ if (filename) {
+ strncpy(filename, path, pathlen);
+
+ filename[pathlen] = '\0';
+ filename = strncat(filename, ep->d_name, strlen(ep->d_name));
+ filename[length] = '\0';
+
+ if (!stat(filename, &sb)) {
+ /* We only want regular files */
+ if (S_ISREG(sb.st_mode)) {
+ /* Whew. Now see if we've got the right dll */
+ handle = dlopen(filename, RTLD_NOW);
+
+ if (handle) {
+ desc_func = dlsym(handle, wdat_descriptor_name);
+
+ if (desc_func) {
+ free(filename);
+ free(path);
+ retval = desc_func(w, sample_rate);
+ w->data_handle = handle;
+ return retval;
+ }
+ }
+ }
+ }
+ free(filename);
+ }
+ }
+ closedir(dp);
+ }
+ free(path);
+ }
+ }
+ start = end;
+ }
+ return retval;
+}
+
+void
+wavedata_unload(Wavedata* w)
+{
+ dlclose(w->data_handle);
+}
diff --git a/src/wavegen.c b/src/wavegen.c
new file mode 100644
index 0000000..3728920
--- /dev/null
+++ b/src/wavegen.c
@@ -0,0 +1,319 @@
+/*
+ A program to generate c header files containing pre-calculated wavedata.
+ Copyright 2011 David Robillard
+ Copyright 2002 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "wdatutil.h"
+#include "wavedata.h"
+#include "common.h"
+
+static void
+usage(void)
+{
+ int i;
+
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Generate bandlimited wavedata and write as c header file\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Usage: wavegen -w <Wavename> -r <Sample Rate> -f <Note> -s <Note Step>\n");
+ fprintf(stderr, " -m <Samples> [-o <Output Filename>] [-p <Prefix>]\n");
+ fprintf(stderr, " [-g <Factor>] [-q] [-t] [-h]\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, " -w, --wave Name of wave to generate (case insensitive)\n");
+ fprintf(stderr, " -r, --rate Intended playback rate in Samples/Second\n");
+ fprintf(stderr, " -f, --first First MIDI note to generate table for\n");
+ fprintf(stderr, " -s, --step Number of MIDI notes to skip for next table\n");
+ fprintf(stderr, " -m, --min Minimum table size in samples\n");
+ fprintf(stderr, " -o, --output Output Filename, name of file to output\n");
+ fprintf(stderr, " If not given, output is to stdout\n");
+ fprintf(stderr, " -p, --prefix Prefix for declarations in header\n");
+ fprintf(stderr, " -g, --gibbs Compensate for Gibbs' effect\n");
+ fprintf(stderr, " -q, --quiet Surpress stderr output\n");
+ fprintf(stderr, " -t, --test Don't actually generate data\n");
+ fprintf(stderr, " -h, --help Print this text and exit\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Supported waves:\n");
+
+ for (i = 0; i < WAVE_TYPE_COUNT; i++) {
+ fprintf(stderr, " %s (%s)\n", wave_names[i], wave_descriptions[i]);
+ }
+
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Gibbs' Effect\n");
+ fprintf(stderr, " Gibbs' effect causes overshoot in waves generated from finite\n");
+ fprintf(stderr, " Fourier Series. Compensation can be applied, which will result in\n");
+ fprintf(stderr, " a waveform that sounds slightly less bright.\n");
+ fprintf(stderr, " Use the --gibbs option to set degree of compensatation, from 0.0\n");
+ fprintf(stderr, " (no compensation) to 1.0 (full compensation)\n");
+ fprintf(stderr, "\n");
+}
+
+/**
+ Create bandlimited wavedata header files for various
+ waveforms
+*/
+int
+main(int argc,
+ char** argv)
+{
+ int option_index;
+ int opt;
+ const char* options = "w:r:f:s:m:o:p:g:qth";
+ struct option long_options[] = {
+ { "wave", 1, 0, 'w' },
+ { "rate", 1, 0, 'r' },
+ { "first", 1, 0, 'f' },
+ { "step", 1, 0, 's' },
+ { "min", 1, 0, 'm' },
+ { "output", 1, 0, 'o' },
+ { "prefix", 0, 0, 'p' },
+ { "gibbs", 1, 0, 'g' },
+ { "quiet", 0, 0, 'q' },
+ { "test", 0, 0, 't' },
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+ };
+ int wavetype = -1;
+ long sample_rate = -1;
+ long first_note = -1;
+ long note_step = -1;
+ long min_table_size = -1;
+ char* filename = NULL;
+ FILE* file;
+ char* prefix = NULL;
+ float gibbs = 0.0f;
+ int quiet = 0;
+ int test = 0;
+
+ Wavedata* w;
+ float freq;
+ uint32_t sample_count;
+ unsigned long max_harmonic_hf;
+ unsigned long max_harmonic_lf;
+ unsigned long i;
+
+ size_t strcmplen;
+ size_t len1;
+ size_t len2;
+
+ /* Parse arguments */
+ if (argc == 1) {
+ usage();
+ exit(-1);
+ }
+
+ opterr = 0;
+ while ((opt = getopt_long(argc, argv, options, long_options, &option_index)) != -1) {
+ switch (opt) {
+ case 'w':
+ for (i = 0; i < WAVE_TYPE_COUNT; i++) {
+ len1 = strlen(optarg);
+ len2 = strlen(wave_names[i]);
+ strcmplen = len1 < len2 ? len1 : len2;
+
+ if (!strncasecmp(optarg, wave_names[i], strcmplen)) {
+ wavetype = i;
+ }
+ }
+ if (wavetype == -1) {
+ fprintf(stderr, "Unrecognised option for Wave: %s\n", optarg);
+ exit(-1);
+ }
+ break;
+ case 'r':
+ sample_rate = (long)atoi(optarg);
+ break;
+ case 'f':
+ first_note = (long)atoi(optarg);
+ break;
+ case 's':
+ note_step = (long)atoi(optarg);
+ break;
+ case 'm':
+ min_table_size = (long)atoi(optarg);
+ break;
+ case 'o':
+ filename = strdup(optarg);
+ break;
+ case 'p':
+ prefix = strdup(optarg);
+ break;
+ case 'g':
+ gibbs = atof(optarg);
+ break;
+ case 'q':
+ quiet = -1;
+ break;
+ case 't':
+ test = -1;
+ break;
+ case 'h':
+ usage();
+ exit(0);
+ break;
+ default:
+ usage();
+ exit(-1);
+ }
+ }
+
+ /* Check basic arguments */
+ if (wavetype == -1) {
+ if (!quiet) {
+ fprintf(stderr, "No wavetype specified.\n");
+ }
+ exit(-1);
+ }
+
+ if (sample_rate == -1) {
+ if (!quiet) {
+ fprintf(stderr, "No sample rate specified.\n");
+ }
+ exit(-1);
+ }
+
+ if (first_note == -1) {
+ if (!quiet) {
+ fprintf(stderr, "No first note specified.\n");
+ }
+ exit(-1);
+ }
+
+ if (note_step == -1) {
+ if (!quiet) {
+ fprintf(stderr, "No note step specified.\n");
+ }
+ exit(-1);
+ }
+
+ if (min_table_size == -1) {
+ if (!quiet) {
+ fprintf(stderr, "No minimum table size specified.\n");
+ }
+ exit(-1);
+ }
+
+ if (gibbs < 0.0f || gibbs > 1.0f) {
+ if (!quiet) {
+ fprintf(stderr, "Gibbs compensation clamped to [0.0, 1.0]\n");
+ fprintf(stderr, " Supplied value: %.2f\n", gibbs);
+ }
+ gibbs = gibbs < 0.0f ? 0.0f : gibbs;
+ gibbs = gibbs > 1.0f ? 1.0f : gibbs;
+ if (!quiet) {
+ fprintf(stderr, " Clamped to: %.2f\n", gibbs);
+ }
+ }
+
+ if (note_step < 1) {
+ if (!quiet) {
+ fprintf(stderr, "Using minimum note step of 1\n");
+ }
+ note_step = 1;
+ }
+
+ /* Get file to write to */
+ if (!filename) {
+ file = stdout;
+ } else {
+ file = fopen(filename, "w");
+ }
+
+ w = wavedata_new(sample_rate);
+
+ if (!w) {
+ if (!quiet) {
+ fprintf(stderr, "Unable to create wavedata\n");
+ }
+
+ exit(-1);
+ }
+
+ freq = FREQ_FROM_NOTE(first_note);
+ max_harmonic_lf = HARM_FROM_FREQ(freq, sample_rate);
+ max_harmonic_hf = max_harmonic_lf;
+
+ for (i = 0; max_harmonic_hf > MIN_HARM(wavetype); i += note_step) {
+ freq = FREQ_FROM_NOTE(first_note + i + note_step);
+ max_harmonic_hf = HARM_FROM_FREQ(freq, sample_rate);
+
+ max_harmonic_hf = ACTUAL_HARM(max_harmonic_hf, wavetype);
+ max_harmonic_lf = ACTUAL_HARM(max_harmonic_lf, wavetype);
+
+ while (max_harmonic_lf == max_harmonic_hf) {
+ i += note_step;
+ freq = FREQ_FROM_NOTE(first_note + i + note_step);
+ max_harmonic_hf = HARM_FROM_FREQ(freq, sample_rate);
+ max_harmonic_hf = ACTUAL_HARM(max_harmonic_hf, wavetype);
+ }
+
+ if (max_harmonic_lf > MIN_EXTRA_HARM(wavetype)) {
+ sample_count = max_harmonic_lf * 2;
+ sample_count = sample_count < min_table_size ? min_table_size : sample_count;
+
+ if (wavedata_add_table(w, sample_count, max_harmonic_lf)) {
+ if (!quiet) {
+ fprintf(stderr, "Could not add wavetable to wavedata\n");
+ }
+
+ wavedata_cleanup(w);
+ exit(-1);
+ }
+ }
+ max_harmonic_lf = max_harmonic_hf;
+ }
+
+ if (!quiet) {
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Generating %s wave\n", wave_names[wavetype]);
+ fprintf(stderr, " Sample Rate: %ld\n", sample_rate);
+ if (gibbs > 0.0f) {
+ fprintf(stderr, " Gibbs' compensation factor: %+.2f\n\n", gibbs);
+ }
+ }
+
+ wavedata_generate_tables(w, wavetype, gibbs);
+
+ if (!test) {
+ if (wavedata_write(w, file, prefix)) {
+ if (!quiet) {
+ fprintf(stderr, "Could not write to file %s!\n\n", filename);
+ }
+ } else {
+ if (!quiet) {
+ fprintf(stderr, "Written to file %s\n\n", filename);
+ }
+ }
+ }
+
+ if (filename) {
+ free(filename);
+ }
+
+ if (prefix) {
+ free(prefix);
+ }
+
+ wavedata_cleanup(w);
+
+ return 0;
+}
diff --git a/src/wdatutil.c b/src/wdatutil.c
new file mode 100644
index 0000000..190e8f5
--- /dev/null
+++ b/src/wdatutil.c
@@ -0,0 +1,672 @@
+/*
+ Code to generate wavedata for bandlimited waveforms.
+ Copyright 2011 David Robillard
+ Copyright 2003 Mike Rawes
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this software. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "common.h"
+#include "wavedata.h"
+#include "wdatutil.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void generate_sine(float* samples,
+ uint32_t sample_count);
+void generate_sawtooth(float* samples,
+ uint32_t sample_count,
+ unsigned long harmonics,
+ float gibbs_comp);
+void generate_square(float* samples,
+ uint32_t sample_count,
+ unsigned long harmonics,
+ float gibbs_comp);
+void generate_parabola(float* samples,
+ uint32_t sample_count,
+ unsigned long harmonics,
+ float gibbs_comp);
+
+#ifdef __cplusplus
+} /* extern "C" { */
+#endif
+
+char* wave_names[] = {
+ "Saw",
+ "Square",
+ "Parabola"
+};
+
+char* wave_descriptions[] = {
+ "Sawtooth Wave",
+ "Square Wave",
+ "Parabola Wave"
+};
+
+unsigned long wave_first_harmonics[] = {
+ 1,
+ 1,
+ 1
+};
+
+unsigned long wave_harmonic_intervals[] = {
+ 1,
+ 2,
+ 1
+};
+
+Wavedata*
+wavedata_new(double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)
+{
+ Wavedata* w;
+
+ w = (Wavedata*)malloc(sizeof(Wavedata));
+
+ if (!w) {
+ return 0;
+ }
+
+ w->data_handle = 0;
+ w->table_count = 0;
+ w->tables = 0;
+ w->lookup = 0;
+ w->lookup_max = 0;
+ w->sample_rate = (float)sample_rate;
+ w->nyquist = w->sample_rate * 0.5f;
+
+ return w;
+}
+
+static void
+wavedata_cleanup(Wavedata* w)
+{
+ unsigned long ti;
+ Wavetable* t;
+
+ for (ti = 0; ti < w->table_count; ti++) {
+ t = w->tables[ti];
+ if (t) {
+ if (t->samples_hf) {
+ free(t->samples_hf);
+ }
+
+ if (t->samples_lf) {
+ free(t->samples_lf);
+ }
+
+ free(t);
+ }
+ }
+
+ free(w);
+}
+
+int
+wavedata_add_table(Wavedata* w,
+ uint32_t sample_count,
+ unsigned long harmonics)
+{
+ Wavetable** tables;
+ Wavetable* t;
+ size_t bytes;
+
+ t = (Wavetable*)malloc(sizeof(Wavetable));
+
+ if (!t) {
+ return -1;
+ }
+
+ /* Extra 3 samples for interpolation */
+ bytes = (sample_count + 3) * sizeof(float);
+
+ t->samples_lf = (float*)malloc(bytes);
+
+ if (!t->samples_lf) {
+ free(t);
+ return -1;
+ }
+
+ t->samples_hf = (float*)malloc(bytes);
+
+ if (!t->samples_hf) {
+ free(t->samples_lf);
+ free(t);
+ return -1;
+ }
+
+ bytes = (w->table_count + 1) * sizeof(Wavetable*);
+ if (w->table_count == 0) {
+ tables = (Wavetable**)malloc(bytes);
+ } else {
+ tables = (Wavetable**)realloc(w->tables, bytes);
+ }
+
+ if (!tables) {
+ free(t);
+ return -1;
+ }
+
+ t->sample_count = sample_count;
+ t->harmonics = harmonics;
+
+ if (w->lookup_max < harmonics) {
+ w->lookup_max = harmonics;
+ }
+
+ tables[w->table_count] = t;
+ w->tables = tables;
+ w->table_count++;
+
+ return 0;
+}
+
+static void
+wavedata_generate_tables(Wavedata* w,
+ Wavetype wavetype,
+ float gibbs_comp)
+{
+ Wavetable* t;
+ float* samples_lf;
+ float* samples_hf;
+ unsigned long h_lf;
+ unsigned long h_hf;
+ unsigned long s;
+ unsigned long i;
+
+ for (i = 0; i < w->table_count; i++) {
+ t = w->tables[i];
+
+ h_lf = t->harmonics;
+
+ if (i < w->table_count - 1) {
+ h_hf = w->tables[i + 1]->harmonics;
+ } else {
+ h_hf = 1;
+ }
+
+ samples_lf = t->samples_lf;
+ samples_hf = t->samples_hf;
+ samples_lf++;
+ samples_hf++;
+
+ switch (wavetype) {
+ case SAW:
+ generate_sawtooth(samples_lf, t->sample_count, h_lf, gibbs_comp);
+ generate_sawtooth(samples_hf, t->sample_count, h_hf, gibbs_comp);
+ break;
+ case SQUARE:
+ generate_square(samples_lf, t->sample_count, h_lf, gibbs_comp);
+ generate_square(samples_hf, t->sample_count, h_hf, gibbs_comp);
+ break;
+ case PARABOLA:
+ generate_parabola(samples_lf, t->sample_count, h_lf, gibbs_comp);
+ generate_parabola(samples_hf, t->sample_count, h_hf, gibbs_comp);
+ break;
+ }
+
+ /* Basic denormalization */
+ for (uint32_t s = 0; s < t->sample_count; s++) {
+ samples_lf[s] = FABSF(samples_lf[s]) < SMALLEST_FLOAT ? 0.0 : samples_lf[s];
+ }
+
+ samples_lf--;
+ samples_lf[0] = samples_lf[t->sample_count];
+ samples_lf[t->sample_count + 1] = samples_hf[1];
+ samples_lf[t->sample_count + 2] = samples_hf[2];
+
+ for (uint32_t s = 0; s < t->sample_count; s++) {
+ samples_hf[s] = FABSF(samples_hf[s]) < SMALLEST_FLOAT ? 0.0 : samples_hf[s];
+ }
+
+ samples_hf--;
+ samples_hf[0] = samples_hf[t->sample_count];
+ samples_hf[t->sample_count + 1] = samples_hf[1];
+ samples_hf[t->sample_count + 2] = samples_hf[2];
+ }
+}
+
+int
+wavedata_write(Wavedata* w,
+ FILE* wdat_fp,
+ char* data_name)
+{
+ Wavetable* t = 0;
+ unsigned long table_count;
+ unsigned long i;
+ unsigned long j;
+ unsigned long s;
+ int column;
+ /*
+ * Extra table at end
+ */
+ table_count = w->table_count + 1;
+
+ fprintf(wdat_fp, "#include "lv 2 / lv2plug.in / ns / lv2core / lv2.h "\n");
+ fprintf(wdat_fp, "#include <stdio.h>\n");
+ fprintf(wdat_fp, "#include \"wavedata.h\"\n");
+ fprintf(wdat_fp, "\n");
+ /*
+ * Fixed data and tables
+ */
+ fprintf(wdat_fp, "unsigned long ref_count = 0;\n");
+ fprintf(wdat_fp, "unsigned long first_sample_rate = 0;\n");
+ fprintf(wdat_fp, "unsigned long table_count = %ld;\n", table_count);
+ fprintf(wdat_fp, "Wavetable tables[%ld];\n", table_count);
+ fprintf(wdat_fp, "Wavetable * ptables[%ld];\n", table_count);
+ fprintf(wdat_fp, "unsigned long lookup[%ld];\n", w->lookup_max + 1);
+ fprintf(wdat_fp, "unsigned long lookup_max = %ld;\n", w->lookup_max);
+ fprintf(wdat_fp, "\n");
+ /*
+ * Sample data
+ * Each table has an extra 3 samples for interpolation
+ */
+ for (i = 0; i < w->table_count; i++) {
+ t = w->tables[i];
+
+ fprintf(wdat_fp, "static float samples_lf_%ld[%ld] = {\n", i, t->sample_count + 3);
+
+ column = 0;
+ for (uint32_t s = 0; s < t->sample_count + 3 - 1; s++, column++) {
+ if (column == 5) {
+ fprintf(wdat_fp, "\n");
+ column = 0;
+ }
+ fprintf(wdat_fp, "%+.8ef,", t->samples_lf[s]);
+ }
+
+ if (column == 5) {
+ fprintf(wdat_fp, "\n");
+ }
+
+ fprintf(wdat_fp, "%+.8ef\n", t->samples_lf[s]);
+ fprintf(wdat_fp, "};\n");
+ fprintf(wdat_fp, "\n");
+
+ fprintf(wdat_fp, "static float samples_hf_%ld[%ld] = {\n", i, t->sample_count + 3);
+
+ column = 0;
+ for (uint32_t s = 0; s < t->sample_count + 3 - 1; s++, column++) {
+ if (column == 5) {
+ fprintf(wdat_fp, "\n");
+ column = 0;
+ }
+ fprintf(wdat_fp, "%+.8ef,", t->samples_hf[s]);
+ }
+
+ if (column == 5) {
+ fprintf(wdat_fp, "\n");
+ }
+
+ fprintf(wdat_fp, "%+.8ef\n", t->samples_hf[s]);
+ fprintf(wdat_fp, "};\n");
+ fprintf(wdat_fp, "\n");
+ }
+
+ fprintf(wdat_fp, "float samples_zero[%ld];\n", t->sample_count + 3);
+ fprintf(wdat_fp, "\n");
+ /*
+ * Function to get Wavedata - the sample rate is needed to calculate
+ * frequencies and related things
+ */
+ fprintf(wdat_fp, "int\n");
+ fprintf(
+ wdat_fp,
+ "blip_get_%s (Wavedata * w, double sample_rate,
+ const char* bundle_path,
+ const LV2_Feature* const* features)\n" ,
+ data_name);
+ fprintf(wdat_fp, "{\n");
+ fprintf(wdat_fp, "\tWavetable * t;\n");
+ fprintf(wdat_fp, "\tunsigned long ti;\n");
+ fprintf(wdat_fp, "\n");
+ /*
+ * Sample rate must be > 0
+ */
+ fprintf(wdat_fp, "\tif (sample_rate == 0)\n");
+ fprintf(wdat_fp, "\t\treturn -1;\n");
+ fprintf(wdat_fp, "\n");
+ /*
+ * First time call - set up all sample rate dependent data
+ */
+ fprintf(wdat_fp, "\tif (first_sample_rate == 0)\n");
+ fprintf(wdat_fp, "\t{\n");
+ fprintf(wdat_fp, "\t\tfirst_sample_rate = sample_rate;\n");
+ fprintf(wdat_fp, "\t\tw->sample_rate = (float) sample_rate;\n");
+ fprintf(wdat_fp, "\t\tw->nyquist = w->sample_rate / 2.0f;\n");
+ fprintf(wdat_fp, "\t\tw->table_count = table_count;\n");
+ fprintf(wdat_fp, "\t\tw->tables = ptables;\n");
+ fprintf(wdat_fp, "\t\tw->lookup = lookup;\n");
+ fprintf(wdat_fp, "\t\tw->lookup_max = lookup_max;\n");
+ fprintf(wdat_fp, "\n");
+ fprintf(wdat_fp, "\t\tfor (ti = 1; ti < table_count - 1; ti++)\n");
+ fprintf(wdat_fp, "\t\t{\n");
+ fprintf(wdat_fp, "\t\t\tt = ptables[ti];\n");
+ fprintf(wdat_fp,
+ "\t\t\tt->min_frequency = w->nyquist / (float) (ptables[ti - 1]->harmonics);\n");
+ fprintf(wdat_fp, "\t\t\tt->max_frequency = w->nyquist / (float) (t->harmonics);\n");
+ fprintf(wdat_fp, "\t\t}\n");
+ fprintf(wdat_fp, "\n");
+ fprintf(wdat_fp, "\t\tt = w->tables[0];\n");
+ fprintf(wdat_fp, "\t\tt->min_frequency = 0.0f;\n");
+ fprintf(wdat_fp, "\t\tt->max_frequency = ptables[1]->min_frequency;\n");
+ fprintf(wdat_fp, "\n");
+ fprintf(wdat_fp, "\t\tt = ptables[table_count - 1];\n");
+ fprintf(wdat_fp, "\t\tt->min_frequency = ptables[w->table_count - 2]->max_frequency;\n");
+ fprintf(wdat_fp, "\t\tt->max_frequency = w->nyquist;\n");
+ fprintf(wdat_fp, "\t\n");
+ fprintf(wdat_fp, "\t\tfor (ti = 0; ti < w->table_count; ti++)\n");
+ fprintf(wdat_fp, "\t\t{\n");
+ fprintf(wdat_fp, "\t\t\tt = w->tables[ti];\n");
+ fprintf(wdat_fp, "\t\t\tt->phase_scale_factor = (float) (t->sample_count) / w->sample_rate;\n");
+ fprintf(wdat_fp,
+ "\t\t\tt->range_scale_factor = 1.0f / (t->max_frequency - t->min_frequency);\n");
+ fprintf(wdat_fp, "\t\t}\n");
+ fprintf(wdat_fp, "\n");
+ fprintf(wdat_fp, "\t\treturn 0;\n");
+ fprintf(wdat_fp, "\t}\n");
+ /*
+ * Already called at least once, so just set up wavedata
+ */
+ fprintf(wdat_fp, "\telse if (sample_rate == first_sample_rate)\n");
+ fprintf(wdat_fp, "\t{\n");
+ fprintf(wdat_fp, "\t\tw->sample_rate = (float) sample_rate;\n");
+ fprintf(wdat_fp, "\t\tw->nyquist = w->sample_rate / 2.0f;\n");
+ fprintf(wdat_fp, "\t\tw->table_count = table_count;\n");
+ fprintf(wdat_fp, "\t\tw->tables = ptables;\n");
+ fprintf(wdat_fp, "\t\tw->lookup = lookup;\n");
+ fprintf(wdat_fp, "\t\tw->lookup_max = lookup_max;\n");
+ fprintf(wdat_fp, "\n");
+ fprintf(wdat_fp, "\t\treturn 0;\n");
+ fprintf(wdat_fp, "\t}\n");
+ /*
+ * Sample rate does not match, so fail
+ *
+ * NOTE: This means multiple sample rates are not supported
+ * This should not present any problems
+ */
+ fprintf(wdat_fp, "\telse\n");
+ fprintf(wdat_fp, "\t{\n");
+ fprintf(wdat_fp, "\t\treturn -1;\n");
+ fprintf(wdat_fp, "\t}\n");
+ fprintf(wdat_fp, "}\n");
+ fprintf(wdat_fp, "\n");
+ /*
+ * _init()
+ * Assemble tables and lookup
+ */
+ fprintf(wdat_fp, "void\n");
+ fprintf(wdat_fp, "_init (void)\n");
+ fprintf(wdat_fp, "{\n");
+ fprintf(wdat_fp, "\tunsigned long max_harmonic;\n");
+ fprintf(wdat_fp, "\tunsigned long ti;\n");
+ fprintf(wdat_fp, "\tunsigned long li;\n");
+ fprintf(wdat_fp, "\tunsigned long s;\n");
+ fprintf(wdat_fp, "\n");
+
+ for (i = 0; i < w->table_count; i++) {
+ t = w->tables[i];
+
+ fprintf(wdat_fp, "\ttables[%ld].sample_count = %ld;\n", i, t->sample_count);
+ fprintf(wdat_fp, "\ttables[%ld].samples_lf = samples_lf_%ld;\n", i, i);
+ fprintf(wdat_fp, "\ttables[%ld].samples_hf = samples_hf_%ld;\n", i, i);
+ fprintf(wdat_fp, "\ttables[%ld].harmonics = %ld;\n", i, t->harmonics);
+ fprintf(wdat_fp, "\n");
+ }
+ /*
+ * Last table - uses same sample data as previous table for lf data,
+ * and zeroes for hf data
+ */
+ i = w->table_count - 1;
+ j = i + 1;
+ t = w->tables[i];
+ /*
+ * Zero silent samples
+ */
+ fprintf(wdat_fp, "\tfor (uint32_t s = 0; s < %ld; s++)\n", t->sample_count + 3);
+ fprintf(wdat_fp, "\t\tsamples_zero[s] = 0.0f;\n");
+ fprintf(wdat_fp, "\n");
+
+ fprintf(wdat_fp, "\ttables[%ld].sample_count = %ld;\n", j, t->sample_count);
+ fprintf(wdat_fp, "\ttables[%ld].samples_lf = samples_hf_%ld;\n", j, i);
+ fprintf(wdat_fp, "\ttables[%ld].samples_hf = samples_zero;\n", j);
+ fprintf(wdat_fp, "\ttables[%ld].harmonics = 1;\n", j);
+ fprintf(wdat_fp, "\n");
+ /*
+ * Get pointers to each wavetable and put them in the pointer array
+ */
+ fprintf(wdat_fp, "\tfor (ti = 0; ti < table_count; ti++)\n");
+ fprintf(wdat_fp, "\t\tptables[ti] = &tables[ti];\n");
+ fprintf(wdat_fp, "\n");
+ /*
+ * Shift all sample offsets forward by one sample
+ * !!! NO! Don't!
+ fprintf (wdat_fp, "\tfor (ti = 0; ti < table_count; ti++)\n");
+ fprintf (wdat_fp, "\t{\n");
+ fprintf (wdat_fp, "\t\tptables[ti]->samples_lf++;\n");
+ fprintf (wdat_fp, "\t\tptables[ti]->samples_hf++;\n");
+ fprintf (wdat_fp, "\t}\n");
+ fprintf (wdat_fp, "\n");
+ */
+ /*
+ * Table lookup vector indexed by harmonic
+ * Add lookup data to vector
+ */
+ fprintf(wdat_fp, "\tli = 0;");
+ fprintf(wdat_fp, "\n");
+ fprintf(wdat_fp, "\tfor (ti = table_count - 1; ti > 0; ti--)\n");
+ fprintf(wdat_fp, "\t{\n");
+ fprintf(wdat_fp, "\t\tmax_harmonic = ptables[ti]->harmonics;\n");
+ fprintf(wdat_fp, "\n");
+ fprintf(wdat_fp, "\t\tfor ( ; li <= max_harmonic; li++)\n");
+ fprintf(wdat_fp, "\t\t\tlookup[li] = ti;\n");
+ fprintf(wdat_fp, "\t}\n");
+ fprintf(wdat_fp, "\n");
+ fprintf(wdat_fp, "\tfor ( ; li <= lookup_max; li++)\n");
+ fprintf(wdat_fp, "\t\tlookup[li] = 0;\n");
+ fprintf(wdat_fp, "}\n");
+
+ return 0;
+}
+
+static void
+generate_sawtooth(float* samples,
+ uint32_t sample_count,
+ unsigned long harmonics,
+ float gibbs_comp)
+{
+ double phase_scale = 2.0 * M_PI / (double)sample_count;
+ float scale = 2.0f / M_PI;
+ unsigned long i;
+ unsigned long h;
+ double mhf;
+ double hf;
+ double k;
+ double m;
+ double phase;
+ double partial;
+
+ if (gibbs_comp > 0.0f) {
+ /* Degree of Gibbs Effect compensation */
+ mhf = (double)harmonics;
+ k = M_PI * (double)gibbs_comp / mhf;
+
+ for (i = 0; i < sample_count; i++) {
+ samples[i] = 0.0f;
+ }
+
+ for (h = 1; h <= harmonics; h++) {
+ hf = (double)h;
+
+ /* Gibbs Effect compensation - Hamming window */
+ /* Modified slightly for smoother fade at highest frequencies */
+ m = 0.54 + 0.46 * cos((hf - 0.5 / mhf) * k);
+
+ for (i = 0; i < sample_count; i++) {
+ phase = (double)i * phase_scale;
+ partial = (m / hf) * sin(phase * hf);
+ samples[i] += (float)partial;
+ }
+ }
+
+ for (i = 0; i < sample_count; i++) {
+ samples[i] *= scale;
+ }
+ } else {
+ /* Allow overshoot */
+ for (i = 0; i < sample_count; i++) {
+ phase = (double)i * phase_scale;
+ samples[i] = 0.0f;
+
+ for (h = 1; h <= harmonics; h++) {
+ hf = (double)h;
+ partial = (1.0 / hf) * sin(phase * hf);
+ samples[i] += (float)partial;
+ }
+ samples[i] *= scale;
+ }
+ }
+}
+
+static void
+generate_square(float* samples,
+ uint32_t sample_count,
+ unsigned long harmonics,
+ float gibbs_comp)
+{
+ double phase_scale = 2.0 * M_PI / (double)sample_count;
+ float scale = 4.0f / M_PI;
+ unsigned long i;
+ unsigned long h;
+ double mhf;
+ double hf;
+ double k;
+ double m;
+ double phase;
+ double partial;
+
+ if (gibbs_comp > 0.0f) {
+ /* Degree of Gibbs Effect compensation */
+ mhf = (double)harmonics;
+ k = M_PI * (double)gibbs_comp / mhf;
+
+ for (i = 0; i < sample_count; i++) {
+ samples[i] = 0.0f;
+ }
+
+ for (h = 1; h <= harmonics; h += 2) {
+ hf = (double)h;
+
+ /* Gibbs Effect compensation - Hamming window */
+ /* Modified slightly for smoother fade at highest frequencies */
+ m = 0.54 + 0.46 * cos((hf - 0.5 / pow(mhf, 2.2)) * k);
+
+ for (i = 0; i < sample_count; i++) {
+ phase = (double)i * phase_scale;
+ partial = (m / hf) * sin(phase * hf);
+ samples[i] += (float)partial;
+ }
+ }
+
+ for (i = 0; i < sample_count; i++) {
+ samples[i] *= scale;
+ }
+ } else {
+ /* Allow overshoot */
+ for (i = 0; i < sample_count; i++) {
+ phase = (double)i * phase_scale;
+ samples[i] = 0.0f;
+
+ for (h = 1; h <= harmonics; h += 2) {
+ hf = (double)h;
+ partial = (1.0 / hf) * sin(phase * hf);
+ samples[i] += (float)partial;
+ }
+ samples[i] *= scale;
+ }
+ }
+}
+
+static void
+generate_parabola(float* samples,
+ uint32_t sample_count,
+ unsigned long harmonics,
+ float gibbs_comp)
+{
+ double phase_scale = 2.0 * M_PI / (double)sample_count;
+ float scale = 2.0f / (M_PI * M_PI);
+ unsigned long i;
+ unsigned long h;
+ double mhf;
+ double hf;
+ double k;
+ double m;
+ double phase;
+ double partial;
+ double sign;
+
+ if (gibbs_comp > 0.0f) {
+ /* Degree of Gibbs Effect compensation */
+ mhf = (double)harmonics;
+ k = M_PI * (double)gibbs_comp / mhf;
+
+ for (i = 0; i < sample_count; i++) {
+ samples[i] = 0.0f;
+ }
+
+ sign = -1.0;
+
+ for (h = 1; h <= harmonics; h++) {
+ hf = (double)h;
+
+ /* Gibbs Effect compensation - Hamming window */
+ /* Modified slightly for smoother fade at highest frequencies */
+ m = 0.54 + 0.46 * cos((hf - 0.5 / mhf) * k);
+
+ for (i = 0; i < sample_count; i++) {
+ phase = (double)i * phase_scale;
+ partial = (sign * 4.0 / (hf * hf)) * cos(phase * hf);
+ samples[i] += (float)partial;
+ }
+ sign = -sign;
+ }
+
+ for (i = 0; i < sample_count; i++) {
+ samples[i] *= scale;
+ }
+ } else {
+ /* Allow overshoot */
+ for (i = 0; i < sample_count; i++) {
+ phase = (double)i * phase_scale;
+ samples[i] = 0.0f;
+ sign = -1.0;
+
+ for (h = 1; h <= harmonics; h++) {
+ hf = (double)h;
+ partial = (sign * 4.0 / (hf * hf)) * cos(phase * hf);
+ samples[i] += (float)partial;
+ sign = -sign;
+ }
+ samples[i] *= scale;
+ }
+ }
+}
diff --git a/waf b/waf
new file mode 100755
index 0000000..c97be3e
--- /dev/null
+++ b/waf
Binary files differ
diff --git a/wscript b/wscript
new file mode 100644
index 0000000..e76ff78
--- /dev/null
+++ b/wscript
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+import os
+import shutil
+import subprocess
+from waflib.extras import autowaf as autowaf
+
+# Version of this package (even if built as a child)
+BLIP_VERSION = '0.0.0'
+
+# Variables for 'waf dist'
+APPNAME = 'blip.lv2'
+VERSION = BLIP_VERSION
+
+# Mandatory variables
+top = '.'
+out = 'build'
+
+def options(opt):
+ opt.load('compiler_c')
+ autowaf.set_options(opt)
+
+def configure(conf):
+ conf.load('compiler_c')
+ autowaf.configure(conf)
+ autowaf.display_header('Blip Configuration')
+
+ autowaf.check_header(conf, 'c', 'lv2/lv2plug.in/ns/lv2core/lv2.h')
+
+ conf.check(function_name = 'sinf',
+ header_name = 'math.h',
+ linkflags = '-lm',
+ define_name = 'HAVE_SINF',
+ mandatory = False)
+
+ conf.env.append_unique('CFLAGS', '-std=c99')
+ conf.env.append_unique('CFLAGS', '-D_XOPEN_SOURCE')
+
+ conf.write_config_header('config.h', remove=False)
+
+ # Set env['pluginlib_PATTERN']
+ pat = conf.env['cshlib_PATTERN']
+ if pat[0:3] == 'lib':
+ pat = pat[3:]
+ conf.env['pluginlib_PATTERN'] = pat
+ conf.env['pluginlib_EXT'] = pat[pat.rfind('.'):]
+
+ autowaf.display_msg(conf, "LV2 bundle directory",
+ conf.env['LV2DIR'])
+ print('')
+
+def build_plugin(bld, lang, bundle, name, source, cflags=[], libs=[]):
+ # Build plugin library
+ penv = bld.env.derive()
+ penv['cshlib_PATTERN'] = bld.env['pluginlib_PATTERN']
+ obj = bld(features = '%s %sshlib' % (lang,lang))
+ obj.env = penv
+ obj.source = source
+ obj.includes = [ '.', './src/include' ]
+ obj.name = name
+ obj.target = os.path.join(bundle, name)
+ obj.linkflags = [ '-nostartfiles' ]
+ if cflags != []:
+ obj.cflags = cflags
+ if libs != []:
+ autowaf.use_lib(bld, obj, libs)
+ obj.install_path = '${LV2DIR}/' + bundle
+
+ # Install data file
+ data_file = '%s.ttl' % name
+ bld.install_files('${LV2DIR}/' + bundle, os.path.join(bundle, data_file))
+
+def build(bld):
+ # Copy data files to build bundle (build/blip.lv2)
+ def do_copy(task):
+ src = task.inputs[0].abspath()
+ tgt = task.outputs[0].abspath()
+ return shutil.copy(src, tgt)
+
+ for i in bld.path.ant_glob('blip.lv2/*.ttl'):
+ bld(rule = do_copy,
+ source = i,
+ target = bld.path.get_bld().make_node('blip.lv2/%s' % i),
+ install_path = '${LV2DIR}/blip.lv2')
+
+ bld(features = 'subst',
+ source = 'blip.lv2/manifest.ttl.in',
+ target = bld.path.get_bld().make_node('blip.lv2/manifest.ttl'),
+ LIB_EXT = bld.env['pluginlib_EXT'],
+ install_path = '${LV2DIR}/blip.lv2')
+
+ plugins = '''
+ adsr
+ adsr_gt
+ amp
+ branch
+ dahdsr
+ difference
+ fmod
+ interpolator
+ product
+ random
+ ratio
+ sum
+ sync_pulse
+ sync_square
+ tracker
+ '''.split()
+# quantiser.so
+# sequencer.so
+
+ # Simple (single source file) plugins
+ for i in plugins:
+ build_plugin(bld, 'c', 'blip.lv2', i,
+ ['src/%s.c' % i])
+
+ # Low pass filter
+ build_plugin(bld, 'c', 'blip.lv2', 'lp4pole',
+ ['src/lp4pole.c', 'src/lp4pole_filter.c'])
+
+ # Oscillators
+ for i in ['pulse', 'sawtooth', 'square', 'triangle']:
+ build_plugin(bld, 'c', 'blip.lv2', i,
+ ['src/%s.c' % i, 'src/wavedata.c'])
+
+def lint(ctx):
+ subprocess.call('cpplint.py --filter=+whitespace/comments,-whitespace/tab,-whitespace/braces,-whitespace/labels,-build/header_guard,-readability/casting,-readability/todo,-build/include src/* serd/*', shell=True)