| @@ -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>. | |||
| @@ -0,0 +1,62 @@ | |||
| #!/usr/bin/make -f | |||
| # Makefile for static aubio # | |||
| # ------------------------- # | |||
| # Created by falkTX | |||
| # | |||
| # -------------------------------------------------------------- | |||
| # Import base definitions | |||
| USE_NANOVG_FBO = true | |||
| include ../../dpf/Makefile.base.mk | |||
| # -------------------------------------------------------------- | |||
| BUILD_C_FLAGS += -DHAVE_CONFIG_H | |||
| BUILD_C_FLAGS += -I. | |||
| BUILD_C_FLAGS += -Isrc | |||
| BUILD_C_FLAGS += $(shell pkg-config --cflags fftw3f) | |||
| OBJS = \ | |||
| src/cvec.c.o \ | |||
| src/fvec.c.o \ | |||
| src/lvec.c.o \ | |||
| src/mathutils.c.o \ | |||
| src/pitch/pitch.c.o \ | |||
| src/pitch/pitchfcomb.c.o \ | |||
| src/pitch/pitchmcomb.c.o \ | |||
| src/pitch/pitchschmitt.c.o \ | |||
| src/pitch/pitchspecacf.c.o \ | |||
| src/pitch/pitchyin.c.o \ | |||
| src/pitch/pitchyinfast.c.o \ | |||
| src/pitch/pitchyinfft.c.o \ | |||
| src/spectral/fft.c.o \ | |||
| src/spectral/phasevoc.c.o \ | |||
| src/temporal/a_weighting.c.o \ | |||
| src/temporal/biquad.c.o \ | |||
| src/temporal/c_weighting.c.o \ | |||
| src/temporal/filter.c.o \ | |||
| src/temporal/resampler.c.o \ | |||
| src/utils/log.c.o \ | |||
| # -------------------------------------------------------------- | |||
| all: libaubio.a | |||
| clean: | |||
| rm -f *.a src/*.d src/*.o src/*/*.d src/*/*.o | |||
| libaubio.a: $(OBJS) | |||
| rm -f $@ | |||
| $(AR) crs $@ $^ | |||
| # -------------------------------------------------------------- | |||
| %.c.o: %.c | |||
| $(CC) $< $(BUILD_C_FLAGS) -c -o $@ | |||
| # -------------------------------------------------------------- | |||
| -include $(OBJS:%.o=%.d) | |||
| # -------------------------------------------------------------- | |||
| @@ -0,0 +1,20 @@ | |||
| #ifndef AUBIO_CONFIG_H | |||
| #define AUBIO_CONFIG_H | |||
| #define HAVE_STDLIB_H 1 | |||
| #define HAVE_STDIO_H 1 | |||
| #define HAVE_MATH_H 1 | |||
| #define HAVE_STRING_H 1 | |||
| #define HAVE_LIMITS_H 1 | |||
| #define HAVE_STDARG_H 1 | |||
| #define HAVE_GETOPT_H 1 | |||
| #define HAVE_UNISTD_H 1 | |||
| #define HAVE_C99_VARARGS_MACROS 1 | |||
| #define HAVE_MEMCPY_HACKS 1 | |||
| #define HAVE_FFTW3 | |||
| #define HAVE_FFTW3F | |||
| #define HAVE_COMPLEX_H | |||
| #endif /* AUBIO_CONFIG_H */ | |||
| @@ -0,0 +1,208 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** \mainpage | |||
| \section introduction Introduction | |||
| aubio is a library to extract annotations from audio signals: it provides a | |||
| set of functions that take an input audio signal, and output pitch estimates, | |||
| attack times (onset), beat location estimates, and other annotation tasks. | |||
| \section basics Basics | |||
| All object structures in aubio share the same function prefixes and suffixes: | |||
| - \p new_aubio_foo creates the object \p foo | |||
| - \p aubio_foo_do executes the object \p foo | |||
| - \p del_aubio_foo destroys the object \p foo | |||
| All memory allocation and deallocation take place in the \p new_ and \p del_ | |||
| functions. Optionally, more than one \p _do methods are available. | |||
| Additional parameters can be adjusted and observed using: | |||
| - \p aubio_foo_get_param, getter function, gets the value of a parameter | |||
| - \p aubio_foo_set_param, setter function, changes the value of a parameter | |||
| Unless specified in its documentation, no memory operations take place in the | |||
| getter functions. However, memory resizing can take place in setter | |||
| functions. | |||
| \subsection vectors Vectors | |||
| Two basic structures are being used in aubio: ::fvec_t and ::cvec_t. The | |||
| ::fvec_t structures are used to store vectors of floating pointer number. | |||
| ::cvec_t are used to store complex number, as two vectors of norm and phase | |||
| elements. | |||
| Additionally, the ::lvec_t structure can be used to store floating point | |||
| numbers in double precision. They are mostly used to store filter | |||
| coefficients, to avoid instability. | |||
| \subsection objects Available objects | |||
| Here is a list of some of the most common objects for aubio: | |||
| \code | |||
| // fast Fourier transform (FFT) | |||
| aubio_fft_t *fft = new_aubio_fft (winsize); | |||
| // phase vocoder | |||
| aubio_pvoc_t *pv = new_aubio_pvoc (winsize, stepsize); | |||
| // onset detection | |||
| aubio_onset_t *onset = new_aubio_onset (method, winsize, stepsize, samplerate); | |||
| // pitch detection | |||
| aubio_pitch_t *pitch = new_aubio_pitch (method, winsize, stepsize, samplerate); | |||
| // beat tracking | |||
| aubio_tempo_t *tempo = new_aubio_tempo (method, winsize, stepsize, samplerate); | |||
| \endcode | |||
| See the <a href="globals_type.html">list of typedefs</a> for a complete list. | |||
| \subsection example Example | |||
| Here is a simple example that creates an A-Weighting filter and applies it to a | |||
| vector. | |||
| \code | |||
| // set window size, and sampling rate | |||
| uint_t winsize = 1024, sr = 44100; | |||
| // create a vector | |||
| fvec_t *this_buffer = new_fvec (winsize); | |||
| // create the a-weighting filter | |||
| aubio_filter_t *this_filter = new_aubio_filter_a_weighting (sr); | |||
| while (running) { | |||
| // here some code to put some data in this_buffer | |||
| // ... | |||
| // apply the filter, in place | |||
| aubio_filter_do (this_filter, this_buffer); | |||
| // here some code to get some data from this_buffer | |||
| // ... | |||
| } | |||
| // and free the structures | |||
| del_aubio_filter (this_filter); | |||
| del_fvec (this_buffer); | |||
| \endcode | |||
| Several examples of C programs are available in the \p examples/ and \p tests/src | |||
| directories of the source tree. | |||
| Some examples: | |||
| - @ref spectral/test-fft.c | |||
| - @ref spectral/test-phasevoc.c | |||
| - @ref onset/test-onset.c | |||
| - @ref pitch/test-pitch.c | |||
| - @ref tempo/test-tempo.c | |||
| - @ref test-fvec.c | |||
| - @ref test-cvec.c | |||
| \subsection unstable_api Unstable API | |||
| Several more functions are available and used within aubio, but not | |||
| documented here, either because they are not considered useful to the user, | |||
| or because they may need to be changed in the future. However, they can still | |||
| be used by defining AUBIO_UNSTABLE to 1 before including the aubio header: | |||
| \code | |||
| #define AUBIO_UNSTABLE 1 | |||
| #include <aubio/aubio.h> | |||
| \endcode | |||
| Future versions of aubio could break API compatibility with these functions | |||
| without warning. If you choose to use functions in AUBIO_UNSTABLE, you are on | |||
| your own. | |||
| \section download Download | |||
| Latest versions, further documentation, examples, wiki, and mailing lists can | |||
| be found at https://aubio.org . | |||
| */ | |||
| #ifndef AUBIO_H | |||
| #define AUBIO_H | |||
| /** @file aubio.h Global aubio include file. | |||
| You will want to include this file as: | |||
| @code | |||
| #include <aubio/aubio.h> | |||
| @endcode | |||
| To access headers with unstable prototypes, use: | |||
| @code | |||
| #define AUBIO_UNSTABLE 1 | |||
| #include <aubio/aubio.h> | |||
| @endcode | |||
| */ | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| #endif | |||
| /* in this order */ | |||
| #include "types.h" | |||
| #include "fvec.h" | |||
| // #include "cvec.h" | |||
| // #include "lvec.h" | |||
| // // #include "fmat.h" | |||
| // #include "musicutils.h" | |||
| // // #include "vecutils.h" | |||
| // #include "temporal/resampler.h" | |||
| // #include "temporal/filter.h" | |||
| // #include "temporal/biquad.h" | |||
| // #include "temporal/a_weighting.h" | |||
| // #include "temporal/c_weighting.h" | |||
| // #include "spectral/fft.h" | |||
| // // #include "spectral/dct.h" | |||
| // #include "spectral/phasevoc.h" | |||
| // // #include "spectral/filterbank.h" | |||
| // // #include "spectral/filterbank_mel.h" | |||
| // // #include "spectral/mfcc.h" | |||
| // // #include "spectral/specdesc.h" | |||
| // // #include "spectral/awhitening.h" | |||
| // // #include "spectral/tss.h" | |||
| #include "pitch/pitch.h" | |||
| // // #include "onset/onset.h" | |||
| // // #include "tempo/tempo.h" | |||
| // // #include "notes/notes.h" | |||
| // // #include "io/source.h" | |||
| // // #include "io/sink.h" | |||
| // // #include "synth/sampler.h" | |||
| // // #include "synth/wavetable.h" | |||
| // // #include "utils/parameter.h" | |||
| // #include "utils/log.h" | |||
| #ifdef __cplusplus | |||
| } /* extern "C" */ | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,359 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** @file | |||
| * Private include file | |||
| * | |||
| * This file is for inclusion from _within_ the library only. | |||
| */ | |||
| #ifndef AUBIO_PRIV_H | |||
| #define AUBIO_PRIV_H | |||
| /********************* | |||
| * | |||
| * External includes | |||
| * | |||
| */ | |||
| #ifdef HAVE_CONFIG_H | |||
| #include "config.h" | |||
| #endif | |||
| #ifdef HAVE_STDLIB_H | |||
| #include <stdlib.h> | |||
| #endif | |||
| #ifdef HAVE_STDIO_H | |||
| #include <stdio.h> | |||
| #endif | |||
| /* must be included before fftw3.h */ | |||
| #ifdef HAVE_COMPLEX_H | |||
| #include <complex.h> | |||
| #endif | |||
| #if defined(HAVE_FFTW3) || defined(HAVE_FFTW3F) | |||
| #include <fftw3.h> | |||
| #endif | |||
| #ifdef HAVE_MATH_H | |||
| #include <math.h> | |||
| #endif | |||
| #ifdef HAVE_STRING_H | |||
| #include <string.h> | |||
| #endif | |||
| #ifdef HAVE_LIMITS_H | |||
| #include <limits.h> // for CHAR_BIT, in C99 standard | |||
| #endif | |||
| #ifdef HAVE_STDARG_H | |||
| #include <stdarg.h> | |||
| #endif | |||
| #ifdef HAVE_ACCELERATE | |||
| #define HAVE_ATLAS 1 | |||
| #include <Accelerate/Accelerate.h> | |||
| #elif defined(HAVE_ATLAS_CBLAS_H) | |||
| #define HAVE_ATLAS 1 | |||
| #include <atlas/cblas.h> | |||
| #else | |||
| #undef HAVE_ATLAS | |||
| #endif | |||
| #ifdef HAVE_ACCELERATE | |||
| #include <Accelerate/Accelerate.h> | |||
| #ifndef HAVE_AUBIO_DOUBLE | |||
| #define aubio_vDSP_mmov vDSP_mmov | |||
| #define aubio_vDSP_vmul vDSP_vmul | |||
| #define aubio_vDSP_vfill vDSP_vfill | |||
| #define aubio_vDSP_meanv vDSP_meanv | |||
| #define aubio_vDSP_sve vDSP_sve | |||
| #define aubio_vDSP_maxv vDSP_maxv | |||
| #define aubio_vDSP_maxvi vDSP_maxvi | |||
| #define aubio_vDSP_minv vDSP_minv | |||
| #define aubio_vDSP_minvi vDSP_minvi | |||
| #define aubio_vDSP_dotpr vDSP_dotpr | |||
| #define aubio_vDSP_vclr vDSP_vclr | |||
| #else /* HAVE_AUBIO_DOUBLE */ | |||
| #define aubio_vDSP_mmov vDSP_mmovD | |||
| #define aubio_vDSP_vmul vDSP_vmulD | |||
| #define aubio_vDSP_vfill vDSP_vfillD | |||
| #define aubio_vDSP_meanv vDSP_meanvD | |||
| #define aubio_vDSP_sve vDSP_sveD | |||
| #define aubio_vDSP_maxv vDSP_maxvD | |||
| #define aubio_vDSP_maxvi vDSP_maxviD | |||
| #define aubio_vDSP_minv vDSP_minvD | |||
| #define aubio_vDSP_minvi vDSP_minviD | |||
| #define aubio_vDSP_dotpr vDSP_dotprD | |||
| #define aubio_vDSP_vclr vDSP_vclrD | |||
| #endif /* HAVE_AUBIO_DOUBLE */ | |||
| #endif /* HAVE_ACCELERATE */ | |||
| #ifdef HAVE_ATLAS | |||
| #ifndef HAVE_AUBIO_DOUBLE | |||
| #define aubio_catlas_set catlas_sset | |||
| #define aubio_cblas_copy cblas_scopy | |||
| #define aubio_cblas_swap cblas_sswap | |||
| #define aubio_cblas_dot cblas_sdot | |||
| #else /* HAVE_AUBIO_DOUBLE */ | |||
| #define aubio_catlas_set catlas_dset | |||
| #define aubio_cblas_copy cblas_dcopy | |||
| #define aubio_cblas_swap cblas_dswap | |||
| #define aubio_cblas_dot cblas_ddot | |||
| #endif /* HAVE_AUBIO_DOUBLE */ | |||
| #endif /* HAVE_ATLAS */ | |||
| #if defined HAVE_INTEL_IPP | |||
| #include <ippcore.h> | |||
| #include <ippvm.h> | |||
| #include <ipps.h> | |||
| #ifndef HAVE_AUBIO_DOUBLE | |||
| #define aubio_ippsSet ippsSet_32f | |||
| #define aubio_ippsZero ippsZero_32f | |||
| #define aubio_ippsCopy ippsCopy_32f | |||
| #define aubio_ippsMul ippsMul_32f | |||
| #define aubio_ippsMulC ippsMulC_32f | |||
| #define aubio_ippsAddC ippsAddC_32f | |||
| #define aubio_ippsLn ippsLn_32f_A21 | |||
| #define aubio_ippsMean(a,b,c) ippsMean_32f(a, b, c, ippAlgHintFast) | |||
| #define aubio_ippsSum(a,b,c) ippsSum_32f(a, b, c, ippAlgHintFast) | |||
| #define aubio_ippsMax ippsMax_32f | |||
| #define aubio_ippsMin ippsMin_32f | |||
| #else /* HAVE_AUBIO_DOUBLE */ | |||
| #define aubio_ippsSet ippsSet_64f | |||
| #define aubio_ippsZero ippsZero_64f | |||
| #define aubio_ippsCopy ippsCopy_64f | |||
| #define aubio_ippsMul ippsMul_64f | |||
| #define aubio_ippsMulC ippsMulC_64f | |||
| #define aubio_ippsAddC ippsAddC_64f | |||
| #define aubio_ippsLn ippsLn_64f_A26 | |||
| #define aubio_ippsMean ippsMean_64f | |||
| #define aubio_ippsSum ippsSum_64f | |||
| #define aubio_ippsMax ippsMax_64f | |||
| #define aubio_ippsMin ippsMin_64f | |||
| #endif /* HAVE_AUBIO_DOUBLE */ | |||
| #endif | |||
| #if !defined(HAVE_MEMCPY_HACKS) && !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS) && !defined(HAVE_INTEL_IPP) | |||
| #define HAVE_NOOPT 1 | |||
| #else | |||
| #undef HAVE_NOOPT | |||
| #endif | |||
| #include "types.h" | |||
| #define AUBIO_UNSTABLE 1 | |||
| #include "mathutils.h" | |||
| /**** | |||
| * | |||
| * SYSTEM INTERFACE | |||
| * | |||
| */ | |||
| /* Memory management */ | |||
| #define AUBIO_MALLOC(_n) malloc(_n) | |||
| #define AUBIO_REALLOC(_p,_n) realloc(_p,_n) | |||
| #define AUBIO_NEW(_t) (_t*)calloc(sizeof(_t), 1) | |||
| #define AUBIO_ARRAY(_t,_n) (_t*)calloc((_n)*sizeof(_t), 1) | |||
| #define AUBIO_MEMCPY(_dst,_src,_n) memcpy(_dst,_src,_n) | |||
| #define AUBIO_MEMSET(_dst,_src,_t) memset(_dst,_src,_t) | |||
| #define AUBIO_FREE(_p) free(_p) | |||
| /* file interface */ | |||
| #define AUBIO_FOPEN(_f,_m) fopen(_f,_m) | |||
| #define AUBIO_FCLOSE(_f) fclose(_f) | |||
| #define AUBIO_FREAD(_p,_s,_n,_f) fread(_p,_s,_n,_f) | |||
| #define AUBIO_FSEEK(_f,_n,_set) fseek(_f,_n,_set) | |||
| /* strings */ | |||
| #define AUBIO_STRLEN(_s) strlen(_s) | |||
| #define AUBIO_STRCMP(_s,_t) strcmp(_s,_t) | |||
| #define AUBIO_STRNCMP(_s,_t,_n) strncmp(_s,_t,_n) | |||
| #define AUBIO_STRCPY(_dst,_src) strcpy(_dst,_src) | |||
| #define AUBIO_STRCHR(_s,_c) strchr(_s,_c) | |||
| #ifdef strdup | |||
| #define AUBIO_STRDUP(s) strdup(s) | |||
| #else | |||
| #define AUBIO_STRDUP(s) AUBIO_STRCPY(AUBIO_MALLOC(AUBIO_STRLEN(s) + 1), s) | |||
| #endif | |||
| /* Error reporting */ | |||
| typedef enum { | |||
| AUBIO_OK = 0, | |||
| AUBIO_FAIL = 1 | |||
| } aubio_status; | |||
| /* Logging */ | |||
| #include "utils/log.h" | |||
| /** internal logging function, defined in utils/log.c */ | |||
| uint_t aubio_log(sint_t level, const char_t *fmt, ...); | |||
| #ifdef HAVE_C99_VARARGS_MACROS | |||
| #define AUBIO_ERR(...) aubio_log(AUBIO_LOG_ERR, "AUBIO ERROR: " __VA_ARGS__) | |||
| #define AUBIO_INF(...) aubio_log(AUBIO_LOG_INF, "AUBIO INFO: " __VA_ARGS__) | |||
| #define AUBIO_MSG(...) aubio_log(AUBIO_LOG_MSG, __VA_ARGS__) | |||
| #define AUBIO_DBG(...) aubio_log(AUBIO_LOG_DBG, __VA_ARGS__) | |||
| #define AUBIO_WRN(...) aubio_log(AUBIO_LOG_WRN, "AUBIO WARNING: " __VA_ARGS__) | |||
| #else | |||
| #define AUBIO_ERR(format, args...) aubio_log(AUBIO_LOG_ERR, "AUBIO ERROR: " format , ##args) | |||
| #define AUBIO_INF(format, args...) aubio_log(AUBIO_LOG_INF, "AUBIO INFO: " format , ##args) | |||
| #define AUBIO_MSG(format, args...) aubio_log(AUBIO_LOG_MSG, format , ##args) | |||
| #define AUBIO_DBG(format, args...) aubio_log(AUBIO_LOG_DBG, format , ##args) | |||
| #define AUBIO_WRN(format, args...) aubio_log(AUBIO_LOG_WRN, "AUBIO WARNING: " format, ##args) | |||
| #endif | |||
| #define AUBIO_ERROR AUBIO_ERR | |||
| #define AUBIO_QUIT(_s) exit(_s) | |||
| #define AUBIO_SPRINTF sprintf | |||
| #define AUBIO_MAX_SAMPLERATE (192000*8) | |||
| #define AUBIO_MAX_CHANNELS 1024 | |||
| /* pi and 2*pi */ | |||
| #ifndef M_PI | |||
| #define PI (3.14159265358979323846) | |||
| #else | |||
| #define PI (M_PI) | |||
| #endif | |||
| #define TWO_PI (PI*2.) | |||
| #ifndef PATH_MAX | |||
| #define PATH_MAX 1024 | |||
| #endif | |||
| /* aliases to math.h functions */ | |||
| #if !HAVE_AUBIO_DOUBLE | |||
| #define EXP expf | |||
| #define COS cosf | |||
| #define SIN sinf | |||
| #define ABS fabsf | |||
| #define POW powf | |||
| #define SQRT sqrtf | |||
| #define LOG10 log10f | |||
| #define LOG logf | |||
| #define FLOOR floorf | |||
| #define CEIL ceilf | |||
| #define ATAN atanf | |||
| #define ATAN2 atan2f | |||
| #else | |||
| #error using double | |||
| #define EXP exp | |||
| #define COS cos | |||
| #define SIN sin | |||
| #define ABS fabs | |||
| #define POW pow | |||
| #define SQRT sqrt | |||
| #define LOG10 log10 | |||
| #define LOG log | |||
| #define FLOOR floor | |||
| #define CEIL ceil | |||
| #define ATAN atan | |||
| #define ATAN2 atan2 | |||
| #endif | |||
| #define ROUND(x) FLOOR(x+.5) | |||
| /* aliases to complex.h functions */ | |||
| #if HAVE_AUBIO_DOUBLE || !defined(HAVE_COMPLEX_H) || defined(WIN32) | |||
| /* mingw32 does not know about c*f functions */ | |||
| #define EXPC cexp | |||
| /** complex = CEXPC(complex) */ | |||
| #define CEXPC cexp | |||
| /** sample = ARGC(complex) */ | |||
| #define ARGC carg | |||
| /** sample = ABSC(complex) norm */ | |||
| #define ABSC cabs | |||
| /** sample = REAL(complex) */ | |||
| #define REAL creal | |||
| /** sample = IMAG(complex) */ | |||
| #define IMAG cimag | |||
| #else | |||
| /** sample = EXPC(complex) */ | |||
| #define EXPC cexpf | |||
| /** complex = CEXPC(complex) */ | |||
| #define CEXPC cexp | |||
| /** sample = ARGC(complex) */ | |||
| #define ARGC cargf | |||
| /** sample = ABSC(complex) norm */ | |||
| #define ABSC cabsf | |||
| /** sample = REAL(complex) */ | |||
| #define REAL crealf | |||
| /** sample = IMAG(complex) */ | |||
| #define IMAG cimagf | |||
| #endif | |||
| /* avoid unresolved symbol with msvc 9 */ | |||
| #if defined(_MSC_VER) && (_MSC_VER < 1900) | |||
| #define isnan _isnan | |||
| #endif | |||
| /* handy shortcuts */ | |||
| #define DB2LIN(g) (POW(10.0,(g)*0.05f)) | |||
| #define LIN2DB(v) (20.0*LOG10(v)) | |||
| #define SQR(_a) ((_a)*(_a)) | |||
| #ifndef MAX | |||
| #define MAX(a,b) (((a)>(b))?(a):(b)) | |||
| #endif /* MAX */ | |||
| #ifndef MIN | |||
| #define MIN(a,b) (((a)<(b))?(a):(b)) | |||
| #endif /* MIN */ | |||
| #define ELEM_SWAP(a,b) { register smpl_t t=(a);(a)=(b);(b)=t; } | |||
| #define VERY_SMALL_NUMBER 2.e-42 //1.e-37 | |||
| /** if ABS(f) < VERY_SMALL_NUMBER, returns 1, else 0 */ | |||
| #define IS_DENORMAL(f) ABS(f) < VERY_SMALL_NUMBER | |||
| /** if ABS(f) < VERY_SMALL_NUMBER, returns 0., else f */ | |||
| #define KILL_DENORMAL(f) IS_DENORMAL(f) ? 0. : f | |||
| /** if f > VERY_SMALL_NUMBER, returns f, else returns VERY_SMALL_NUMBER */ | |||
| #define CEIL_DENORMAL(f) f < VERY_SMALL_NUMBER ? VERY_SMALL_NUMBER : f | |||
| #define SAFE_LOG10(f) LOG10(CEIL_DENORMAL(f)) | |||
| #define SAFE_LOG(f) LOG(CEIL_DENORMAL(f)) | |||
| /** silence unused parameter warning by adding an attribute */ | |||
| #if defined(__GNUC__) | |||
| #define UNUSED __attribute__((unused)) | |||
| #else | |||
| #define UNUSED | |||
| #endif | |||
| /* are we using gcc -std=c99 ? */ | |||
| #if defined(__STRICT_ANSI__) | |||
| #define strnlen(a,b) MIN(strlen(a),b) | |||
| #if !HAVE_AUBIO_DOUBLE | |||
| #define floorf floor | |||
| #endif | |||
| #endif /* __STRICT_ANSI__ */ | |||
| #endif /* AUBIO_PRIV_H */ | |||
| @@ -0,0 +1,169 @@ | |||
| /* | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "cvec.h" | |||
| cvec_t * new_cvec(uint_t length) { | |||
| cvec_t * s; | |||
| if ((sint_t)length <= 0) { | |||
| return NULL; | |||
| } | |||
| s = AUBIO_NEW(cvec_t); | |||
| s->length = length/2 + 1; | |||
| s->norm = AUBIO_ARRAY(smpl_t,s->length); | |||
| s->phas = AUBIO_ARRAY(smpl_t,s->length); | |||
| return s; | |||
| } | |||
| void del_cvec(cvec_t *s) { | |||
| AUBIO_FREE(s->norm); | |||
| AUBIO_FREE(s->phas); | |||
| AUBIO_FREE(s); | |||
| } | |||
| void cvec_norm_set_sample (cvec_t *s, smpl_t data, uint_t position) { | |||
| s->norm[position] = data; | |||
| } | |||
| void cvec_phas_set_sample (cvec_t *s, smpl_t data, uint_t position) { | |||
| s->phas[position] = data; | |||
| } | |||
| smpl_t cvec_norm_get_sample (cvec_t *s, uint_t position) { | |||
| return s->norm[position]; | |||
| } | |||
| smpl_t cvec_phas_get_sample (cvec_t *s, uint_t position) { | |||
| return s->phas[position]; | |||
| } | |||
| smpl_t * cvec_norm_get_data (const cvec_t *s) { | |||
| return s->norm; | |||
| } | |||
| smpl_t * cvec_phas_get_data (const cvec_t *s) { | |||
| return s->phas; | |||
| } | |||
| /* helper functions */ | |||
| void cvec_print(const cvec_t *s) { | |||
| uint_t j; | |||
| AUBIO_MSG("norm: "); | |||
| for (j=0; j< s->length; j++) { | |||
| AUBIO_MSG(AUBIO_SMPL_FMT " ", s->norm[j]); | |||
| } | |||
| AUBIO_MSG("\n"); | |||
| AUBIO_MSG("phas: "); | |||
| for (j=0; j< s->length; j++) { | |||
| AUBIO_MSG(AUBIO_SMPL_FMT " ", s->phas[j]); | |||
| } | |||
| AUBIO_MSG("\n"); | |||
| } | |||
| void cvec_copy(const cvec_t *s, cvec_t *t) { | |||
| if (s->length != t->length) { | |||
| AUBIO_ERR("trying to copy %d elements to %d elements \n", | |||
| s->length, t->length); | |||
| return; | |||
| } | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsCopy(s->phas, t->phas, (int)s->length); | |||
| aubio_ippsCopy(s->norm, t->norm, (int)s->length); | |||
| #elif defined(HAVE_MEMCPY_HACKS) | |||
| memcpy(t->norm, s->norm, t->length * sizeof(smpl_t)); | |||
| memcpy(t->phas, s->phas, t->length * sizeof(smpl_t)); | |||
| #else | |||
| uint_t j; | |||
| for (j=0; j< t->length; j++) { | |||
| t->norm[j] = s->norm[j]; | |||
| t->phas[j] = s->phas[j]; | |||
| } | |||
| #endif | |||
| } | |||
| void cvec_norm_set_all(cvec_t *s, smpl_t val) { | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsSet(val, s->norm, (int)s->length); | |||
| #else | |||
| uint_t j; | |||
| for (j=0; j< s->length; j++) { | |||
| s->norm[j] = val; | |||
| } | |||
| #endif | |||
| } | |||
| void cvec_norm_zeros(cvec_t *s) { | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsZero(s->norm, (int)s->length); | |||
| #elif defined(HAVE_MEMCPY_HACKS) | |||
| memset(s->norm, 0, s->length * sizeof(smpl_t)); | |||
| #else | |||
| cvec_norm_set_all (s, 0.); | |||
| #endif | |||
| } | |||
| void cvec_norm_ones(cvec_t *s) { | |||
| cvec_norm_set_all (s, 1.); | |||
| } | |||
| void cvec_phas_set_all (cvec_t *s, smpl_t val) { | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsSet(val, s->phas, (int)s->length); | |||
| #else | |||
| uint_t j; | |||
| for (j=0; j< s->length; j++) { | |||
| s->phas[j] = val; | |||
| } | |||
| #endif | |||
| } | |||
| void cvec_phas_zeros(cvec_t *s) { | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsZero(s->phas, (int)s->length); | |||
| #elif defined(HAVE_MEMCPY_HACKS) | |||
| memset(s->phas, 0, s->length * sizeof(smpl_t)); | |||
| #else | |||
| cvec_phas_set_all (s, 0.); | |||
| #endif | |||
| } | |||
| void cvec_phas_ones(cvec_t *s) { | |||
| cvec_phas_set_all (s, 1.); | |||
| } | |||
| void cvec_zeros(cvec_t *s) { | |||
| cvec_norm_zeros(s); | |||
| cvec_phas_zeros(s); | |||
| } | |||
| void cvec_logmag(cvec_t *s, smpl_t lambda) { | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsMulC(s->norm, lambda, s->norm, (int)s->length); | |||
| aubio_ippsAddC(s->norm, 1.0, s->norm, (int)s->length); | |||
| aubio_ippsLn(s->norm, s->norm, (int)s->length); | |||
| #else | |||
| uint_t j; | |||
| for (j=0; j< s->length; j++) { | |||
| s->norm[j] = LOG(lambda * s->norm[j] + 1); | |||
| } | |||
| #endif | |||
| } | |||
| @@ -0,0 +1,247 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #ifndef AUBIO_CVEC_H | |||
| #define AUBIO_CVEC_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** \file | |||
| Vector of complex-valued data, stored in polar coordinates | |||
| This file specifies the ::cvec_t buffer type, which is used throughout aubio | |||
| to store complex data. Complex values are stored in terms of ::cvec_t.phas | |||
| and norm, within 2 vectors of ::smpl_t of size (size/2+1) each. | |||
| \example test-cvec.c | |||
| */ | |||
| /** Vector of real-valued phase and spectrum data | |||
| \code | |||
| uint_t buffer_size = 1024; | |||
| // create a complex vector of 512 values | |||
| cvec_t * input = new_cvec (buffer_size); | |||
| // set some values of the vector | |||
| input->norm[23] = 2.; | |||
| input->phas[23] = M_PI; | |||
| // .. | |||
| // compute the mean of the vector | |||
| mean = cvec_mean(input); | |||
| // destroy the vector | |||
| del_cvec (input); | |||
| \endcode | |||
| */ | |||
| typedef struct { | |||
| uint_t length; /**< length of buffer = (requested length)/2 + 1 */ | |||
| smpl_t *norm; /**< norm array of size ::cvec_t.length */ | |||
| smpl_t *phas; /**< phase array of size ::cvec_t.length */ | |||
| } cvec_t; | |||
| /** cvec_t buffer creation function | |||
| This function creates a cvec_t structure holding two arrays of size | |||
| [length/2+1], corresponding to the norm and phase values of the | |||
| spectral frame. The length stored in the structure is the actual size of both | |||
| arrays, not the length of the complex and symmetrical vector, specified as | |||
| creation argument. | |||
| \param length the length of the buffer to create | |||
| */ | |||
| cvec_t * new_cvec(uint_t length); | |||
| /** cvec_t buffer deletion function | |||
| \param s buffer to delete as returned by new_cvec() | |||
| */ | |||
| void del_cvec(cvec_t *s); | |||
| /** write norm value in a complex buffer | |||
| This is equivalent to: | |||
| \code | |||
| s->norm[position] = val; | |||
| \endcode | |||
| \param s vector to write to | |||
| \param val norm value to write in s->norm[position] | |||
| \param position sample position to write to | |||
| */ | |||
| void cvec_norm_set_sample (cvec_t *s, smpl_t val, uint_t position); | |||
| /** write phase value in a complex buffer | |||
| This is equivalent to: | |||
| \code | |||
| s->phas[position] = val; | |||
| \endcode | |||
| \param s vector to write to | |||
| \param val phase value to write in s->phas[position] | |||
| \param position sample position to write to | |||
| */ | |||
| void cvec_phas_set_sample (cvec_t *s, smpl_t val, uint_t position); | |||
| /** read norm value from a complex buffer | |||
| This is equivalent to: | |||
| \code | |||
| smpl_t foo = s->norm[position]; | |||
| \endcode | |||
| \param s vector to read from | |||
| \param position sample position to read from | |||
| */ | |||
| smpl_t cvec_norm_get_sample (cvec_t *s, uint_t position); | |||
| /** read phase value from a complex buffer | |||
| This is equivalent to: | |||
| \code | |||
| smpl_t foo = s->phas[position]; | |||
| \endcode | |||
| \param s vector to read from | |||
| \param position sample position to read from | |||
| \returns the value of the sample at position | |||
| */ | |||
| smpl_t cvec_phas_get_sample (cvec_t *s, uint_t position); | |||
| /** read norm data from a complex buffer | |||
| \code | |||
| smpl_t *data = s->norm; | |||
| \endcode | |||
| \param s vector to read from | |||
| */ | |||
| smpl_t * cvec_norm_get_data (const cvec_t *s); | |||
| /** read phase data from a complex buffer | |||
| This is equivalent to: | |||
| \code | |||
| smpl_t *data = s->phas; | |||
| \endcode | |||
| \param s vector to read from | |||
| */ | |||
| smpl_t * cvec_phas_get_data (const cvec_t *s); | |||
| /** print out cvec data | |||
| \param s vector to print out | |||
| */ | |||
| void cvec_print(const cvec_t *s); | |||
| /** make a copy of a vector | |||
| \param s source vector | |||
| \param t vector to copy to | |||
| */ | |||
| void cvec_copy(const cvec_t *s, cvec_t *t); | |||
| /** set all norm elements to a given value | |||
| \param s vector to modify | |||
| \param val value to set elements to | |||
| */ | |||
| void cvec_norm_set_all (cvec_t *s, smpl_t val); | |||
| /** set all norm elements to zero | |||
| \param s vector to modify | |||
| */ | |||
| void cvec_norm_zeros(cvec_t *s); | |||
| /** set all norm elements to one | |||
| \param s vector to modify | |||
| */ | |||
| void cvec_norm_ones(cvec_t *s); | |||
| /** set all phase elements to a given value | |||
| \param s vector to modify | |||
| \param val value to set elements to | |||
| */ | |||
| void cvec_phas_set_all (cvec_t *s, smpl_t val); | |||
| /** set all phase elements to zero | |||
| \param s vector to modify | |||
| */ | |||
| void cvec_phas_zeros(cvec_t *s); | |||
| /** set all phase elements to one | |||
| \param s vector to modify | |||
| */ | |||
| void cvec_phas_ones(cvec_t *s); | |||
| /** set all norm and phas elements to zero | |||
| \param s vector to modify | |||
| */ | |||
| void cvec_zeros(cvec_t *s); | |||
| /** take logarithmic magnitude | |||
| \param s input cvec to compress | |||
| \param lambda value to use for normalisation | |||
| \f$ S_k = log( \lambda * S_k + 1 ) \f$ | |||
| */ | |||
| void cvec_logmag(cvec_t *s, smpl_t lambda); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_CVEC_H */ | |||
| @@ -0,0 +1,149 @@ | |||
| /* | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| fvec_t * new_fvec(uint_t length) { | |||
| fvec_t * s; | |||
| if ((sint_t)length <= 0) { | |||
| return NULL; | |||
| } | |||
| s = AUBIO_NEW(fvec_t); | |||
| s->length = length; | |||
| s->data = AUBIO_ARRAY(smpl_t, s->length); | |||
| return s; | |||
| } | |||
| void del_fvec(fvec_t *s) { | |||
| AUBIO_FREE(s->data); | |||
| AUBIO_FREE(s); | |||
| } | |||
| void fvec_set_sample(fvec_t *s, smpl_t data, uint_t position) { | |||
| s->data[position] = data; | |||
| } | |||
| smpl_t fvec_get_sample(const fvec_t *s, uint_t position) { | |||
| return s->data[position]; | |||
| } | |||
| smpl_t * fvec_get_data(const fvec_t *s) { | |||
| return s->data; | |||
| } | |||
| /* helper functions */ | |||
| void fvec_print(const fvec_t *s) { | |||
| uint_t j; | |||
| for (j=0; j< s->length; j++) { | |||
| AUBIO_MSG(AUBIO_SMPL_FMT " ", s->data[j]); | |||
| } | |||
| AUBIO_MSG("\n"); | |||
| } | |||
| void fvec_set_all (fvec_t *s, smpl_t val) { | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsSet(val, s->data, (int)s->length); | |||
| #elif defined(HAVE_ATLAS) | |||
| aubio_catlas_set(s->length, val, s->data, 1); | |||
| #elif defined(HAVE_ACCELERATE) | |||
| aubio_vDSP_vfill(&val, s->data, 1, s->length); | |||
| #else | |||
| uint_t j; | |||
| for ( j = 0; j< s->length; j++ ) | |||
| { | |||
| s->data[j] = val; | |||
| } | |||
| #endif | |||
| } | |||
| void fvec_zeros(fvec_t *s) { | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsZero(s->data, (int)s->length); | |||
| #elif defined(HAVE_ACCELERATE) | |||
| aubio_vDSP_vclr(s->data, 1, s->length); | |||
| #elif defined(HAVE_MEMCPY_HACKS) | |||
| memset(s->data, 0, s->length * sizeof(smpl_t)); | |||
| #else | |||
| fvec_set_all(s, 0.); | |||
| #endif | |||
| } | |||
| void fvec_ones(fvec_t *s) { | |||
| fvec_set_all (s, 1.); | |||
| } | |||
| void fvec_rev(fvec_t *s) { | |||
| uint_t j; | |||
| for (j=0; j< FLOOR((smpl_t)s->length/2); j++) { | |||
| ELEM_SWAP(s->data[j], s->data[s->length-1-j]); | |||
| } | |||
| } | |||
| void fvec_weight(fvec_t *s, const fvec_t *weight) { | |||
| uint_t length = MIN(s->length, weight->length); | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsMul(s->data, weight->data, s->data, (int)length); | |||
| #elif defined(HAVE_ACCELERATE) | |||
| aubio_vDSP_vmul( s->data, 1, weight->data, 1, s->data, 1, length ); | |||
| #else | |||
| uint_t j; | |||
| for (j = 0; j < length; j++) { | |||
| s->data[j] *= weight->data[j]; | |||
| } | |||
| #endif /* HAVE_ACCELERATE */ | |||
| } | |||
| void fvec_weighted_copy(const fvec_t *in, const fvec_t *weight, fvec_t *out) { | |||
| uint_t length = MIN(in->length, MIN(out->length, weight->length)); | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsMul(in->data, weight->data, out->data, (int)length); | |||
| #elif defined(HAVE_ACCELERATE) | |||
| aubio_vDSP_vmul(in->data, 1, weight->data, 1, out->data, 1, length); | |||
| #else | |||
| uint_t j; | |||
| for (j = 0; j < length; j++) { | |||
| out->data[j] = in->data[j] * weight->data[j]; | |||
| } | |||
| #endif | |||
| } | |||
| void fvec_copy(const fvec_t *s, fvec_t *t) { | |||
| if (s->length != t->length) { | |||
| AUBIO_ERR("trying to copy %d elements to %d elements \n", | |||
| s->length, t->length); | |||
| return; | |||
| } | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsCopy(s->data, t->data, (int)s->length); | |||
| #elif defined(HAVE_BLAS) | |||
| aubio_cblas_copy(s->length, s->data, 1, t->data, 1); | |||
| #elif defined(HAVE_ACCELERATE) | |||
| aubio_vDSP_mmov(s->data, t->data, 1, s->length, 1, 1); | |||
| #elif defined(HAVE_MEMCPY_HACKS) | |||
| memcpy(t->data, s->data, t->length * sizeof(smpl_t)); | |||
| #else | |||
| uint_t j; | |||
| for (j = 0; j < t->length; j++) { | |||
| t->data[j] = s->data[j]; | |||
| } | |||
| #endif | |||
| } | |||
| @@ -0,0 +1,178 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #ifndef AUBIO_FVEC_H | |||
| #define AUBIO_FVEC_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** \file | |||
| Vector of real-valued data | |||
| This file specifies the ::fvec_t buffer type, which is used throughout aubio | |||
| to store vector of real-valued ::smpl_t. | |||
| \example test-fvec.c | |||
| */ | |||
| /** Buffer for real data | |||
| Vector of real-valued data | |||
| ::fvec_t is is the structure used to store vector of real-valued data, ::smpl_t . | |||
| \code | |||
| uint_t buffer_size = 1024; | |||
| // create a vector of 512 values | |||
| fvec_t * input = new_fvec (buffer_size); | |||
| // set some values of the vector | |||
| input->data[23] = 2.; | |||
| // .. | |||
| // compute the mean of the vector | |||
| mean = fvec_mean(a_vector); | |||
| // destroy the vector | |||
| del_fvec(a_vector); | |||
| \endcode | |||
| See `examples/` and `tests/src` directories for more examples. | |||
| */ | |||
| typedef struct { | |||
| uint_t length; /**< length of buffer */ | |||
| smpl_t *data; /**< data vector of length ::fvec_t.length */ | |||
| } fvec_t; | |||
| /** fvec_t buffer creation function | |||
| \param length the length of the buffer to create | |||
| */ | |||
| fvec_t * new_fvec(uint_t length); | |||
| /** fvec_t buffer deletion function | |||
| \param s buffer to delete as returned by new_fvec() | |||
| */ | |||
| void del_fvec(fvec_t *s); | |||
| /** read sample value in a buffer | |||
| \param s vector to read from | |||
| \param position sample position to read from | |||
| */ | |||
| smpl_t fvec_get_sample(const fvec_t *s, uint_t position); | |||
| /** write sample value in a buffer | |||
| \param s vector to write to | |||
| \param data value to write in s->data[position] | |||
| \param position sample position to write to | |||
| */ | |||
| void fvec_set_sample(fvec_t *s, smpl_t data, uint_t position); | |||
| /** read data from a buffer | |||
| \param s vector to read from | |||
| */ | |||
| smpl_t * fvec_get_data(const fvec_t *s); | |||
| /** print out fvec data | |||
| \param s vector to print out | |||
| */ | |||
| void fvec_print(const fvec_t *s); | |||
| /** set all elements to a given value | |||
| \param s vector to modify | |||
| \param val value to set elements to | |||
| */ | |||
| void fvec_set_all (fvec_t *s, smpl_t val); | |||
| /** set all elements to zero | |||
| \param s vector to modify | |||
| */ | |||
| void fvec_zeros(fvec_t *s); | |||
| /** set all elements to ones | |||
| \param s vector to modify | |||
| */ | |||
| void fvec_ones(fvec_t *s); | |||
| /** revert order of vector elements | |||
| \param s vector to revert | |||
| */ | |||
| void fvec_rev(fvec_t *s); | |||
| /** apply weight to vector | |||
| If the weight vector is longer than s, only the first elements are used. If | |||
| the weight vector is shorter than s, the last elements of s are not weighted. | |||
| \param s vector to weight | |||
| \param weight weighting coefficients | |||
| */ | |||
| void fvec_weight(fvec_t *s, const fvec_t *weight); | |||
| /** make a copy of a vector | |||
| \param s source vector | |||
| \param t vector to copy to | |||
| */ | |||
| void fvec_copy(const fvec_t *s, fvec_t *t); | |||
| /** make a copy of a vector, applying weights to each element | |||
| \param in input vector | |||
| \param weight weights vector | |||
| \param out output vector | |||
| */ | |||
| void fvec_weighted_copy(const fvec_t *in, const fvec_t *weight, fvec_t *out); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_FVEC_H */ | |||
| @@ -0,0 +1,80 @@ | |||
| /* | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "lvec.h" | |||
| lvec_t * new_lvec(uint_t length) { | |||
| lvec_t * s; | |||
| if ((sint_t)length <= 0) { | |||
| return NULL; | |||
| } | |||
| s = AUBIO_NEW(lvec_t); | |||
| s->length = length; | |||
| s->data = AUBIO_ARRAY(lsmp_t, s->length); | |||
| return s; | |||
| } | |||
| void del_lvec(lvec_t *s) { | |||
| AUBIO_FREE(s->data); | |||
| AUBIO_FREE(s); | |||
| } | |||
| void lvec_set_sample(lvec_t *s, lsmp_t data, uint_t position) { | |||
| s->data[position] = data; | |||
| } | |||
| lsmp_t lvec_get_sample(lvec_t *s, uint_t position) { | |||
| return s->data[position]; | |||
| } | |||
| lsmp_t * lvec_get_data(const lvec_t *s) { | |||
| return s->data; | |||
| } | |||
| /* helper functions */ | |||
| void lvec_print(const lvec_t *s) { | |||
| uint_t j; | |||
| for (j=0; j< s->length; j++) { | |||
| AUBIO_MSG(AUBIO_LSMP_FMT " ", s->data[j]); | |||
| } | |||
| AUBIO_MSG("\n"); | |||
| } | |||
| void lvec_set_all (lvec_t *s, smpl_t val) { | |||
| uint_t j; | |||
| for (j=0; j< s->length; j++) { | |||
| s->data[j] = val; | |||
| } | |||
| } | |||
| void lvec_zeros(lvec_t *s) { | |||
| #if HAVE_MEMCPY_HACKS | |||
| memset(s->data, 0, s->length * sizeof(lsmp_t)); | |||
| #else | |||
| lvec_set_all (s, 0.); | |||
| #endif | |||
| } | |||
| void lvec_ones(lvec_t *s) { | |||
| lvec_set_all (s, 1.); | |||
| } | |||
| @@ -0,0 +1,118 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #ifndef AUBIO_LVEC_H | |||
| #define AUBIO_LVEC_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** \file | |||
| Vector of real-valued data in double precision | |||
| This file specifies the ::lvec_t buffer type, which is used in some places in | |||
| aubio to store a vector of ::lsmp_t. | |||
| Note: the lvec_t data type is required in some algorithms such as IIR filters | |||
| (see temporal/filter.h). | |||
| \example test-lvec.c | |||
| */ | |||
| /** Buffer for real data in double precision */ | |||
| typedef struct { | |||
| uint_t length; /**< length of buffer */ | |||
| lsmp_t *data; /**< data array of size [length] */ | |||
| } lvec_t; | |||
| /** lvec_t buffer creation function | |||
| \param length the length of the buffer to create | |||
| */ | |||
| lvec_t * new_lvec(uint_t length); | |||
| /** lvec_t buffer deletion function | |||
| \param s buffer to delete as returned by new_lvec() | |||
| */ | |||
| void del_lvec(lvec_t *s); | |||
| /** read sample value in a buffer | |||
| \param s vector to read from | |||
| \param position sample position to read from | |||
| */ | |||
| lsmp_t lvec_get_sample(lvec_t *s, uint_t position); | |||
| /** write sample value in a buffer | |||
| \param s vector to write to | |||
| \param data value to write in s->data[position] | |||
| \param position sample position to write to | |||
| */ | |||
| void lvec_set_sample(lvec_t *s, lsmp_t data, uint_t position); | |||
| /** read data from a buffer | |||
| \param s vector to read from | |||
| */ | |||
| lsmp_t * lvec_get_data(const lvec_t *s); | |||
| /** print out lvec data | |||
| \param s vector to print out | |||
| */ | |||
| void lvec_print(const lvec_t *s); | |||
| /** set all elements to a given value | |||
| \param s vector to modify | |||
| \param val value to set elements to | |||
| */ | |||
| void lvec_set_all(lvec_t *s, smpl_t val); | |||
| /** set all elements to zero | |||
| \param s vector to modify | |||
| */ | |||
| void lvec_zeros(lvec_t *s); | |||
| /** set all elements to ones | |||
| \param s vector to modify | |||
| */ | |||
| void lvec_ones(lvec_t *s); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_LVEC_H */ | |||
| @@ -0,0 +1,681 @@ | |||
| /* | |||
| Copyright (C) 2003-2014 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /* see in mathutils.h for doc */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "mathutils.h" | |||
| #include "musicutils.h" | |||
| /** Window types */ | |||
| typedef enum | |||
| { | |||
| aubio_win_ones, | |||
| aubio_win_rectangle, | |||
| aubio_win_hamming, | |||
| aubio_win_hanning, | |||
| aubio_win_hanningz, | |||
| aubio_win_blackman, | |||
| aubio_win_blackman_harris, | |||
| aubio_win_gaussian, | |||
| aubio_win_welch, | |||
| aubio_win_parzen, | |||
| aubio_win_default = aubio_win_hanningz, | |||
| } aubio_window_type; | |||
| fvec_t * | |||
| new_aubio_window (char_t * window_type, uint_t length) | |||
| { | |||
| fvec_t * win = new_fvec (length); | |||
| uint_t err; | |||
| if (win == NULL) { | |||
| return NULL; | |||
| } | |||
| err = fvec_set_window (win, window_type); | |||
| if (err != 0) { | |||
| del_fvec(win); | |||
| return NULL; | |||
| } | |||
| return win; | |||
| } | |||
| uint_t fvec_set_window (fvec_t *win, char_t *window_type) { | |||
| smpl_t * w = win->data; | |||
| uint_t i, size = win->length; | |||
| aubio_window_type wintype; | |||
| if (window_type == NULL) { | |||
| AUBIO_ERR ("window type can not be null.\n"); | |||
| return 1; | |||
| } else if (strcmp (window_type, "ones") == 0) | |||
| wintype = aubio_win_ones; | |||
| else if (strcmp (window_type, "rectangle") == 0) | |||
| wintype = aubio_win_rectangle; | |||
| else if (strcmp (window_type, "hamming") == 0) | |||
| wintype = aubio_win_hamming; | |||
| else if (strcmp (window_type, "hanning") == 0) | |||
| wintype = aubio_win_hanning; | |||
| else if (strcmp (window_type, "hanningz") == 0) | |||
| wintype = aubio_win_hanningz; | |||
| else if (strcmp (window_type, "blackman") == 0) | |||
| wintype = aubio_win_blackman; | |||
| else if (strcmp (window_type, "blackman_harris") == 0) | |||
| wintype = aubio_win_blackman_harris; | |||
| else if (strcmp (window_type, "gaussian") == 0) | |||
| wintype = aubio_win_gaussian; | |||
| else if (strcmp (window_type, "welch") == 0) | |||
| wintype = aubio_win_welch; | |||
| else if (strcmp (window_type, "parzen") == 0) | |||
| wintype = aubio_win_parzen; | |||
| else if (strcmp (window_type, "default") == 0) | |||
| wintype = aubio_win_default; | |||
| else { | |||
| AUBIO_ERR ("unknown window type `%s`.\n", window_type); | |||
| return 1; | |||
| } | |||
| switch(wintype) { | |||
| case aubio_win_ones: | |||
| fvec_ones(win); | |||
| break; | |||
| case aubio_win_rectangle: | |||
| fvec_set_all(win, .5); | |||
| break; | |||
| case aubio_win_hamming: | |||
| for (i=0;i<size;i++) | |||
| w[i] = 0.54 - 0.46 * COS(TWO_PI * i / (size)); | |||
| break; | |||
| case aubio_win_hanning: | |||
| for (i=0;i<size;i++) | |||
| w[i] = 0.5 - (0.5 * COS(TWO_PI * i / (size))); | |||
| break; | |||
| case aubio_win_hanningz: | |||
| for (i=0;i<size;i++) | |||
| w[i] = 0.5 * (1.0 - COS(TWO_PI * i / (size))); | |||
| break; | |||
| case aubio_win_blackman: | |||
| for (i=0;i<size;i++) | |||
| w[i] = 0.42 | |||
| - 0.50 * COS( TWO_PI*i/(size-1.0)) | |||
| + 0.08 * COS(2.0*TWO_PI*i/(size-1.0)); | |||
| break; | |||
| case aubio_win_blackman_harris: | |||
| for (i=0;i<size;i++) | |||
| w[i] = 0.35875 | |||
| - 0.48829 * COS( TWO_PI*i/(size-1.0)) | |||
| + 0.14128 * COS(2.0*TWO_PI*i/(size-1.0)) | |||
| - 0.01168 * COS(3.0*TWO_PI*i/(size-1.0)); | |||
| break; | |||
| case aubio_win_gaussian: | |||
| { | |||
| lsmp_t a, b, c = 0.5; | |||
| uint_t n; | |||
| for (n = 0; n < size; n++) | |||
| { | |||
| a = (n-c*(size-1))/(SQR(c)*(size-1)); | |||
| b = -c*SQR(a); | |||
| w[n] = EXP(b); | |||
| } | |||
| } | |||
| break; | |||
| case aubio_win_welch: | |||
| for (i=0;i<size;i++) | |||
| w[i] = 1.0 - SQR((2.*i-size)/(size+1.0)); | |||
| break; | |||
| case aubio_win_parzen: | |||
| for (i=0;i<size;i++) | |||
| w[i] = 1.0 - ABS((2.f*i-size)/(size+1.0f)); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| return 0; | |||
| } | |||
| smpl_t | |||
| aubio_unwrap2pi (smpl_t phase) | |||
| { | |||
| /* mod(phase+pi,-2pi)+pi */ | |||
| return phase + TWO_PI * (1. + FLOOR (-(phase + PI) / TWO_PI)); | |||
| } | |||
| smpl_t | |||
| fvec_mean (fvec_t * s) | |||
| { | |||
| smpl_t tmp = 0.0; | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsMean(s->data, (int)s->length, &tmp); | |||
| return tmp; | |||
| #elif defined(HAVE_ACCELERATE) | |||
| aubio_vDSP_meanv(s->data, 1, &tmp, s->length); | |||
| return tmp; | |||
| #else | |||
| uint_t j; | |||
| for (j = 0; j < s->length; j++) { | |||
| tmp += s->data[j]; | |||
| } | |||
| return tmp / (smpl_t)(s->length); | |||
| #endif | |||
| } | |||
| smpl_t | |||
| fvec_sum (fvec_t * s) | |||
| { | |||
| smpl_t tmp = 0.0; | |||
| #if defined(HAVE_INTEL_IPP) | |||
| aubio_ippsSum(s->data, (int)s->length, &tmp); | |||
| #elif defined(HAVE_ACCELERATE) | |||
| aubio_vDSP_sve(s->data, 1, &tmp, s->length); | |||
| #else | |||
| uint_t j; | |||
| for (j = 0; j < s->length; j++) { | |||
| tmp += s->data[j]; | |||
| } | |||
| #endif | |||
| return tmp; | |||
| } | |||
| smpl_t | |||
| fvec_max (fvec_t * s) | |||
| { | |||
| #if defined(HAVE_INTEL_IPP) | |||
| smpl_t tmp = 0.; | |||
| aubio_ippsMax( s->data, (int)s->length, &tmp); | |||
| #elif defined(HAVE_ACCELERATE) | |||
| smpl_t tmp = 0.; | |||
| aubio_vDSP_maxv( s->data, 1, &tmp, s->length ); | |||
| #else | |||
| uint_t j; | |||
| smpl_t tmp = s->data[0]; | |||
| for (j = 1; j < s->length; j++) { | |||
| tmp = (tmp > s->data[j]) ? tmp : s->data[j]; | |||
| } | |||
| #endif | |||
| return tmp; | |||
| } | |||
| smpl_t | |||
| fvec_min (fvec_t * s) | |||
| { | |||
| #if defined(HAVE_INTEL_IPP) | |||
| smpl_t tmp = 0.; | |||
| aubio_ippsMin(s->data, (int)s->length, &tmp); | |||
| #elif defined(HAVE_ACCELERATE) | |||
| smpl_t tmp = 0.; | |||
| aubio_vDSP_minv(s->data, 1, &tmp, s->length); | |||
| #else | |||
| uint_t j; | |||
| smpl_t tmp = s->data[0]; | |||
| for (j = 1; j < s->length; j++) { | |||
| tmp = (tmp < s->data[j]) ? tmp : s->data[j]; | |||
| } | |||
| #endif | |||
| return tmp; | |||
| } | |||
| uint_t | |||
| fvec_min_elem (fvec_t * s) | |||
| { | |||
| #ifndef HAVE_ACCELERATE | |||
| uint_t j, pos = 0.; | |||
| smpl_t tmp = s->data[0]; | |||
| for (j = 0; j < s->length; j++) { | |||
| pos = (tmp < s->data[j]) ? pos : j; | |||
| tmp = (tmp < s->data[j]) ? tmp : s->data[j]; | |||
| } | |||
| #else | |||
| smpl_t tmp = 0.; | |||
| vDSP_Length pos = 0; | |||
| aubio_vDSP_minvi(s->data, 1, &tmp, &pos, s->length); | |||
| #endif | |||
| return (uint_t)pos; | |||
| } | |||
| uint_t | |||
| fvec_max_elem (fvec_t * s) | |||
| { | |||
| #ifndef HAVE_ACCELERATE | |||
| uint_t j, pos = 0; | |||
| smpl_t tmp = 0.0; | |||
| for (j = 0; j < s->length; j++) { | |||
| pos = (tmp > s->data[j]) ? pos : j; | |||
| tmp = (tmp > s->data[j]) ? tmp : s->data[j]; | |||
| } | |||
| #else | |||
| smpl_t tmp = 0.; | |||
| vDSP_Length pos = 0; | |||
| aubio_vDSP_maxvi(s->data, 1, &tmp, &pos, s->length); | |||
| #endif | |||
| return (uint_t)pos; | |||
| } | |||
| void | |||
| fvec_shift (fvec_t * s) | |||
| { | |||
| uint_t half = s->length / 2, start = half, j; | |||
| // if length is odd, middle element is moved to the end | |||
| if (2 * half < s->length) start ++; | |||
| #ifndef HAVE_BLAS | |||
| for (j = 0; j < half; j++) { | |||
| ELEM_SWAP (s->data[j], s->data[j + start]); | |||
| } | |||
| #else | |||
| aubio_cblas_swap(half, s->data, 1, s->data + start, 1); | |||
| #endif | |||
| if (start != half) { | |||
| for (j = 0; j < half; j++) { | |||
| ELEM_SWAP (s->data[j + start - 1], s->data[j + start]); | |||
| } | |||
| } | |||
| } | |||
| void | |||
| fvec_ishift (fvec_t * s) | |||
| { | |||
| uint_t half = s->length / 2, start = half, j; | |||
| // if length is odd, middle element is moved to the beginning | |||
| if (2 * half < s->length) start ++; | |||
| #ifndef HAVE_BLAS | |||
| for (j = 0; j < half; j++) { | |||
| ELEM_SWAP (s->data[j], s->data[j + start]); | |||
| } | |||
| #else | |||
| aubio_cblas_swap(half, s->data, 1, s->data + start, 1); | |||
| #endif | |||
| if (start != half) { | |||
| for (j = 0; j < half; j++) { | |||
| ELEM_SWAP (s->data[half], s->data[j]); | |||
| } | |||
| } | |||
| } | |||
| void fvec_push(fvec_t *in, smpl_t new_elem) { | |||
| uint_t i; | |||
| for (i = 0; i < in->length - 1; i++) { | |||
| in->data[i] = in->data[i + 1]; | |||
| } | |||
| in->data[in->length - 1] = new_elem; | |||
| } | |||
| void fvec_clamp(fvec_t *in, smpl_t absmax) { | |||
| uint_t i; | |||
| for (i = 0; i < in->length; i++) { | |||
| if (in->data[i] > 0 && in->data[i] > ABS(absmax)) { | |||
| in->data[i] = absmax; | |||
| } else if (in->data[i] < 0 && in->data[i] < -ABS(absmax)) { | |||
| in->data[i] = -absmax; | |||
| } | |||
| } | |||
| } | |||
| smpl_t | |||
| aubio_level_lin (const fvec_t * f) | |||
| { | |||
| smpl_t energy = 0.; | |||
| #ifndef HAVE_BLAS | |||
| uint_t j; | |||
| for (j = 0; j < f->length; j++) { | |||
| energy += SQR (f->data[j]); | |||
| } | |||
| #else | |||
| energy = aubio_cblas_dot(f->length, f->data, 1, f->data, 1); | |||
| #endif | |||
| return energy / f->length; | |||
| } | |||
| smpl_t | |||
| fvec_local_hfc (fvec_t * v) | |||
| { | |||
| smpl_t hfc = 0.; | |||
| uint_t j; | |||
| for (j = 0; j < v->length; j++) { | |||
| hfc += (j + 1) * v->data[j]; | |||
| } | |||
| return hfc; | |||
| } | |||
| void | |||
| fvec_min_removal (fvec_t * v) | |||
| { | |||
| smpl_t v_min = fvec_min (v); | |||
| fvec_add (v, - v_min ); | |||
| } | |||
| smpl_t | |||
| fvec_alpha_norm (fvec_t * o, smpl_t alpha) | |||
| { | |||
| uint_t j; | |||
| smpl_t tmp = 0.; | |||
| for (j = 0; j < o->length; j++) { | |||
| tmp += POW (ABS (o->data[j]), alpha); | |||
| } | |||
| return POW (tmp / o->length, 1. / alpha); | |||
| } | |||
| void | |||
| fvec_alpha_normalise (fvec_t * o, smpl_t alpha) | |||
| { | |||
| uint_t j; | |||
| smpl_t norm = fvec_alpha_norm (o, alpha); | |||
| for (j = 0; j < o->length; j++) { | |||
| o->data[j] /= norm; | |||
| } | |||
| } | |||
| void | |||
| fvec_add (fvec_t * o, smpl_t val) | |||
| { | |||
| uint_t j; | |||
| for (j = 0; j < o->length; j++) { | |||
| o->data[j] += val; | |||
| } | |||
| } | |||
| void | |||
| fvec_mul (fvec_t *o, smpl_t val) | |||
| { | |||
| uint_t j; | |||
| for (j = 0; j < o->length; j++) { | |||
| o->data[j] *= val; | |||
| } | |||
| } | |||
| void fvec_adapt_thres(fvec_t * vec, fvec_t * tmp, | |||
| uint_t post, uint_t pre) { | |||
| uint_t length = vec->length, j; | |||
| for (j=0;j<length;j++) { | |||
| vec->data[j] -= fvec_moving_thres(vec, tmp, post, pre, j); | |||
| } | |||
| } | |||
| smpl_t | |||
| fvec_moving_thres (fvec_t * vec, fvec_t * tmpvec, | |||
| uint_t post, uint_t pre, uint_t pos) | |||
| { | |||
| uint_t k; | |||
| smpl_t *medar = (smpl_t *) tmpvec->data; | |||
| uint_t win_length = post + pre + 1; | |||
| uint_t length = vec->length; | |||
| /* post part of the buffer does not exist */ | |||
| if (pos < post + 1) { | |||
| for (k = 0; k < post + 1 - pos; k++) | |||
| medar[k] = 0.; /* 0-padding at the beginning */ | |||
| for (k = post + 1 - pos; k < win_length; k++) | |||
| medar[k] = vec->data[k + pos - post]; | |||
| /* the buffer is fully defined */ | |||
| } else if (pos + pre < length) { | |||
| for (k = 0; k < win_length; k++) | |||
| medar[k] = vec->data[k + pos - post]; | |||
| /* pre part of the buffer does not exist */ | |||
| } else { | |||
| for (k = 0; k < length - pos + post; k++) | |||
| medar[k] = vec->data[k + pos - post]; | |||
| for (k = length - pos + post; k < win_length; k++) | |||
| medar[k] = 0.; /* 0-padding at the end */ | |||
| } | |||
| return fvec_median (tmpvec); | |||
| } | |||
| smpl_t fvec_median (fvec_t * input) { | |||
| uint_t n = input->length; | |||
| smpl_t * arr = (smpl_t *) input->data; | |||
| uint_t low, high ; | |||
| uint_t median; | |||
| uint_t middle, ll, hh; | |||
| low = 0 ; high = n-1 ; median = (low + high) / 2; | |||
| for (;;) { | |||
| if (high <= low) /* One element only */ | |||
| return arr[median] ; | |||
| if (high == low + 1) { /* Two elements only */ | |||
| if (arr[low] > arr[high]) | |||
| ELEM_SWAP(arr[low], arr[high]) ; | |||
| return arr[median] ; | |||
| } | |||
| /* Find median of low, middle and high items; swap into position low */ | |||
| middle = (low + high) / 2; | |||
| if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]); | |||
| if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]); | |||
| if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; | |||
| /* Swap low item (now in position middle) into position (low+1) */ | |||
| ELEM_SWAP(arr[middle], arr[low+1]) ; | |||
| /* Nibble from each end towards middle, swapping items when stuck */ | |||
| ll = low + 1; | |||
| hh = high; | |||
| for (;;) { | |||
| do ll++; while (arr[low] > arr[ll]) ; | |||
| do hh--; while (arr[hh] > arr[low]) ; | |||
| if (hh < ll) | |||
| break; | |||
| ELEM_SWAP(arr[ll], arr[hh]) ; | |||
| } | |||
| /* Swap middle item (in position low) back into correct position */ | |||
| ELEM_SWAP(arr[low], arr[hh]) ; | |||
| /* Re-set active partition */ | |||
| if (hh <= median) | |||
| low = ll; | |||
| if (hh >= median) | |||
| high = hh - 1; | |||
| } | |||
| } | |||
| smpl_t fvec_quadratic_peak_pos (const fvec_t * x, uint_t pos) { | |||
| smpl_t s0, s1, s2; uint_t x0, x2; | |||
| smpl_t half = .5, two = 2.; | |||
| if (pos == 0 || pos == x->length - 1) return pos; | |||
| x0 = (pos < 1) ? pos : pos - 1; | |||
| x2 = (pos + 1 < x->length) ? pos + 1 : pos; | |||
| if (x0 == pos) return (x->data[pos] <= x->data[x2]) ? pos : x2; | |||
| if (x2 == pos) return (x->data[pos] <= x->data[x0]) ? pos : x0; | |||
| s0 = x->data[x0]; | |||
| s1 = x->data[pos]; | |||
| s2 = x->data[x2]; | |||
| return pos + half * (s0 - s2 ) / (s0 - two * s1 + s2); | |||
| } | |||
| smpl_t fvec_quadratic_peak_mag (fvec_t *x, smpl_t pos) { | |||
| smpl_t x0, x1, x2; | |||
| uint_t index = (uint_t)(pos - .5) + 1; | |||
| if (pos >= x->length || pos < 0.) return 0.; | |||
| if ((smpl_t)index == pos) return x->data[index]; | |||
| x0 = x->data[index - 1]; | |||
| x1 = x->data[index]; | |||
| x2 = x->data[index + 1]; | |||
| return x1 - .25 * (x0 - x2) * (pos - index); | |||
| } | |||
| uint_t fvec_peakpick(const fvec_t * onset, uint_t pos) { | |||
| uint_t tmp=0; | |||
| tmp = (onset->data[pos] > onset->data[pos-1] | |||
| && onset->data[pos] > onset->data[pos+1] | |||
| && onset->data[pos] > 0.); | |||
| return tmp; | |||
| } | |||
| smpl_t | |||
| aubio_quadfrac (smpl_t s0, smpl_t s1, smpl_t s2, smpl_t pf) | |||
| { | |||
| smpl_t tmp = | |||
| s0 + (pf / 2.) * (pf * (s0 - 2. * s1 + s2) - 3. * s0 + 4. * s1 - s2); | |||
| return tmp; | |||
| } | |||
| smpl_t | |||
| aubio_freqtomidi (smpl_t freq) | |||
| { | |||
| smpl_t midi; | |||
| if (freq < 2. || freq > 100000.) return 0.; // avoid nans and infs | |||
| /* log(freq/A-2)/log(2) */ | |||
| midi = freq / 6.875; | |||
| midi = LOG (midi) / 0.6931471805599453; | |||
| midi *= 12; | |||
| midi -= 3; | |||
| return midi; | |||
| } | |||
| smpl_t | |||
| aubio_miditofreq (smpl_t midi) | |||
| { | |||
| smpl_t freq; | |||
| if (midi > 140.) return 0.; // avoid infs | |||
| freq = (midi + 3.) / 12.; | |||
| freq = EXP (freq * 0.6931471805599453); | |||
| freq *= 6.875; | |||
| return freq; | |||
| } | |||
| smpl_t | |||
| aubio_bintofreq (smpl_t bin, smpl_t samplerate, smpl_t fftsize) | |||
| { | |||
| smpl_t freq = samplerate / fftsize; | |||
| return freq * MAX(bin, 0); | |||
| } | |||
| smpl_t | |||
| aubio_bintomidi (smpl_t bin, smpl_t samplerate, smpl_t fftsize) | |||
| { | |||
| smpl_t midi = aubio_bintofreq (bin, samplerate, fftsize); | |||
| return aubio_freqtomidi (midi); | |||
| } | |||
| smpl_t | |||
| aubio_freqtobin (smpl_t freq, smpl_t samplerate, smpl_t fftsize) | |||
| { | |||
| smpl_t bin = fftsize / samplerate; | |||
| return MAX(freq, 0) * bin; | |||
| } | |||
| smpl_t | |||
| aubio_miditobin (smpl_t midi, smpl_t samplerate, smpl_t fftsize) | |||
| { | |||
| smpl_t freq = aubio_miditofreq (midi); | |||
| return aubio_freqtobin (freq, samplerate, fftsize); | |||
| } | |||
| uint_t | |||
| aubio_is_power_of_two (uint_t a) | |||
| { | |||
| if ((a & (a - 1)) == 0) { | |||
| return 1; | |||
| } else { | |||
| return 0; | |||
| } | |||
| } | |||
| uint_t | |||
| aubio_next_power_of_two (uint_t a) | |||
| { | |||
| uint_t i = 1; | |||
| while (i < a) i <<= 1; | |||
| return i; | |||
| } | |||
| uint_t | |||
| aubio_power_of_two_order (uint_t a) | |||
| { | |||
| int order = 0; | |||
| int temp = aubio_next_power_of_two(a); | |||
| while (temp >>= 1) { | |||
| ++order; | |||
| } | |||
| return order; | |||
| } | |||
| smpl_t | |||
| aubio_db_spl (const fvec_t * o) | |||
| { | |||
| return 10. * LOG10 (aubio_level_lin (o)); | |||
| } | |||
| uint_t | |||
| aubio_silence_detection (const fvec_t * o, smpl_t threshold) | |||
| { | |||
| return (aubio_db_spl (o) < threshold); | |||
| } | |||
| smpl_t | |||
| aubio_level_detection (const fvec_t * o, smpl_t threshold) | |||
| { | |||
| smpl_t db_spl = aubio_db_spl (o); | |||
| if (db_spl < threshold) { | |||
| return 1.; | |||
| } else { | |||
| return db_spl; | |||
| } | |||
| } | |||
| smpl_t | |||
| aubio_zero_crossing_rate (fvec_t * input) | |||
| { | |||
| uint_t j; | |||
| uint_t zcr = 0; | |||
| for (j = 1; j < input->length; j++) { | |||
| // previous was strictly negative | |||
| if (input->data[j - 1] < 0.) { | |||
| // current is positive or null | |||
| if (input->data[j] >= 0.) { | |||
| zcr += 1; | |||
| } | |||
| // previous was positive or null | |||
| } else { | |||
| // current is strictly negative | |||
| if (input->data[j] < 0.) { | |||
| zcr += 1; | |||
| } | |||
| } | |||
| } | |||
| return zcr / (smpl_t) input->length; | |||
| } | |||
| void | |||
| aubio_autocorr (const fvec_t * input, fvec_t * output) | |||
| { | |||
| uint_t i, j, length = input->length; | |||
| smpl_t *data, *acf; | |||
| smpl_t tmp = 0; | |||
| data = input->data; | |||
| acf = output->data; | |||
| for (i = 0; i < length; i++) { | |||
| tmp = 0.; | |||
| for (j = i; j < length; j++) { | |||
| tmp += data[j - i] * data[j]; | |||
| } | |||
| acf[i] = tmp / (smpl_t) (length - i); | |||
| } | |||
| } | |||
| void | |||
| aubio_cleanup (void) | |||
| { | |||
| #ifdef HAVE_FFTW3F | |||
| fftwf_cleanup (); | |||
| #else | |||
| #ifdef HAVE_FFTW3 | |||
| fftw_cleanup (); | |||
| #endif | |||
| #endif | |||
| } | |||
| @@ -0,0 +1,338 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** \file | |||
| Various math functions | |||
| \example test-mathutils.c | |||
| \example test-mathutils-window.c | |||
| */ | |||
| #ifndef AUBIO_MATHUTILS_H | |||
| #define AUBIO_MATHUTILS_H | |||
| #include "fvec.h" | |||
| #include "musicutils.h" | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** compute the mean of a vector | |||
| \param s vector to compute mean from | |||
| \return the mean of `v` | |||
| */ | |||
| smpl_t fvec_mean (fvec_t * s); | |||
| /** find the max of a vector | |||
| \param s vector to get the max from | |||
| \return the value of the minimum of v | |||
| */ | |||
| smpl_t fvec_max (fvec_t * s); | |||
| /** find the min of a vector | |||
| \param s vector to get the min from | |||
| \return the value of the maximum of v | |||
| */ | |||
| smpl_t fvec_min (fvec_t * s); | |||
| /** find the index of the min of a vector | |||
| \param s vector to get the index from | |||
| \return the index of the minimum element of v | |||
| */ | |||
| uint_t fvec_min_elem (fvec_t * s); | |||
| /** find the index of the max of a vector | |||
| \param s vector to get the index from | |||
| \return the index of the maximum element of v | |||
| */ | |||
| uint_t fvec_max_elem (fvec_t * s); | |||
| /** swap the left and right halves of a vector | |||
| This function swaps the left part of the signal with the right part of the | |||
| signal. Therefore | |||
| \f$ a[0], a[1], ..., a[\frac{N}{2}], a[\frac{N}{2}+1], ..., a[N-1], a[N] \f$ | |||
| becomes | |||
| \f$ a[\frac{N}{2}+1], ..., a[N-1], a[N], a[0], a[1], ..., a[\frac{N}{2}] \f$ | |||
| This operation, known as 'fftshift' in the Matlab Signal Processing Toolbox, | |||
| can be used before computing the FFT to simplify the phase relationship of the | |||
| resulting spectrum. See Amalia de Götzen's paper referred to above. | |||
| */ | |||
| void fvec_shift (fvec_t * v); | |||
| /** swap the left and right halves of a vector | |||
| This function swaps the left part of the signal with the right part of the | |||
| signal. Therefore | |||
| \f$ a[0], a[1], ..., a[\frac{N}{2}], a[\frac{N}{2}+1], ..., a[N-1], a[N] \f$ | |||
| becomes | |||
| \f$ a[\frac{N}{2}+1], ..., a[N-1], a[N], a[0], a[1], ..., a[\frac{N}{2}] \f$ | |||
| This operation, known as 'ifftshift' in the Matlab Signal Processing Toolbox, | |||
| can be used after computing the inverse FFT to simplify the phase relationship | |||
| of the resulting spectrum. See Amalia de Götzen's paper referred to above. | |||
| */ | |||
| void fvec_ishift (fvec_t * v); | |||
| /** push a new element to the end of a vector, erasing the first element and | |||
| * sliding all others | |||
| \param in vector to push to | |||
| \param new_elem new_element to add at the end of the vector | |||
| In numpy words, this is equivalent to: in = np.concatenate([in, [new_elem]])[1:] | |||
| */ | |||
| void fvec_push(fvec_t *in, smpl_t new_elem); | |||
| /** compute the sum of all elements of a vector | |||
| \param v vector to compute the sum of | |||
| \return the sum of v | |||
| */ | |||
| smpl_t fvec_sum (fvec_t * v); | |||
| /** compute the High Frequency Content of a vector | |||
| The High Frequency Content is defined as \f$ \sum_0^{N-1} (k+1) v[k] \f$. | |||
| \param v vector to get the energy from | |||
| \return the HFC of v | |||
| */ | |||
| smpl_t fvec_local_hfc (fvec_t * v); | |||
| /** computes the p-norm of a vector | |||
| Computes the p-norm of a vector for \f$ p = \alpha \f$ | |||
| \f$ L^p = ||x||_p = (|x_1|^p + |x_2|^p + ... + |x_n|^p ) ^ \frac{1}{p} \f$ | |||
| If p = 1, the result is the Manhattan distance. | |||
| If p = 2, the result is the Euclidean distance. | |||
| As p tends towards large values, \f$ L^p \f$ tends towards the maximum of the | |||
| input vector. | |||
| References: | |||
| - <a href="http://en.wikipedia.org/wiki/Lp_space">\f$L^p\f$ space</a> on | |||
| Wikipedia | |||
| \param v vector to compute norm from | |||
| \param p order of the computed norm | |||
| \return the p-norm of v | |||
| */ | |||
| smpl_t fvec_alpha_norm (fvec_t * v, smpl_t p); | |||
| /** alpha normalisation | |||
| This function divides all elements of a vector by the p-norm as computed by | |||
| fvec_alpha_norm(). | |||
| \param v vector to compute norm from | |||
| \param p order of the computed norm | |||
| */ | |||
| void fvec_alpha_normalise (fvec_t * v, smpl_t p); | |||
| /** add a constant to each elements of a vector | |||
| \param v vector to add constant to | |||
| \param c constant to add to v | |||
| */ | |||
| void fvec_add (fvec_t * v, smpl_t c); | |||
| /** multiply each elements of a vector by a scalar | |||
| \param v vector to add constant to | |||
| \param s constant to scale v with | |||
| */ | |||
| void fvec_mul (fvec_t * v, smpl_t s); | |||
| /** remove the minimum value of the vector to each elements | |||
| \param v vector to remove minimum from | |||
| */ | |||
| void fvec_min_removal (fvec_t * v); | |||
| /** compute moving median threshold of a vector | |||
| This function computes the moving median threshold value of at the given | |||
| position of a vector, taking the median among post elements before and up to | |||
| pre elements after pos. | |||
| \param v input vector | |||
| \param tmp temporary vector of length post+1+pre | |||
| \param post length of causal part to take before pos | |||
| \param pre length of anti-causal part to take after pos | |||
| \param pos index to compute threshold for | |||
| \return moving median threshold value | |||
| */ | |||
| smpl_t fvec_moving_thres (fvec_t * v, fvec_t * tmp, uint_t post, uint_t pre, | |||
| uint_t pos); | |||
| /** apply adaptive threshold to a vector | |||
| For each points at position p of an input vector, this function remove the | |||
| moving median threshold computed at p. | |||
| \param v input vector | |||
| \param tmp temporary vector of length post+1+pre | |||
| \param post length of causal part to take before pos | |||
| \param pre length of anti-causal part to take after pos | |||
| */ | |||
| void fvec_adapt_thres (fvec_t * v, fvec_t * tmp, uint_t post, uint_t pre); | |||
| /** returns the median of a vector | |||
| The QuickSelect routine is based on the algorithm described in "Numerical | |||
| recipes in C", Second Edition, Cambridge University Press, 1992, Section 8.5, | |||
| ISBN 0-521-43108-5 | |||
| This implementation of the QuickSelect routine is based on Nicolas | |||
| Devillard's implementation, available at http://ndevilla.free.fr/median/median/ | |||
| and in the Public Domain. | |||
| \param v vector to get median from | |||
| \return the median of v | |||
| */ | |||
| smpl_t fvec_median (fvec_t * v); | |||
| /** finds exact peak index by quadratic interpolation | |||
| See [Quadratic Interpolation of Spectral | |||
| Peaks](https://ccrma.stanford.edu/~jos/sasp/Quadratic_Peak_Interpolation.html), | |||
| by Julius O. Smith III | |||
| \f$ p_{frac} = \frac{1}{2} \frac {x[p-1] - x[p+1]} {x[p-1] - 2 x[p] + x[p+1]} \in [ -.5, .5] \f$ | |||
| \param x vector to get the interpolated peak position from | |||
| \param p index of the peak in vector `x` | |||
| \return \f$ p + p_{frac} \f$ exact peak position of interpolated maximum or minimum | |||
| */ | |||
| smpl_t fvec_quadratic_peak_pos (const fvec_t * x, uint_t p); | |||
| /** finds magnitude of peak by quadratic interpolation | |||
| See [Quadratic Interpolation of Spectral | |||
| Peaks](https://ccrma.stanford.edu/~jos/sasp/Quadratic_Peak_Interpolation.html), | |||
| by Julius O. Smith III | |||
| \param x vector to get the magnitude of the interpolated peak position from | |||
| \param p index of the peak in vector `x` | |||
| \return magnitude of interpolated peak | |||
| */ | |||
| smpl_t fvec_quadratic_peak_mag (fvec_t * x, smpl_t p); | |||
| /** Quadratic interpolation using Lagrange polynomial. | |||
| Inspired from ``Comparison of interpolation algorithms in real-time sound | |||
| processing'', Vladimir Arnost, | |||
| \param s0,s1,s2 are 3 consecutive samples of a curve | |||
| \param pf is the floating point index [0;2] | |||
| \return \f$ s0 + (pf/2.)*((pf-3.)*s0-2.*(pf-2.)*s1+(pf-1.)*s2); \f$ | |||
| */ | |||
| smpl_t aubio_quadfrac (smpl_t s0, smpl_t s1, smpl_t s2, smpl_t pf); | |||
| /** return 1 if v[p] is a peak and positive, 0 otherwise | |||
| This function returns 1 if a peak is found at index p in the vector v. The | |||
| peak is defined as follows: | |||
| - v[p] is positive | |||
| - v[p-1] < v[p] | |||
| - v[p] > v[p+1] | |||
| \param v input vector | |||
| \param p position of supposed for peak | |||
| \return 1 if a peak is found, 0 otherwise | |||
| */ | |||
| uint_t fvec_peakpick (const fvec_t * v, uint_t p); | |||
| /** return 1 if a is a power of 2, 0 otherwise */ | |||
| uint_t aubio_is_power_of_two(uint_t a); | |||
| /** return the next power of power of 2 greater than a */ | |||
| uint_t aubio_next_power_of_two(uint_t a); | |||
| /** return the log2 factor of the given power of 2 value a */ | |||
| uint_t aubio_power_of_two_order(uint_t a); | |||
| /** compute normalised autocorrelation function | |||
| \param input vector to compute autocorrelation from | |||
| \param output vector to store autocorrelation function to | |||
| */ | |||
| void aubio_autocorr (const fvec_t * input, fvec_t * output); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_MATHUTILS_H */ | |||
| @@ -0,0 +1,270 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** @file | |||
| * various functions useful in audio signal processing | |||
| */ | |||
| #ifndef AUBIO_MUSICUTILS_H | |||
| #define AUBIO_MUSICUTILS_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** create window | |||
| \param window_type type of the window to create | |||
| \param size length of the window to create (see fvec_set_window()) | |||
| */ | |||
| fvec_t *new_aubio_window (char_t * window_type, uint_t size); | |||
| /** set elements of a vector to window coefficients | |||
| \param window exsting ::fvec_t to use | |||
| \param window_type type of the window to create | |||
| List of available window types: "rectangle", "hamming", "hanning", | |||
| "hanningz", "blackman", "blackman_harris", "gaussian", "welch", "parzen", | |||
| "default". | |||
| "default" is equivalent to "hanningz". | |||
| References: | |||
| - <a href="http://en.wikipedia.org/wiki/Window_function">Window | |||
| function</a> on Wikipedia | |||
| - Amalia de Götzen, Nicolas Bernardini, and Daniel Arfib. Traditional (?) | |||
| implementations of a phase vocoder: the tricks of the trade. In Proceedings of | |||
| the International Conference on Digital Audio Effects (DAFx-00), pages 37–44, | |||
| Uni- versity of Verona, Italy, 2000. | |||
| (<a href="http://www.cs.princeton.edu/courses/archive/spr09/cos325/Bernardini.pdf"> | |||
| pdf</a>) | |||
| */ | |||
| uint_t fvec_set_window (fvec_t * window, char_t * window_type); | |||
| /** compute the principal argument | |||
| This function maps the input phase to its corresponding value wrapped in the | |||
| range \f$ [-\pi, \pi] \f$. | |||
| \param phase unwrapped phase to map to the unit circle | |||
| \return equivalent phase wrapped to the unit circle | |||
| */ | |||
| smpl_t aubio_unwrap2pi (smpl_t phase); | |||
| /** convert frequency bin to midi value */ | |||
| smpl_t aubio_bintomidi (smpl_t bin, smpl_t samplerate, smpl_t fftsize); | |||
| /** convert midi value to frequency bin */ | |||
| smpl_t aubio_miditobin (smpl_t midi, smpl_t samplerate, smpl_t fftsize); | |||
| /** convert frequency bin to frequency (Hz) */ | |||
| smpl_t aubio_bintofreq (smpl_t bin, smpl_t samplerate, smpl_t fftsize); | |||
| /** convert frequency (Hz) to frequency bin */ | |||
| smpl_t aubio_freqtobin (smpl_t freq, smpl_t samplerate, smpl_t fftsize); | |||
| /** convert frequency (Hz) to mel | |||
| \param freq input frequency, in Hz | |||
| \return output mel | |||
| Converts a scalar from the frequency domain to the mel scale using Slaney | |||
| Auditory Toolbox's implementation: | |||
| If \f$ f < 1000 \f$, \f$ m = 3 f / 200 \f$. | |||
| If \f$ f >= 1000 \f$, \f$ m = 1000 + 27 \frac{{ln}(f) - ln(1000))} | |||
| {{ln}(6400) - ln(1000)} | |||
| \f$ | |||
| See also | |||
| -------- | |||
| aubio_meltohz(), aubio_hztomel_htk(). | |||
| */ | |||
| smpl_t aubio_hztomel (smpl_t freq); | |||
| /** convert mel to frequency (Hz) | |||
| \param mel input mel | |||
| \return output frequency, in Hz | |||
| Converts a scalar from the mel scale to the frequency domain using Slaney | |||
| Auditory Toolbox's implementation: | |||
| If \f$ f < 1000 \f$, \f$ f = 200 m/3 \f$. | |||
| If \f$ f \geq 1000 \f$, \f$ f = 1000 + \left(\frac{6400}{1000}\right) | |||
| ^{\frac{m - 1000}{27}} \f$ | |||
| See also | |||
| -------- | |||
| aubio_hztomel(), aubio_meltohz_htk(). | |||
| References | |||
| ---------- | |||
| Malcolm Slaney, *Auditory Toolbox Version 2, Technical Report #1998-010* | |||
| https://engineering.purdue.edu/~malcolm/interval/1998-010/ | |||
| */ | |||
| smpl_t aubio_meltohz (smpl_t mel); | |||
| /** convert frequency (Hz) to mel | |||
| \param freq input frequency, in Hz | |||
| \return output mel | |||
| Converts a scalar from the frequency domain to the mel scale, using the | |||
| equation defined by O'Shaughnessy, as implemented in the HTK speech | |||
| recognition toolkit: | |||
| \f$ m = 1127 + ln(1 + \frac{f}{700}) \f$ | |||
| See also | |||
| -------- | |||
| aubio_meltohz_htk(), aubio_hztomel(). | |||
| References | |||
| ---------- | |||
| Douglas O'Shaughnessy (1987). *Speech communication: human and machine*. | |||
| Addison-Wesley. p. 150. ISBN 978-0-201-16520-3. | |||
| HTK Speech Recognition Toolkit: http://htk.eng.cam.ac.uk/ | |||
| */ | |||
| smpl_t aubio_hztomel_htk (smpl_t freq); | |||
| /** convert mel to frequency (Hz) | |||
| \param mel input mel | |||
| \return output frequency, in Hz | |||
| Converts a scalar from the mel scale to the frequency domain, using the | |||
| equation defined by O'Shaughnessy, as implemented in the HTK speech | |||
| recognition toolkit: | |||
| \f$ f = 700 * {e}^\left(\frac{f}{1127} - 1\right) \f$ | |||
| See also | |||
| -------- | |||
| aubio_hztomel_htk(), aubio_meltohz(). | |||
| */ | |||
| smpl_t aubio_meltohz_htk (smpl_t mel); | |||
| /** convert frequency (Hz) to midi value (0-128) */ | |||
| smpl_t aubio_freqtomidi (smpl_t freq); | |||
| /** convert midi value (0-128) to frequency (Hz) */ | |||
| smpl_t aubio_miditofreq (smpl_t midi); | |||
| /** clean up cached memory at the end of program | |||
| This function should be used at the end of programs to purge all cached | |||
| memory. So far it is only useful to clean FFTW's cache. | |||
| */ | |||
| void aubio_cleanup (void); | |||
| /** zero-crossing rate (ZCR) | |||
| The zero-crossing rate is the number of times a signal changes sign, | |||
| divided by the length of this signal. | |||
| \param v vector to compute ZCR from | |||
| \return zero-crossing rate of v | |||
| */ | |||
| smpl_t aubio_zero_crossing_rate (fvec_t * v); | |||
| /** compute sound level on a linear scale | |||
| This gives the average of the square amplitudes. | |||
| \param v vector to compute level from | |||
| \return level of v | |||
| */ | |||
| smpl_t aubio_level_lin (const fvec_t * v); | |||
| /** compute sound pressure level (SPL) in dB | |||
| This quantity is often wrongly called 'loudness'. | |||
| This gives ten times the log10 of the average of the square amplitudes. | |||
| \param v vector to compute dB SPL from | |||
| \return level of v in dB SPL | |||
| */ | |||
| smpl_t aubio_db_spl (const fvec_t * v); | |||
| /** check if buffer level in dB SPL is under a given threshold | |||
| \param v vector to get level from | |||
| \param threshold threshold in dB SPL | |||
| \return 1 if level is under the given threshold, 0 otherwise | |||
| */ | |||
| uint_t aubio_silence_detection (const fvec_t * v, smpl_t threshold); | |||
| /** get buffer level if level >= threshold, 1. otherwise | |||
| \param v vector to get level from | |||
| \param threshold threshold in dB SPL | |||
| \return level in dB SPL if level >= threshold, 1. otherwise | |||
| */ | |||
| smpl_t aubio_level_detection (const fvec_t * v, smpl_t threshold); | |||
| /** clamp the values of a vector within the range [-abs(max), abs(max)] | |||
| \param in vector to clamp | |||
| \param absmax maximum value over which input vector elements should be clamped | |||
| */ | |||
| void fvec_clamp(fvec_t *in, smpl_t absmax); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_MUSICUTILS_H */ | |||
| @@ -0,0 +1,530 @@ | |||
| /* | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "cvec.h" | |||
| #include "lvec.h" | |||
| #include "mathutils.h" | |||
| #include "musicutils.h" | |||
| #include "spectral/phasevoc.h" | |||
| #include "temporal/filter.h" | |||
| #include "temporal/c_weighting.h" | |||
| #include "pitch/pitchmcomb.h" | |||
| #include "pitch/pitchyin.h" | |||
| #include "pitch/pitchfcomb.h" | |||
| #include "pitch/pitchschmitt.h" | |||
| #include "pitch/pitchyinfft.h" | |||
| #include "pitch/pitchyinfast.h" | |||
| #include "pitch/pitchspecacf.h" | |||
| #include "pitch/pitch.h" | |||
| #define DEFAULT_PITCH_SILENCE -50. | |||
| /** pitch detection algorithms */ | |||
| typedef enum | |||
| { | |||
| aubio_pitcht_yin, /**< `yin`, YIN algorithm */ | |||
| aubio_pitcht_mcomb, /**< `mcomb`, Multi-comb filter */ | |||
| aubio_pitcht_schmitt, /**< `schmitt`, Schmitt trigger */ | |||
| aubio_pitcht_fcomb, /**< `fcomb`, Fast comb filter */ | |||
| aubio_pitcht_yinfft, /**< `yinfft`, Spectral YIN */ | |||
| aubio_pitcht_yinfast, /**< `yinfast`, YIN fast */ | |||
| aubio_pitcht_specacf, /**< `specacf`, Spectral autocorrelation */ | |||
| aubio_pitcht_default | |||
| = aubio_pitcht_yinfft, /**< `default` */ | |||
| } aubio_pitch_type; | |||
| /** pitch detection output modes */ | |||
| typedef enum | |||
| { | |||
| aubio_pitchm_freq, /**< Frequency (Hz) */ | |||
| aubio_pitchm_midi, /**< MIDI note (0.,127) */ | |||
| aubio_pitchm_cent, /**< Cent */ | |||
| aubio_pitchm_bin, /**< Frequency bin (0,bufsize) */ | |||
| aubio_pitchm_default = aubio_pitchm_freq, /**< the one used when "default" is asked */ | |||
| } aubio_pitch_mode; | |||
| /** callback to get pitch candidate, defined below */ | |||
| typedef void (*aubio_pitch_detect_t) (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
| /** callback to convert pitch from one unit to another, defined below */ | |||
| typedef smpl_t(*aubio_pitch_convert_t) (smpl_t value, uint_t samplerate, uint_t bufsize); | |||
| /** callback to fetch the confidence of the algorithm */ | |||
| typedef smpl_t (*aubio_pitch_get_conf_t) (void * p); | |||
| /** generic pitch detection structure */ | |||
| struct _aubio_pitch_t | |||
| { | |||
| aubio_pitch_type type; /**< pitch detection mode */ | |||
| aubio_pitch_mode mode; /**< pitch detection output mode */ | |||
| uint_t samplerate; /**< samplerate */ | |||
| uint_t bufsize; /**< buffer size */ | |||
| void *p_object; /**< pointer to pitch object */ | |||
| aubio_filter_t *filter; /**< filter */ | |||
| fvec_t *filtered; /**< filtered input */ | |||
| aubio_pvoc_t *pv; /**< phase vocoder for mcomb */ | |||
| cvec_t *fftgrain; /**< spectral frame for mcomb */ | |||
| fvec_t *buf; /**< temporary buffer for yin */ | |||
| aubio_pitch_detect_t detect_cb; /**< callback to get the pitch candidates */ | |||
| aubio_pitch_convert_t conv_cb; /**< callback to convert it to the desired unit */ | |||
| aubio_pitch_get_conf_t conf_cb; /**< pointer to the current confidence callback */ | |||
| smpl_t silence; /**< silence threshold */ | |||
| }; | |||
| /* callback functions for pitch detection */ | |||
| static void aubio_pitch_do_mcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
| static void aubio_pitch_do_yin (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
| static void aubio_pitch_do_schmitt (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
| static void aubio_pitch_do_fcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
| static void aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
| static void aubio_pitch_do_yinfast (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
| static void aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
| /* internal functions for frequency conversion */ | |||
| static smpl_t freqconvbin (smpl_t f, uint_t samplerate, uint_t bufsize); | |||
| static smpl_t freqconvmidi (smpl_t f, uint_t samplerate, uint_t bufsize); | |||
| static smpl_t freqconvpass (smpl_t f, uint_t samplerate, uint_t bufsize); | |||
| /* adapter to stack ibuf new samples at the end of buf, and trim `buf` to `bufsize` */ | |||
| void aubio_pitch_slideblock (aubio_pitch_t * p, const fvec_t * ibuf); | |||
| aubio_pitch_t * | |||
| new_aubio_pitch (const char_t * pitch_mode, | |||
| uint_t bufsize, uint_t hopsize, uint_t samplerate) | |||
| { | |||
| aubio_pitch_t *p = AUBIO_NEW (aubio_pitch_t); | |||
| aubio_pitch_type pitch_type; | |||
| if (pitch_mode == NULL) { | |||
| AUBIO_ERR ("pitch: can not use ‘NULL‘ for pitch detection method\n"); | |||
| goto beach; | |||
| } | |||
| if (strcmp (pitch_mode, "mcomb") == 0) | |||
| pitch_type = aubio_pitcht_mcomb; | |||
| else if (strcmp (pitch_mode, "yinfast") == 0) | |||
| pitch_type = aubio_pitcht_yinfast; | |||
| else if (strcmp (pitch_mode, "yinfft") == 0) | |||
| pitch_type = aubio_pitcht_yinfft; | |||
| else if (strcmp (pitch_mode, "yin") == 0) | |||
| pitch_type = aubio_pitcht_yin; | |||
| else if (strcmp (pitch_mode, "schmitt") == 0) | |||
| pitch_type = aubio_pitcht_schmitt; | |||
| else if (strcmp (pitch_mode, "fcomb") == 0) | |||
| pitch_type = aubio_pitcht_fcomb; | |||
| else if (strcmp (pitch_mode, "specacf") == 0) | |||
| pitch_type = aubio_pitcht_specacf; | |||
| else if (strcmp (pitch_mode, "default") == 0) | |||
| pitch_type = aubio_pitcht_default; | |||
| else { | |||
| AUBIO_ERR ("pitch: unknown pitch detection method ‘%s’\n", pitch_mode); | |||
| goto beach; | |||
| } | |||
| // check parameters are valid | |||
| if ((sint_t)hopsize < 1) { | |||
| AUBIO_ERR("pitch: got hopsize %d, but can not be < 1\n", hopsize); | |||
| goto beach; | |||
| } else if ((sint_t)bufsize < 1) { | |||
| AUBIO_ERR("pitch: got buffer_size %d, but can not be < 1\n", bufsize); | |||
| goto beach; | |||
| } else if (bufsize < hopsize) { | |||
| AUBIO_ERR("pitch: hop size (%d) is larger than win size (%d)\n", hopsize, bufsize); | |||
| goto beach; | |||
| } else if ((sint_t)samplerate < 1) { | |||
| AUBIO_ERR("pitch: samplerate (%d) can not be < 1\n", samplerate); | |||
| goto beach; | |||
| } | |||
| p->samplerate = samplerate; | |||
| p->type = pitch_type; | |||
| aubio_pitch_set_unit (p, "default"); | |||
| p->bufsize = bufsize; | |||
| p->silence = DEFAULT_PITCH_SILENCE; | |||
| p->conf_cb = NULL; | |||
| switch (p->type) { | |||
| case aubio_pitcht_yin: | |||
| p->buf = new_fvec (bufsize); | |||
| p->p_object = new_aubio_pitchyin (bufsize); | |||
| if (!p->p_object) goto beach; | |||
| p->detect_cb = aubio_pitch_do_yin; | |||
| p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyin_get_confidence; | |||
| aubio_pitchyin_set_tolerance (p->p_object, 0.15); | |||
| break; | |||
| case aubio_pitcht_mcomb: | |||
| p->filtered = new_fvec (hopsize); | |||
| p->pv = new_aubio_pvoc (bufsize, hopsize); | |||
| if (!p->pv) goto beach; | |||
| p->fftgrain = new_cvec (bufsize); | |||
| p->p_object = new_aubio_pitchmcomb (bufsize, hopsize); | |||
| p->filter = new_aubio_filter_c_weighting (samplerate); | |||
| p->detect_cb = aubio_pitch_do_mcomb; | |||
| break; | |||
| case aubio_pitcht_fcomb: | |||
| p->buf = new_fvec (bufsize); | |||
| p->p_object = new_aubio_pitchfcomb (bufsize, hopsize); | |||
| if (!p->p_object) goto beach; | |||
| p->detect_cb = aubio_pitch_do_fcomb; | |||
| break; | |||
| case aubio_pitcht_schmitt: | |||
| p->buf = new_fvec (bufsize); | |||
| p->p_object = new_aubio_pitchschmitt (bufsize); | |||
| p->detect_cb = aubio_pitch_do_schmitt; | |||
| break; | |||
| case aubio_pitcht_yinfft: | |||
| p->buf = new_fvec (bufsize); | |||
| p->p_object = new_aubio_pitchyinfft (samplerate, bufsize); | |||
| if (!p->p_object) goto beach; | |||
| p->detect_cb = aubio_pitch_do_yinfft; | |||
| p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyinfft_get_confidence; | |||
| aubio_pitchyinfft_set_tolerance (p->p_object, 0.85); | |||
| break; | |||
| case aubio_pitcht_yinfast: | |||
| p->buf = new_fvec (bufsize); | |||
| p->p_object = new_aubio_pitchyinfast (bufsize); | |||
| if (!p->p_object) goto beach; | |||
| p->detect_cb = aubio_pitch_do_yinfast; | |||
| p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyinfast_get_confidence; | |||
| aubio_pitchyinfast_set_tolerance (p->p_object, 0.15); | |||
| break; | |||
| case aubio_pitcht_specacf: | |||
| p->buf = new_fvec (bufsize); | |||
| p->p_object = new_aubio_pitchspecacf (bufsize); | |||
| if (!p->p_object) goto beach; | |||
| p->detect_cb = aubio_pitch_do_specacf; | |||
| p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchspecacf_get_tolerance; | |||
| aubio_pitchspecacf_set_tolerance (p->p_object, 0.85); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| return p; | |||
| beach: | |||
| if (p->filtered) del_fvec(p->filtered); | |||
| if (p->buf) del_fvec(p->buf); | |||
| AUBIO_FREE(p); | |||
| return NULL; | |||
| } | |||
| void | |||
| del_aubio_pitch (aubio_pitch_t * p) | |||
| { | |||
| switch (p->type) { | |||
| case aubio_pitcht_yin: | |||
| del_fvec (p->buf); | |||
| del_aubio_pitchyin (p->p_object); | |||
| break; | |||
| case aubio_pitcht_mcomb: | |||
| del_fvec (p->filtered); | |||
| del_aubio_pvoc (p->pv); | |||
| del_cvec (p->fftgrain); | |||
| del_aubio_filter (p->filter); | |||
| del_aubio_pitchmcomb (p->p_object); | |||
| break; | |||
| case aubio_pitcht_schmitt: | |||
| del_fvec (p->buf); | |||
| del_aubio_pitchschmitt (p->p_object); | |||
| break; | |||
| case aubio_pitcht_fcomb: | |||
| del_fvec (p->buf); | |||
| del_aubio_pitchfcomb (p->p_object); | |||
| break; | |||
| case aubio_pitcht_yinfft: | |||
| del_fvec (p->buf); | |||
| del_aubio_pitchyinfft (p->p_object); | |||
| break; | |||
| case aubio_pitcht_yinfast: | |||
| del_fvec (p->buf); | |||
| del_aubio_pitchyinfast (p->p_object); | |||
| break; | |||
| case aubio_pitcht_specacf: | |||
| del_fvec (p->buf); | |||
| del_aubio_pitchspecacf (p->p_object); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| AUBIO_FREE (p); | |||
| } | |||
| void | |||
| aubio_pitch_slideblock (aubio_pitch_t * p, const fvec_t * ibuf) | |||
| { | |||
| uint_t overlap_size = p->buf->length - ibuf->length; | |||
| #if 1 //!HAVE_MEMCPY_HACKS | |||
| uint_t j; | |||
| for (j = 0; j < overlap_size; j++) { | |||
| p->buf->data[j] = p->buf->data[j + ibuf->length]; | |||
| } | |||
| for (j = 0; j < ibuf->length; j++) { | |||
| p->buf->data[j + overlap_size] = ibuf->data[j]; | |||
| } | |||
| #else | |||
| smpl_t *data = p->buf->data; | |||
| smpl_t *newdata = ibuf->data; | |||
| memmove(data, data + ibuf->length, overlap_size); | |||
| memcpy(data + overlap_size, newdata, ibuf->length); | |||
| #endif | |||
| } | |||
| uint_t | |||
| aubio_pitch_set_unit (aubio_pitch_t * p, const char_t * pitch_unit) | |||
| { | |||
| uint_t err = AUBIO_OK; | |||
| aubio_pitch_mode pitch_mode; | |||
| if (strcmp (pitch_unit, "freq") == 0) | |||
| pitch_mode = aubio_pitchm_freq; | |||
| else if (strcmp (pitch_unit, "hertz") == 0) | |||
| pitch_mode = aubio_pitchm_freq; | |||
| else if (strcmp (pitch_unit, "Hertz") == 0) | |||
| pitch_mode = aubio_pitchm_freq; | |||
| else if (strcmp (pitch_unit, "Hz") == 0) | |||
| pitch_mode = aubio_pitchm_freq; | |||
| else if (strcmp (pitch_unit, "f0") == 0) | |||
| pitch_mode = aubio_pitchm_freq; | |||
| else if (strcmp (pitch_unit, "midi") == 0) | |||
| pitch_mode = aubio_pitchm_midi; | |||
| else if (strcmp (pitch_unit, "cent") == 0) | |||
| pitch_mode = aubio_pitchm_cent; | |||
| else if (strcmp (pitch_unit, "bin") == 0) | |||
| pitch_mode = aubio_pitchm_bin; | |||
| else if (strcmp (pitch_unit, "default") == 0) | |||
| pitch_mode = aubio_pitchm_default; | |||
| else { | |||
| AUBIO_WRN("pitch: unknown pitch detection unit ‘%s’, using default\n", | |||
| pitch_unit); | |||
| pitch_mode = aubio_pitchm_default; | |||
| err = AUBIO_FAIL; | |||
| } | |||
| p->mode = pitch_mode; | |||
| switch (p->mode) { | |||
| case aubio_pitchm_freq: | |||
| p->conv_cb = freqconvpass; | |||
| break; | |||
| case aubio_pitchm_midi: | |||
| p->conv_cb = freqconvmidi; | |||
| break; | |||
| case aubio_pitchm_cent: | |||
| /* bug: not implemented */ | |||
| p->conv_cb = freqconvmidi; | |||
| break; | |||
| case aubio_pitchm_bin: | |||
| p->conv_cb = freqconvbin; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| return err; | |||
| } | |||
| uint_t | |||
| aubio_pitch_set_tolerance (aubio_pitch_t * p, smpl_t tol) | |||
| { | |||
| switch (p->type) { | |||
| case aubio_pitcht_yin: | |||
| aubio_pitchyin_set_tolerance (p->p_object, tol); | |||
| break; | |||
| case aubio_pitcht_yinfft: | |||
| aubio_pitchyinfft_set_tolerance (p->p_object, tol); | |||
| break; | |||
| case aubio_pitcht_yinfast: | |||
| aubio_pitchyinfast_set_tolerance (p->p_object, tol); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| return AUBIO_OK; | |||
| } | |||
| smpl_t | |||
| aubio_pitch_get_tolerance (aubio_pitch_t * p) | |||
| { | |||
| smpl_t tolerance = 1.; | |||
| switch (p->type) { | |||
| case aubio_pitcht_yin: | |||
| tolerance = aubio_pitchyin_get_tolerance (p->p_object); | |||
| break; | |||
| case aubio_pitcht_yinfft: | |||
| tolerance = aubio_pitchyinfft_get_tolerance (p->p_object); | |||
| break; | |||
| case aubio_pitcht_yinfast: | |||
| tolerance = aubio_pitchyinfast_get_tolerance (p->p_object); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| return tolerance; | |||
| } | |||
| uint_t | |||
| aubio_pitch_set_silence (aubio_pitch_t * p, smpl_t silence) | |||
| { | |||
| if (silence <= 0 && silence >= -200) { | |||
| p->silence = silence; | |||
| return AUBIO_OK; | |||
| } else { | |||
| AUBIO_WRN("pitch: could not set silence to %.2f\n", silence); | |||
| return AUBIO_FAIL; | |||
| } | |||
| } | |||
| smpl_t | |||
| aubio_pitch_get_silence (aubio_pitch_t * p) | |||
| { | |||
| return p->silence; | |||
| } | |||
| /* do method, calling the detection callback, then the conversion callback */ | |||
| void | |||
| aubio_pitch_do (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf) | |||
| { | |||
| p->detect_cb (p, ibuf, obuf); | |||
| if (aubio_silence_detection(ibuf, p->silence) == 1) { | |||
| obuf->data[0] = 0.; | |||
| } | |||
| obuf->data[0] = p->conv_cb (obuf->data[0], p->samplerate, p->bufsize); | |||
| } | |||
| /* do method for each algorithm */ | |||
| void | |||
| aubio_pitch_do_mcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf) | |||
| { | |||
| aubio_filter_do_outplace (p->filter, ibuf, p->filtered); | |||
| aubio_pvoc_do (p->pv, ibuf, p->fftgrain); | |||
| aubio_pitchmcomb_do (p->p_object, p->fftgrain, obuf); | |||
| obuf->data[0] = aubio_bintofreq (obuf->data[0], p->samplerate, p->bufsize); | |||
| } | |||
| void | |||
| aubio_pitch_do_yin (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf) | |||
| { | |||
| smpl_t pitch = 0.; | |||
| aubio_pitch_slideblock (p, ibuf); | |||
| aubio_pitchyin_do (p->p_object, p->buf, obuf); | |||
| pitch = obuf->data[0]; | |||
| if (pitch > 0) { | |||
| pitch = p->samplerate / (pitch + 0.); | |||
| } else { | |||
| pitch = 0.; | |||
| } | |||
| obuf->data[0] = pitch; | |||
| } | |||
| void | |||
| aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf) | |||
| { | |||
| smpl_t pitch = 0.; | |||
| aubio_pitch_slideblock (p, ibuf); | |||
| aubio_pitchyinfft_do (p->p_object, p->buf, obuf); | |||
| pitch = obuf->data[0]; | |||
| if (pitch > 0) { | |||
| pitch = p->samplerate / (pitch + 0.); | |||
| } else { | |||
| pitch = 0.; | |||
| } | |||
| obuf->data[0] = pitch; | |||
| } | |||
| void | |||
| aubio_pitch_do_yinfast (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf) | |||
| { | |||
| smpl_t pitch = 0.; | |||
| aubio_pitch_slideblock (p, ibuf); | |||
| aubio_pitchyinfast_do (p->p_object, p->buf, obuf); | |||
| pitch = obuf->data[0]; | |||
| if (pitch > 0) { | |||
| pitch = p->samplerate / (pitch + 0.); | |||
| } else { | |||
| pitch = 0.; | |||
| } | |||
| obuf->data[0] = pitch; | |||
| } | |||
| void | |||
| aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out) | |||
| { | |||
| smpl_t pitch = 0., period; | |||
| aubio_pitch_slideblock (p, ibuf); | |||
| aubio_pitchspecacf_do (p->p_object, p->buf, out); | |||
| //out->data[0] = aubio_bintofreq (out->data[0], p->samplerate, p->bufsize); | |||
| period = out->data[0]; | |||
| if (period > 0) { | |||
| pitch = p->samplerate / period; | |||
| } else { | |||
| pitch = 0.; | |||
| } | |||
| out->data[0] = pitch; | |||
| } | |||
| void | |||
| aubio_pitch_do_fcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out) | |||
| { | |||
| aubio_pitch_slideblock (p, ibuf); | |||
| aubio_pitchfcomb_do (p->p_object, p->buf, out); | |||
| out->data[0] = aubio_bintofreq (out->data[0], p->samplerate, p->bufsize); | |||
| } | |||
| void | |||
| aubio_pitch_do_schmitt (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out) | |||
| { | |||
| smpl_t period, pitch = 0.; | |||
| aubio_pitch_slideblock (p, ibuf); | |||
| aubio_pitchschmitt_do (p->p_object, p->buf, out); | |||
| period = out->data[0]; | |||
| if (period > 0) { | |||
| pitch = p->samplerate / period; | |||
| } else { | |||
| pitch = 0.; | |||
| } | |||
| out->data[0] = pitch; | |||
| } | |||
| /* conversion callbacks */ | |||
| smpl_t | |||
| freqconvbin(smpl_t f, uint_t samplerate, uint_t bufsize) | |||
| { | |||
| return aubio_freqtobin(f, samplerate, bufsize); | |||
| } | |||
| smpl_t | |||
| freqconvmidi (smpl_t f, uint_t samplerate UNUSED, uint_t bufsize UNUSED) | |||
| { | |||
| return aubio_freqtomidi (f); | |||
| } | |||
| smpl_t | |||
| freqconvpass (smpl_t f, uint_t samplerate UNUSED, uint_t bufsize UNUSED) | |||
| { | |||
| return f; | |||
| } | |||
| /* confidence callbacks */ | |||
| smpl_t | |||
| aubio_pitch_get_confidence (aubio_pitch_t * p) | |||
| { | |||
| if (p->conf_cb) { | |||
| return p->conf_cb(p->p_object); | |||
| } | |||
| return 0.; | |||
| } | |||
| @@ -0,0 +1,197 @@ | |||
| /* | |||
| Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #ifndef AUBIO_PITCH_H | |||
| #define AUBIO_PITCH_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** \file | |||
| Pitch detection object | |||
| This file creates the objects required for the computation of the selected | |||
| pitch detection algorithm and output the results, in midi note or Hz. | |||
| \section pitch Pitch detection methods | |||
| A list of the pitch detection methods currently available follows. | |||
| \b \p default : use the default method | |||
| Currently, the default method is set to \p yinfft . | |||
| \b \p schmitt : Schmitt trigger | |||
| This pitch extraction method implements a Schmitt trigger to estimate the | |||
| period of a signal. | |||
| This file was derived from the tuneit project, written by Mario Lang to | |||
| detect the fundamental frequency of a sound. | |||
| See http://delysid.org/tuneit.html | |||
| \b \p fcomb : a fast harmonic comb filter | |||
| This pitch extraction method implements a fast harmonic comb filter to | |||
| determine the fundamental frequency of a harmonic sound. | |||
| This file was derived from the tuneit project, written by Mario Lang to | |||
| detect the fundamental frequency of a sound. | |||
| See http://delysid.org/tuneit.html | |||
| \b \p mcomb : multiple-comb filter | |||
| This fundamental frequency estimation algorithm implements spectral | |||
| flattening, multi-comb filtering and peak histogramming. | |||
| This method was designed by Juan P. Bello and described in: | |||
| Juan-Pablo Bello. ``Towards the Automated Analysis of Simple Polyphonic | |||
| Music''. PhD thesis, Centre for Digital Music, Queen Mary University of | |||
| London, London, UK, 2003. | |||
| \b \p yin : YIN algorithm | |||
| This algorithm was developed by A. de Cheveigne and H. Kawahara and | |||
| published in: | |||
| De Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency | |||
| estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930. | |||
| see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html | |||
| \b \p yinfast : Yinfast algorithm | |||
| This algorithm is equivalent to the YIN algorithm, but computed in the | |||
| spectral domain for efficiency. See also `python/demos/demo_yin_compare.py`. | |||
| \b \p yinfft : Yinfft algorithm | |||
| This algorithm was derived from the YIN algorithm. In this implementation, a | |||
| Fourier transform is used to compute a tapered square difference function, | |||
| which allows spectral weighting. Because the difference function is tapered, | |||
| the selection of the period is simplified. | |||
| Paul Brossier, [Automatic annotation of musical audio for interactive | |||
| systems](http://aubio.org/phd/), Chapter 3, Pitch Analysis, PhD thesis, | |||
| Centre for Digital music, Queen Mary University of London, London, UK, 2006. | |||
| \example pitch/test-pitch.c | |||
| \example examples/aubiopitch.c | |||
| */ | |||
| /** pitch detection object */ | |||
| typedef struct _aubio_pitch_t aubio_pitch_t; | |||
| /** execute pitch detection on an input signal frame | |||
| \param o pitch detection object as returned by new_aubio_pitch() | |||
| \param in input signal of size [hop_size] | |||
| \param out output pitch candidates of size [1] | |||
| */ | |||
| void aubio_pitch_do (aubio_pitch_t * o, const fvec_t * in, fvec_t * out); | |||
| /** change yin or yinfft tolerance threshold | |||
| \param o pitch detection object as returned by new_aubio_pitch() | |||
| \param tol tolerance default is 0.15 for yin and 0.85 for yinfft | |||
| */ | |||
| uint_t aubio_pitch_set_tolerance (aubio_pitch_t * o, smpl_t tol); | |||
| /** get yin or yinfft tolerance threshold | |||
| \param o pitch detection object as returned by new_aubio_pitch() | |||
| \return tolerance (default is 0.15 for yin and 0.85 for yinfft) | |||
| */ | |||
| smpl_t aubio_pitch_get_tolerance (aubio_pitch_t * o); | |||
| /** deletion of the pitch detection object | |||
| \param o pitch detection object as returned by new_aubio_pitch() | |||
| */ | |||
| void del_aubio_pitch (aubio_pitch_t * o); | |||
| /** creation of the pitch detection object | |||
| \param method set pitch detection algorithm | |||
| \param buf_size size of the input buffer to analyse | |||
| \param hop_size step size between two consecutive analysis instant | |||
| \param samplerate sampling rate of the signal | |||
| \return newly created ::aubio_pitch_t | |||
| */ | |||
| aubio_pitch_t *new_aubio_pitch (const char_t * method, | |||
| uint_t buf_size, uint_t hop_size, uint_t samplerate); | |||
| /** set the output unit of the pitch detection object | |||
| \param o pitch detection object as returned by new_aubio_pitch() | |||
| \param mode set pitch units for output | |||
| mode can be one of "Hz", "midi", "cent", or "bin". Defaults to "Hz". | |||
| \return 0 if successfull, non-zero otherwise | |||
| */ | |||
| uint_t aubio_pitch_set_unit (aubio_pitch_t * o, const char_t * mode); | |||
| /** set the silence threshold of the pitch detection object | |||
| \param o pitch detection object as returned by new_aubio_pitch() | |||
| \param silence level threshold under which pitch should be ignored, in dB | |||
| \return 0 if successfull, non-zero otherwise | |||
| */ | |||
| uint_t aubio_pitch_set_silence (aubio_pitch_t * o, smpl_t silence); | |||
| /** set the silence threshold of the pitch detection object | |||
| \param o pitch detection object as returned by ::new_aubio_pitch() | |||
| \return level threshold under which pitch should be ignored, in dB | |||
| */ | |||
| smpl_t aubio_pitch_get_silence (aubio_pitch_t * o); | |||
| /** get the current confidence | |||
| \param o pitch detection object as returned by new_aubio_pitch() | |||
| \return the current confidence of the pitch algorithm | |||
| */ | |||
| smpl_t aubio_pitch_get_confidence (aubio_pitch_t * o); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_PITCH_H */ | |||
| @@ -0,0 +1,144 @@ | |||
| /* | |||
| Copyright (C) 2004, 2005 Mario Lang <mlang@delysid.org> | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "cvec.h" | |||
| #include "mathutils.h" | |||
| #include "musicutils.h" | |||
| #include "spectral/fft.h" | |||
| #include "pitch/pitchfcomb.h" | |||
| #define MAX_PEAKS 8 | |||
| typedef struct | |||
| { | |||
| smpl_t bin; | |||
| smpl_t db; | |||
| } aubio_fpeak_t; | |||
| struct _aubio_pitchfcomb_t | |||
| { | |||
| uint_t fftSize; | |||
| uint_t stepSize; | |||
| uint_t rate; | |||
| fvec_t *winput; | |||
| fvec_t *win; | |||
| cvec_t *fftOut; | |||
| fvec_t *fftLastPhase; | |||
| aubio_fft_t *fft; | |||
| }; | |||
| aubio_pitchfcomb_t * | |||
| new_aubio_pitchfcomb (uint_t bufsize, uint_t hopsize) | |||
| { | |||
| aubio_pitchfcomb_t *p = AUBIO_NEW (aubio_pitchfcomb_t); | |||
| p->fftSize = bufsize; | |||
| p->stepSize = hopsize; | |||
| p->fft = new_aubio_fft (bufsize); | |||
| if (!p->fft) goto beach; | |||
| p->winput = new_fvec (bufsize); | |||
| p->fftOut = new_cvec (bufsize); | |||
| p->fftLastPhase = new_fvec (bufsize); | |||
| p->win = new_aubio_window ("hanning", bufsize); | |||
| return p; | |||
| beach: | |||
| AUBIO_FREE(p); | |||
| return NULL; | |||
| } | |||
| /* input must be stepsize long */ | |||
| void | |||
| aubio_pitchfcomb_do (aubio_pitchfcomb_t * p, const fvec_t * input, fvec_t * output) | |||
| { | |||
| uint_t k, l, maxharm = 0; | |||
| smpl_t phaseDifference = TWO_PI * (smpl_t) p->stepSize / (smpl_t) p->fftSize; | |||
| aubio_fpeak_t peaks[MAX_PEAKS]; | |||
| for (k = 0; k < MAX_PEAKS; k++) { | |||
| peaks[k].db = -200.; | |||
| peaks[k].bin = 0.; | |||
| } | |||
| for (k = 0; k < input->length; k++) { | |||
| p->winput->data[k] = p->win->data[k] * input->data[k]; | |||
| } | |||
| aubio_fft_do (p->fft, p->winput, p->fftOut); | |||
| for (k = 0; k <= p->fftSize / 2; k++) { | |||
| smpl_t | |||
| magnitude = | |||
| 20. * LOG10 (2. * p->fftOut->norm[k] / (smpl_t) p->fftSize), | |||
| phase = p->fftOut->phas[k], tmp, bin; | |||
| /* compute phase difference */ | |||
| tmp = phase - p->fftLastPhase->data[k]; | |||
| p->fftLastPhase->data[k] = phase; | |||
| /* subtract expected phase difference */ | |||
| tmp -= (smpl_t) k *phaseDifference; | |||
| /* map delta phase into +/- Pi interval */ | |||
| tmp = aubio_unwrap2pi (tmp); | |||
| /* get deviation from bin frequency from the +/- Pi interval */ | |||
| tmp = p->fftSize / (smpl_t) p->stepSize * tmp / (TWO_PI); | |||
| /* compute the k-th partials' true bin */ | |||
| bin = (smpl_t) k + tmp; | |||
| if (bin > 0.0 && magnitude > peaks[0].db) { // && magnitude < 0) { | |||
| memmove (peaks + 1, peaks, sizeof (aubio_fpeak_t) * (MAX_PEAKS - 1)); | |||
| peaks[0].bin = bin; | |||
| peaks[0].db = magnitude; | |||
| } | |||
| } | |||
| k = 0; | |||
| for (l = 1; l < MAX_PEAKS && peaks[l].bin > 0.0; l++) { | |||
| sint_t harmonic; | |||
| for (harmonic = 5; harmonic > 1; harmonic--) { | |||
| if (peaks[0].bin / peaks[l].bin < harmonic + .02 && | |||
| peaks[0].bin / peaks[l].bin > harmonic - .02) { | |||
| if (harmonic > (sint_t) maxharm && peaks[0].db < peaks[l].db / 2) { | |||
| maxharm = harmonic; | |||
| k = l; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| output->data[0] = peaks[k].bin; | |||
| /* quick hack to clean output a bit */ | |||
| if (peaks[k].bin > 5000.) | |||
| output->data[0] = 0.; | |||
| } | |||
| void | |||
| del_aubio_pitchfcomb (aubio_pitchfcomb_t * p) | |||
| { | |||
| del_cvec (p->fftOut); | |||
| del_fvec (p->fftLastPhase); | |||
| del_fvec (p->win); | |||
| del_fvec (p->winput); | |||
| del_aubio_fft (p->fft); | |||
| AUBIO_FREE (p); | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| /* | |||
| Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** \file | |||
| Pitch detection using a fast harmonic comb filter | |||
| This pitch extraction method implements a fast harmonic comb filter to | |||
| determine the fundamental frequency of a harmonic sound. | |||
| This file was derived from the tuneit project, written by Mario Lang to | |||
| detect the fundamental frequency of a sound. | |||
| See http://delysid.org/tuneit.html | |||
| \example pitch/test-pitchfcomb.c | |||
| */ | |||
| #ifndef AUBIO_PITCHFCOMB_H | |||
| #define AUBIO_PITCHFCOMB_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** pitch detection object */ | |||
| typedef struct _aubio_pitchfcomb_t aubio_pitchfcomb_t; | |||
| /** execute pitch detection on an input buffer | |||
| \param p pitch detection object as returned by new_aubio_pitchfcomb | |||
| \param input input signal window (length as specified at creation time) | |||
| \param output pitch candidates in bins | |||
| */ | |||
| void aubio_pitchfcomb_do (aubio_pitchfcomb_t * p, const fvec_t * input, | |||
| fvec_t * output); | |||
| /** creation of the pitch detection object | |||
| \param buf_size size of the input buffer to analyse | |||
| \param hop_size step size between two consecutive analysis instant | |||
| */ | |||
| aubio_pitchfcomb_t *new_aubio_pitchfcomb (uint_t buf_size, uint_t hop_size); | |||
| /** deletion of the pitch detection object | |||
| \param p pitch detection object as returned by new_aubio_pitchfcomb | |||
| */ | |||
| void del_aubio_pitchfcomb (aubio_pitchfcomb_t * p); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_PITCHFCOMB_H */ | |||
| @@ -0,0 +1,435 @@ | |||
| /* | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "cvec.h" | |||
| #include "mathutils.h" | |||
| #include "pitch/pitchmcomb.h" | |||
| #define CAND_SWAP(a,b) { register aubio_spectralcandidate_t *t=(a);(a)=(b);(b)=t; } | |||
| typedef struct _aubio_spectralpeak_t aubio_spectralpeak_t; | |||
| typedef struct _aubio_spectralcandidate_t aubio_spectralcandidate_t; | |||
| uint_t aubio_pitchmcomb_get_root_peak (aubio_spectralpeak_t * peaks, | |||
| uint_t length); | |||
| uint_t aubio_pitchmcomb_quadpick (aubio_spectralpeak_t * spectral_peaks, | |||
| const fvec_t * X); | |||
| void aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, const fvec_t * oldmag); | |||
| void aubio_pitchmcomb_combdet (aubio_pitchmcomb_t * p, const fvec_t * newmag); | |||
| /* not used but useful : sort by amplitudes (or anything else) | |||
| * sort_pitchpeak(peaks, length); | |||
| */ | |||
| #if 0 | |||
| /** spectral_peak comparison function (must return signed int) */ | |||
| static sint_t aubio_pitchmcomb_sort_peak_comp (const void *x, const void *y); | |||
| /** sort spectral_peak against their mag */ | |||
| void aubio_pitchmcomb_sort_peak (aubio_spectralpeak_t * peaks, uint_t nbins); | |||
| /** select the best candidates */ | |||
| uint_t aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, | |||
| smpl_t * cands); | |||
| #endif | |||
| /** sort spectral_candidate against their comb ene */ | |||
| void aubio_pitchmcomb_sort_cand_ene (aubio_spectralcandidate_t ** candidates, | |||
| uint_t nbins); | |||
| #if 0 | |||
| /** sort spectral_candidate against their frequency */ | |||
| void aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates, | |||
| uint_t nbins); | |||
| #endif | |||
| struct _aubio_pitchmcomb_t | |||
| { | |||
| smpl_t threshold; /**< offset threshold [0.033 or 0.01] */ | |||
| smpl_t alpha; /**< normalisation exponent [9] */ | |||
| smpl_t cutoff; /**< low-pass filter cutoff [0.34, 1] */ | |||
| smpl_t tol; /**< tolerance [0.05] */ | |||
| // smpl_t tau; /**< frequency precision [44100/4096] */ | |||
| uint_t win_post; /**< median filter window length */ | |||
| uint_t win_pre; /**< median filter window */ | |||
| uint_t ncand; /**< maximum number of candidates (combs) */ | |||
| uint_t npartials; /**< maximum number of partials per combs */ | |||
| uint_t count; /**< picked picks */ | |||
| uint_t goodcandidate; /**< best candidate */ | |||
| uint_t spec_partition; /**< spectrum partition to consider */ | |||
| aubio_spectralpeak_t *peaks; /**< up to length win/spec_partition */ | |||
| aubio_spectralcandidate_t **candidates; /** up to five candidates */ | |||
| /* some scratch pads */ | |||
| /** \bug (unnecessary copied from fftgrain?) */ | |||
| fvec_t *newmag; /**< vec to store mag */ | |||
| fvec_t *scratch; /**< vec to store modified mag */ | |||
| fvec_t *scratch2; /**< vec to compute moving median */ | |||
| fvec_t *theta; /**< vec to store phase */ | |||
| smpl_t phasediff; | |||
| smpl_t phasefreq; | |||
| /** threshfn: name or handle of fn for computing adaptive threshold [median] */ | |||
| /** aubio_thresholdfn_t thresholdfn; */ | |||
| /** picker: name or handle of fn for picking event times [quadpick] */ | |||
| /** aubio_pickerfn_t pickerfn; */ | |||
| }; | |||
| /** spectral peak object */ | |||
| struct _aubio_spectralpeak_t | |||
| { | |||
| uint_t bin; /**< bin [0-(length-1)] */ | |||
| smpl_t ebin; /**< estimated bin */ | |||
| smpl_t mag; /**< peak magnitude */ | |||
| }; | |||
| /** spectral candidates array object */ | |||
| struct _aubio_spectralcandidate_t | |||
| { | |||
| smpl_t ebin; /**< interpolated bin */ | |||
| smpl_t *ecomb; /**< comb */ | |||
| smpl_t ene; /**< candidate energy */ | |||
| smpl_t len; /**< length */ | |||
| }; | |||
| void | |||
| aubio_pitchmcomb_do (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, fvec_t * output) | |||
| { | |||
| uint_t j; | |||
| smpl_t instfreq; | |||
| fvec_t *newmag = (fvec_t *) p->newmag; | |||
| //smpl_t hfc; //fe=instfreq(theta1,theta,ops); //theta1=theta; | |||
| /* copy incoming grain to newmag */ | |||
| for (j = 0; j < newmag->length; j++) | |||
| newmag->data[j] = fftgrain->norm[j]; | |||
| /* detect only if local energy > 10. */ | |||
| //if (aubio_level_lin (newmag) * newmag->length > 10.) { | |||
| //hfc = fvec_local_hfc(newmag); //not used | |||
| aubio_pitchmcomb_spectral_pp (p, newmag); | |||
| aubio_pitchmcomb_combdet (p, newmag); | |||
| //aubio_pitchmcomb_sort_cand_freq(p->candidates,p->ncand); | |||
| //return p->candidates[p->goodcandidate]->ebin; | |||
| j = (uint_t) FLOOR (p->candidates[p->goodcandidate]->ebin + .5); | |||
| instfreq = aubio_unwrap2pi (fftgrain->phas[j] | |||
| - p->theta->data[j] - j * p->phasediff); | |||
| instfreq *= p->phasefreq; | |||
| /* store phase for next run */ | |||
| for (j = 0; j < p->theta->length; j++) { | |||
| p->theta->data[j] = fftgrain->phas[j]; | |||
| } | |||
| //return p->candidates[p->goodcandidate]->ebin; | |||
| output->data[0] = | |||
| FLOOR (p->candidates[p->goodcandidate]->ebin + .5) + instfreq; | |||
| /*} else { | |||
| return -1.; | |||
| } */ | |||
| } | |||
| #if 0 | |||
| uint_t | |||
| aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, smpl_t * cands) | |||
| { | |||
| uint_t j; | |||
| uint_t k; | |||
| fvec_t *newmag = (fvec_t *) p->newmag; | |||
| aubio_spectralcandidate_t **scands = | |||
| (aubio_spectralcandidate_t **) (p->candidates); | |||
| //smpl_t hfc; //fe=instfreq(theta1,theta,ops); //theta1=theta; | |||
| /* copy incoming grain to newmag */ | |||
| for (j = 0; j < newmag->length; j++) | |||
| newmag->data[j] = fftgrain->norm[j]; | |||
| /* detect only if local energy > 10. */ | |||
| if (aubio_level_lin (newmag) * newmag->length > 10.) { | |||
| /* hfc = fvec_local_hfc(newmag); do not use */ | |||
| aubio_pitchmcomb_spectral_pp (p, newmag); | |||
| aubio_pitchmcomb_combdet (p, newmag); | |||
| aubio_pitchmcomb_sort_cand_freq (scands, p->ncand); | |||
| /* store ncand comb energies in cands[1:ncand] */ | |||
| for (k = 0; k < p->ncand; k++) | |||
| cands[k] = p->candidates[k]->ene; | |||
| /* store ncand[end] freq in cands[end] */ | |||
| cands[p->ncand] = p->candidates[p->ncand - 1]->ebin; | |||
| return 1; | |||
| } else { | |||
| for (k = 0; k < p->ncand; k++) | |||
| cands[k] = 0; | |||
| return 0; | |||
| } | |||
| } | |||
| #endif | |||
| void | |||
| aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, const fvec_t * newmag) | |||
| { | |||
| fvec_t *mag = (fvec_t *) p->scratch; | |||
| fvec_t *tmp = (fvec_t *) p->scratch2; | |||
| uint_t j; | |||
| uint_t length = mag->length; | |||
| /* copy newmag to mag (scracth) */ | |||
| for (j = 0; j < length; j++) { | |||
| mag->data[j] = newmag->data[j]; | |||
| } | |||
| fvec_min_removal (mag); /* min removal */ | |||
| fvec_alpha_normalise (mag, p->alpha); /* alpha normalisation */ | |||
| /* skipped *//* low pass filtering */ | |||
| /** \bug fvec_moving_thres may write out of bounds */ | |||
| fvec_adapt_thres (mag, tmp, p->win_post, p->win_pre); /* adaptative threshold */ | |||
| fvec_add (mag, -p->threshold); /* fixed threshold */ | |||
| { | |||
| aubio_spectralpeak_t *peaks = (aubio_spectralpeak_t *) p->peaks; | |||
| uint_t count; | |||
| /* return bin and ebin */ | |||
| count = aubio_pitchmcomb_quadpick (peaks, mag); | |||
| for (j = 0; j < count; j++) | |||
| peaks[j].mag = newmag->data[peaks[j].bin]; | |||
| /* reset non peaks */ | |||
| for (j = count; j < length; j++) | |||
| peaks[j].mag = 0.; | |||
| p->peaks = peaks; | |||
| p->count = count; | |||
| } | |||
| } | |||
| void | |||
| aubio_pitchmcomb_combdet (aubio_pitchmcomb_t * p, const fvec_t * newmag) | |||
| { | |||
| aubio_spectralpeak_t *peaks = (aubio_spectralpeak_t *) p->peaks; | |||
| aubio_spectralcandidate_t **candidate = | |||
| (aubio_spectralcandidate_t **) p->candidates; | |||
| /* parms */ | |||
| uint_t N = p->npartials; /* maximum number of partials to be considered 10 */ | |||
| uint_t M = p->ncand; /* maximum number of combs to be considered 5 */ | |||
| uint_t length = newmag->length; | |||
| uint_t count = p->count; | |||
| uint_t k; | |||
| uint_t l; | |||
| uint_t d; | |||
| uint_t curlen = 0; | |||
| smpl_t delta2; | |||
| smpl_t xx; | |||
| uint_t position = 0; | |||
| uint_t root_peak = 0; | |||
| uint_t tmpl = 0; | |||
| smpl_t tmpene = 0.; | |||
| /* get the biggest peak in the spectrum */ | |||
| root_peak = aubio_pitchmcomb_get_root_peak (peaks, count); | |||
| /* not enough partials in highest notes, could be forced */ | |||
| //if (peaks[root_peak].ebin >= aubio_miditofreq(85.)/p->tau) N=2; | |||
| //if (peaks[root_peak].ebin >= aubio_miditofreq(90.)/p->tau) N=1; | |||
| /* now calculate the energy of each of the 5 combs */ | |||
| for (l = 0; l < M; l++) { | |||
| smpl_t scaler = (1. / (l + 1.)); | |||
| candidate[l]->ene = 0.; /* reset ene and len sums */ | |||
| candidate[l]->len = 0.; | |||
| candidate[l]->ebin = scaler * peaks[root_peak].ebin; | |||
| /* if less than N peaks available, curlen < N */ | |||
| if (candidate[l]->ebin != 0.) | |||
| curlen = (uint_t) FLOOR (length / (candidate[l]->ebin)); | |||
| curlen = (N < curlen) ? N : curlen; | |||
| /* fill candidate[l]->ecomb[k] with (k+1)*candidate[l]->ebin */ | |||
| for (k = 0; k < curlen; k++) | |||
| candidate[l]->ecomb[k] = (candidate[l]->ebin) * (k + 1.); | |||
| for (k = curlen; k < length; k++) | |||
| candidate[l]->ecomb[k] = 0.; | |||
| /* for each in candidate[l]->ecomb[k] */ | |||
| for (k = 0; k < curlen; k++) { | |||
| xx = 100000.; | |||
| /** get the candidate->ecomb the closer to peaks.ebin | |||
| * (to cope with the inharmonicity)*/ | |||
| for (d = 0; d < count; d++) { | |||
| delta2 = ABS (candidate[l]->ecomb[k] - peaks[d].ebin); | |||
| if (delta2 <= xx) { | |||
| position = d; | |||
| xx = delta2; | |||
| } | |||
| } | |||
| /* for a Q factor of 17, maintaining "constant Q filtering", | |||
| * and sum energy and length over non null combs */ | |||
| if (17. * xx < candidate[l]->ecomb[k]) { | |||
| candidate[l]->ecomb[k] = peaks[position].ebin; | |||
| candidate[l]->ene += /* ecomb rounded to nearest int */ | |||
| POW (newmag->data[(uint_t) FLOOR (candidate[l]->ecomb[k] + .5)], | |||
| 0.25); | |||
| candidate[l]->len += 1. / curlen; | |||
| } else | |||
| candidate[l]->ecomb[k] = 0.; | |||
| } | |||
| /* punishment */ | |||
| /*if (candidate[l]->len<0.6) | |||
| candidate[l]->ene=0.; */ | |||
| /* remember best candidate energy (in polyphonic, could check for | |||
| * tmpene*1.1 < candidate->ene to reduce jumps towards low frequencies) */ | |||
| if (tmpene < candidate[l]->ene) { | |||
| tmpl = l; | |||
| tmpene = candidate[l]->ene; | |||
| } | |||
| } | |||
| //p->candidates=candidate; | |||
| //p->peaks=peaks; | |||
| p->goodcandidate = tmpl; | |||
| } | |||
| /** T=quadpick(X): return indices of elements of X which are peaks and positive | |||
| * exact peak positions are retrieved by quadratic interpolation | |||
| * | |||
| * \bug peak-picking too picky, sometimes counts too many peaks ? | |||
| */ | |||
| uint_t | |||
| aubio_pitchmcomb_quadpick (aubio_spectralpeak_t * spectral_peaks, const fvec_t * X) | |||
| { | |||
| uint_t j, ispeak, count = 0; | |||
| for (j = 1; j < X->length - 1; j++) { | |||
| ispeak = fvec_peakpick (X, j); | |||
| if (ispeak) { | |||
| count += ispeak; | |||
| spectral_peaks[count - 1].bin = j; | |||
| spectral_peaks[count - 1].ebin = fvec_quadratic_peak_pos (X, j); | |||
| } | |||
| } | |||
| return count; | |||
| } | |||
| /* get predominant partial */ | |||
| uint_t | |||
| aubio_pitchmcomb_get_root_peak (aubio_spectralpeak_t * peaks, uint_t length) | |||
| { | |||
| uint_t i, pos = 0; | |||
| smpl_t tmp = 0.; | |||
| for (i = 0; i < length; i++) | |||
| if (tmp <= peaks[i].mag) { | |||
| pos = i; | |||
| tmp = peaks[i].mag; | |||
| } | |||
| return pos; | |||
| } | |||
| #if 0 | |||
| void | |||
| aubio_pitchmcomb_sort_peak (aubio_spectralpeak_t * peaks, uint_t nbins) | |||
| { | |||
| qsort (peaks, nbins, sizeof (aubio_spectralpeak_t), | |||
| aubio_pitchmcomb_sort_peak_comp); | |||
| } | |||
| static sint_t | |||
| aubio_pitchmcomb_sort_peak_comp (const void *x, const void *y) | |||
| { | |||
| return (((aubio_spectralpeak_t *) y)->mag - | |||
| ((aubio_spectralpeak_t *) x)->mag); | |||
| } | |||
| void | |||
| aubio_pitchmcomb_sort_cand_ene (aubio_spectralcandidate_t ** candidates, | |||
| uint_t nbins) | |||
| { | |||
| uint_t cur = 0; | |||
| uint_t run = 0; | |||
| for (cur = 0; cur < nbins; cur++) { | |||
| for (run = cur + 1; run < nbins; run++) { | |||
| if (candidates[run]->ene > candidates[cur]->ene) | |||
| CAND_SWAP (candidates[run], candidates[cur]); | |||
| } | |||
| } | |||
| } | |||
| void | |||
| aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates, | |||
| uint_t nbins) | |||
| { | |||
| uint_t cur = 0; | |||
| uint_t run = 0; | |||
| for (cur = 0; cur < nbins; cur++) { | |||
| for (run = cur + 1; run < nbins; run++) { | |||
| if (candidates[run]->ebin < candidates[cur]->ebin) | |||
| CAND_SWAP (candidates[run], candidates[cur]); | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| aubio_pitchmcomb_t * | |||
| new_aubio_pitchmcomb (uint_t bufsize, uint_t hopsize) | |||
| { | |||
| aubio_pitchmcomb_t *p = AUBIO_NEW (aubio_pitchmcomb_t); | |||
| /* bug: should check if size / 8 > post+pre+1 */ | |||
| uint_t i, j; | |||
| uint_t spec_size; | |||
| p->spec_partition = 2; | |||
| p->ncand = 5; | |||
| p->npartials = 5; | |||
| p->cutoff = 1.; | |||
| p->threshold = 0.01; | |||
| p->win_post = 8; | |||
| p->win_pre = 7; | |||
| // p->tau = samplerate/bufsize; | |||
| p->alpha = 9.; | |||
| p->goodcandidate = 0; | |||
| p->phasefreq = bufsize / hopsize / TWO_PI; | |||
| p->phasediff = TWO_PI * hopsize / bufsize; | |||
| spec_size = bufsize / p->spec_partition + 1; | |||
| //p->pickerfn = quadpick; | |||
| //p->biquad = new_biquad(0.1600,0.3200,0.1600, -0.5949, 0.2348); | |||
| /* allocate temp memory */ | |||
| p->newmag = new_fvec (spec_size); | |||
| /* array for median */ | |||
| p->scratch = new_fvec (spec_size); | |||
| /* array for phase */ | |||
| p->theta = new_fvec (spec_size); | |||
| /* array for adaptative threshold */ | |||
| p->scratch2 = new_fvec (p->win_post + p->win_pre + 1); | |||
| /* array of spectral peaks */ | |||
| p->peaks = AUBIO_ARRAY (aubio_spectralpeak_t, spec_size); | |||
| for (i = 0; i < spec_size; i++) { | |||
| p->peaks[i].bin = 0.; | |||
| p->peaks[i].ebin = 0.; | |||
| p->peaks[i].mag = 0.; | |||
| } | |||
| /* array of pointers to spectral candidates */ | |||
| p->candidates = AUBIO_ARRAY (aubio_spectralcandidate_t *, p->ncand); | |||
| for (i = 0; i < p->ncand; i++) { | |||
| p->candidates[i] = AUBIO_NEW (aubio_spectralcandidate_t); | |||
| p->candidates[i]->ecomb = AUBIO_ARRAY (smpl_t, spec_size); | |||
| for (j = 0; j < spec_size; j++) { | |||
| p->candidates[i]->ecomb[j] = 0.; | |||
| } | |||
| p->candidates[i]->ene = 0.; | |||
| p->candidates[i]->ebin = 0.; | |||
| p->candidates[i]->len = 0.; | |||
| } | |||
| return p; | |||
| } | |||
| void | |||
| del_aubio_pitchmcomb (aubio_pitchmcomb_t * p) | |||
| { | |||
| uint_t i; | |||
| del_fvec (p->newmag); | |||
| del_fvec (p->scratch); | |||
| del_fvec (p->theta); | |||
| del_fvec (p->scratch2); | |||
| AUBIO_FREE (p->peaks); | |||
| for (i = 0; i < p->ncand; i++) { | |||
| AUBIO_FREE (p->candidates[i]->ecomb); | |||
| AUBIO_FREE (p->candidates[i]); | |||
| } | |||
| AUBIO_FREE (p->candidates); | |||
| AUBIO_FREE (p); | |||
| } | |||
| @@ -0,0 +1,77 @@ | |||
| /* | |||
| Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** \file | |||
| Pitch detection using multiple-comb filter | |||
| This fundamental frequency estimation algorithm implements spectral | |||
| flattening, multi-comb filtering and peak histogramming. | |||
| This method was designed by Juan P. Bello and described in: | |||
| Juan-Pablo Bello. ``Towards the Automated Analysis of Simple Polyphonic | |||
| Music''. PhD thesis, Centre for Digital Music, Queen Mary University of | |||
| London, London, UK, 2003. | |||
| \example pitch/test-pitchmcomb.c | |||
| */ | |||
| #ifndef AUBIO_PITCHMCOMB_H | |||
| #define AUBIO_PITCHMCOMB_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** pitch detection object */ | |||
| typedef struct _aubio_pitchmcomb_t aubio_pitchmcomb_t; | |||
| /** execute pitch detection on an input spectral frame | |||
| \param p pitch detection object as returned by new_aubio_pitchmcomb | |||
| \param in_fftgrain input signal spectrum as computed by aubio_pvoc_do | |||
| \param out_cands pitch candidate frequenciess, in bins | |||
| */ | |||
| void aubio_pitchmcomb_do (aubio_pitchmcomb_t * p, const cvec_t * in_fftgrain, | |||
| fvec_t * out_cands); | |||
| /** creation of the pitch detection object | |||
| \param buf_size size of the input buffer to analyse | |||
| \param hop_size step size between two consecutive analysis instant | |||
| */ | |||
| aubio_pitchmcomb_t *new_aubio_pitchmcomb (uint_t buf_size, uint_t hop_size); | |||
| /** deletion of the pitch detection object | |||
| \param p pitch detection object as returned by new_aubio_pitchfcomb | |||
| */ | |||
| void del_aubio_pitchmcomb (aubio_pitchmcomb_t * p); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_PITCHMCOMB_H */ | |||
| @@ -0,0 +1,119 @@ | |||
| /* | |||
| Copyright (C) 2004, 2005 Mario Lang <mlang@delysid.org> | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "pitch/pitchschmitt.h" | |||
| smpl_t aubio_schmittS16LE (aubio_pitchschmitt_t * p, uint_t nframes, | |||
| signed short int *indata); | |||
| struct _aubio_pitchschmitt_t | |||
| { | |||
| uint_t blockSize; | |||
| uint_t rate; | |||
| signed short int *schmittBuffer; | |||
| signed short int *schmittPointer; | |||
| signed short int *buf; | |||
| }; | |||
| aubio_pitchschmitt_t * | |||
| new_aubio_pitchschmitt (uint_t size) | |||
| { | |||
| aubio_pitchschmitt_t *p = AUBIO_NEW (aubio_pitchschmitt_t); | |||
| p->blockSize = size; | |||
| p->schmittBuffer = AUBIO_ARRAY (signed short int, p->blockSize); | |||
| p->buf = AUBIO_ARRAY (signed short int, p->blockSize); | |||
| p->schmittPointer = p->schmittBuffer; | |||
| return p; | |||
| } | |||
| void | |||
| aubio_pitchschmitt_do (aubio_pitchschmitt_t * p, const fvec_t * input, | |||
| fvec_t * output) | |||
| { | |||
| uint_t j; | |||
| for (j = 0; j < input->length; j++) { | |||
| p->buf[j] = input->data[j] * 32768.; | |||
| } | |||
| output->data[0] = aubio_schmittS16LE (p, input->length, p->buf); | |||
| } | |||
| smpl_t | |||
| aubio_schmittS16LE (aubio_pitchschmitt_t * p, uint_t nframes, | |||
| signed short int *indata) | |||
| { | |||
| uint_t i, j; | |||
| uint_t blockSize = p->blockSize; | |||
| signed short int *schmittBuffer = p->schmittBuffer; | |||
| signed short int *schmittPointer = p->schmittPointer; | |||
| smpl_t period = 0., trigfact = 0.6; | |||
| for (i = 0; i < nframes; i++) { | |||
| *schmittPointer++ = indata[i]; | |||
| if (schmittPointer - schmittBuffer >= (sint_t) blockSize) { | |||
| sint_t endpoint, startpoint, t1, t2, A1, A2, tc, schmittTriggered; | |||
| schmittPointer = schmittBuffer; | |||
| for (j = 0, A1 = 0, A2 = 0; j < blockSize; j++) { | |||
| if (schmittBuffer[j] > 0 && A1 < schmittBuffer[j]) | |||
| A1 = schmittBuffer[j]; | |||
| if (schmittBuffer[j] < 0 && A2 < -schmittBuffer[j]) | |||
| A2 = -schmittBuffer[j]; | |||
| } | |||
| t1 = (sint_t) (A1 * trigfact + 0.5); | |||
| t2 = -(sint_t) (A2 * trigfact + 0.5); | |||
| startpoint = 0; | |||
| for (j = 1; j < blockSize && schmittBuffer[j] <= t1; j++); | |||
| for ( ; j < blockSize - 1 && !(schmittBuffer[j] >= t2 && | |||
| schmittBuffer[j + 1] < t2); j++); | |||
| startpoint = j; | |||
| schmittTriggered = 0; | |||
| endpoint = startpoint + 1; | |||
| for (j = startpoint, tc = 0; j < blockSize; j++) { | |||
| if (!schmittTriggered) { | |||
| schmittTriggered = (schmittBuffer[j] >= t1); | |||
| } else if (schmittBuffer[j] >= t2 && schmittBuffer[j + 1] < t2) { | |||
| endpoint = j; | |||
| tc++; | |||
| schmittTriggered = 0; | |||
| } | |||
| } | |||
| if ((endpoint > startpoint) && (tc > 0)) { | |||
| period = (smpl_t) (endpoint - startpoint) / tc; | |||
| } | |||
| } | |||
| } | |||
| p->schmittBuffer = schmittBuffer; | |||
| p->schmittPointer = schmittPointer; | |||
| return period; | |||
| } | |||
| void | |||
| del_aubio_pitchschmitt (aubio_pitchschmitt_t * p) | |||
| { | |||
| AUBIO_FREE (p->schmittBuffer); | |||
| AUBIO_FREE (p->buf); | |||
| AUBIO_FREE (p); | |||
| } | |||
| @@ -0,0 +1,75 @@ | |||
| /* | |||
| Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** \file | |||
| Pitch detection using a Schmitt trigger | |||
| This pitch extraction method implements a Schmitt trigger to estimate the | |||
| period of a signal. | |||
| This file was derived from the tuneit project, written by Mario Lang to | |||
| detect the fundamental frequency of a sound. | |||
| See http://delysid.org/tuneit.html | |||
| \example pitch/test-pitchschmitt.c | |||
| */ | |||
| #ifndef AUBIO_PITCHSCHMITT_H | |||
| #define AUBIO_PITCHSCHMITT_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** pitch detection object */ | |||
| typedef struct _aubio_pitchschmitt_t aubio_pitchschmitt_t; | |||
| /** execute pitch detection on an input buffer | |||
| \param p pitch detection object as returned by new_aubio_pitchschmitt | |||
| \param samples_in input signal vector (length as specified at creation time) | |||
| \param cands_out pitch period estimates, in samples | |||
| */ | |||
| void aubio_pitchschmitt_do (aubio_pitchschmitt_t * p, const fvec_t * samples_in, | |||
| fvec_t * cands_out); | |||
| /** creation of the pitch detection object | |||
| \param buf_size size of the input buffer to analyse | |||
| */ | |||
| aubio_pitchschmitt_t *new_aubio_pitchschmitt (uint_t buf_size); | |||
| /** deletion of the pitch detection object | |||
| \param p pitch detection object as returned by new_aubio_pitchschmitt | |||
| */ | |||
| void del_aubio_pitchschmitt (aubio_pitchschmitt_t * p); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_PITCHSCHMITT_H */ | |||
| @@ -0,0 +1,116 @@ | |||
| /* | |||
| Copyright (C) 2013 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "cvec.h" | |||
| #include "mathutils.h" | |||
| #include "spectral/fft.h" | |||
| #include "pitch/pitchspecacf.h" | |||
| /** pitch specacf structure */ | |||
| struct _aubio_pitchspecacf_t | |||
| { | |||
| fvec_t *win; /**< temporal weighting window */ | |||
| fvec_t *winput; /**< windowed spectrum */ | |||
| aubio_fft_t *fft; /**< fft object to compute*/ | |||
| fvec_t *fftout; /**< Fourier transform output */ | |||
| fvec_t *sqrmag; /**< square magnitudes */ | |||
| fvec_t *acf; /**< auto correlation function */ | |||
| smpl_t tol; /**< tolerance */ | |||
| smpl_t confidence; /**< confidence */ | |||
| }; | |||
| aubio_pitchspecacf_t * | |||
| new_aubio_pitchspecacf (uint_t bufsize) | |||
| { | |||
| aubio_pitchspecacf_t *p = AUBIO_NEW (aubio_pitchspecacf_t); | |||
| p->fft = new_aubio_fft (bufsize); | |||
| if (!p->fft) goto beach; | |||
| p->win = new_aubio_window ("hanningz", bufsize); | |||
| p->winput = new_fvec (bufsize); | |||
| p->fftout = new_fvec (bufsize); | |||
| p->sqrmag = new_fvec (bufsize); | |||
| p->acf = new_fvec (bufsize / 2 + 1); | |||
| p->tol = 1.; | |||
| p->confidence = 0.; | |||
| return p; | |||
| beach: | |||
| AUBIO_FREE(p); | |||
| return NULL; | |||
| } | |||
| void | |||
| aubio_pitchspecacf_do (aubio_pitchspecacf_t * p, const fvec_t * input, fvec_t * output) | |||
| { | |||
| uint_t l, tau; | |||
| fvec_t *fftout = p->fftout; | |||
| // window the input | |||
| for (l = 0; l < input->length; l++) { | |||
| p->winput->data[l] = p->win->data[l] * input->data[l]; | |||
| } | |||
| // get the real / imag parts of its fft | |||
| aubio_fft_do_complex (p->fft, p->winput, fftout); | |||
| for (l = 0; l < input->length / 2 + 1; l++) { | |||
| p->sqrmag->data[l] = SQR(fftout->data[l]); | |||
| } | |||
| // get the real / imag parts of the fft of the squared magnitude | |||
| aubio_fft_do_complex (p->fft, p->sqrmag, fftout); | |||
| // copy real part to acf | |||
| for (l = 0; l < fftout->length / 2 + 1; l++) { | |||
| p->acf->data[l] = fftout->data[l]; | |||
| } | |||
| // get the minimum | |||
| tau = fvec_min_elem (p->acf); | |||
| // get the interpolated minimum | |||
| output->data[0] = fvec_quadratic_peak_pos (p->acf, tau) * 2.; | |||
| } | |||
| void | |||
| del_aubio_pitchspecacf (aubio_pitchspecacf_t * p) | |||
| { | |||
| del_fvec (p->win); | |||
| del_fvec (p->winput); | |||
| del_aubio_fft (p->fft); | |||
| del_fvec (p->sqrmag); | |||
| del_fvec (p->fftout); | |||
| del_fvec (p->acf); | |||
| AUBIO_FREE (p); | |||
| } | |||
| smpl_t | |||
| aubio_pitchspecacf_get_confidence (const aubio_pitchspecacf_t * o) { | |||
| // no confidence for now | |||
| return o->confidence; | |||
| } | |||
| uint_t | |||
| aubio_pitchspecacf_set_tolerance (aubio_pitchspecacf_t * p, smpl_t tol) | |||
| { | |||
| p->tol = tol; | |||
| return 0; | |||
| } | |||
| smpl_t | |||
| aubio_pitchspecacf_get_tolerance (const aubio_pitchspecacf_t * p) | |||
| { | |||
| return p->tol; | |||
| } | |||
| @@ -0,0 +1,103 @@ | |||
| /* | |||
| Copyright (C) 2013 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** \file | |||
| Pitch detection using spectral auto correlation | |||
| This algorithm implements pitch detection by computing the autocorrelation | |||
| function as the cosine transform of the square spectral magnitudes. | |||
| Anssi Klapuri. Qualitative and quantitative aspects in the design of | |||
| periodicity esti- mation algorithms. In Proceedings of the European Signal | |||
| Processing Conference (EUSIPCO), 2000. | |||
| Paul Brossier, [Automatic annotation of musical audio for interactive | |||
| systems](http://aubio.org/phd/), Chapter 3, Pitch Analysis, Autocorrelation, | |||
| pp. 75-77, PhD thesis, Centre for Digital music, Queen Mary University of | |||
| London, London, UK, 2006. | |||
| \example pitch/test-pitchspecacf.c | |||
| */ | |||
| #ifndef AUBIO_PITCHSPECACF_H | |||
| #define AUBIO_PITCHSPECACF_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** pitch detection object */ | |||
| typedef struct _aubio_pitchspecacf_t aubio_pitchspecacf_t; | |||
| /** execute pitch detection on an input buffer | |||
| \param o pitch detection object as returned by new_aubio_pitchspecacf | |||
| \param samples_in input signal vector (length as specified at creation time) | |||
| \param cands_out pitch period candidates, in samples | |||
| */ | |||
| void aubio_pitchspecacf_do (aubio_pitchspecacf_t * o, const fvec_t * samples_in, fvec_t * cands_out); | |||
| /** creation of the pitch detection object | |||
| \param buf_size size of the input buffer to analyse | |||
| */ | |||
| aubio_pitchspecacf_t *new_aubio_pitchspecacf (uint_t buf_size); | |||
| /** deletion of the pitch detection object | |||
| \param o pitch detection object as returned by new_aubio_pitchspecacf() | |||
| */ | |||
| void del_aubio_pitchspecacf (aubio_pitchspecacf_t * o); | |||
| /** get tolerance parameter for `specacf` pitch detection object | |||
| \param o pitch detection object | |||
| \return tolerance parameter for minima selection [default 1.] | |||
| */ | |||
| smpl_t aubio_pitchspecacf_get_tolerance (const aubio_pitchspecacf_t * o); | |||
| /** set tolerance parameter for `specacf` pitch detection object | |||
| \param o pitch detection object | |||
| \param tol tolerance parameter for minima selection [default 1.] | |||
| \return `1` on error, `0` on success | |||
| */ | |||
| uint_t aubio_pitchspecacf_set_tolerance (aubio_pitchspecacf_t * o, smpl_t tol); | |||
| /** get currenct confidence for `specacf` pitch detection object | |||
| \param o pitch detection object | |||
| \return confidence parameter | |||
| */ | |||
| smpl_t aubio_pitchspecacf_get_confidence (const aubio_pitchspecacf_t * o); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_PITCHSPECACF_H */ | |||
| @@ -0,0 +1,189 @@ | |||
| /* | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /* This algorithm was developed by A. de Cheveigné and H. Kawahara and | |||
| * published in: | |||
| * | |||
| * de Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency | |||
| * estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930. | |||
| * | |||
| * see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "mathutils.h" | |||
| #include "pitch/pitchyin.h" | |||
| struct _aubio_pitchyin_t | |||
| { | |||
| fvec_t *yin; | |||
| smpl_t tol; | |||
| uint_t peak_pos; | |||
| }; | |||
| #if 0 | |||
| /** compute difference function | |||
| \param input input signal | |||
| \param yinbuf output buffer to store difference function (half shorter than input) | |||
| */ | |||
| void aubio_pitchyin_diff (fvec_t * input, fvec_t * yinbuf); | |||
| /** in place computation of the YIN cumulative normalised function | |||
| \param yinbuf input signal (a square difference function), also used to store function | |||
| */ | |||
| void aubio_pitchyin_getcum (fvec_t * yinbuf); | |||
| /** detect pitch in a YIN function | |||
| \param yinbuf input buffer as computed by aubio_pitchyin_getcum | |||
| */ | |||
| uint_t aubio_pitchyin_getpitch (const fvec_t * yinbuf); | |||
| #endif | |||
| aubio_pitchyin_t * | |||
| new_aubio_pitchyin (uint_t bufsize) | |||
| { | |||
| aubio_pitchyin_t *o = AUBIO_NEW (aubio_pitchyin_t); | |||
| o->yin = new_fvec (bufsize / 2); | |||
| o->tol = 0.15; | |||
| o->peak_pos = 0; | |||
| return o; | |||
| } | |||
| void | |||
| del_aubio_pitchyin (aubio_pitchyin_t * o) | |||
| { | |||
| del_fvec (o->yin); | |||
| AUBIO_FREE (o); | |||
| } | |||
| #if 0 | |||
| /* outputs the difference function */ | |||
| void | |||
| aubio_pitchyin_diff (fvec_t * input, fvec_t * yin) | |||
| { | |||
| uint_t j, tau; | |||
| smpl_t tmp; | |||
| for (tau = 0; tau < yin->length; tau++) { | |||
| yin->data[tau] = 0.; | |||
| } | |||
| for (tau = 1; tau < yin->length; tau++) { | |||
| for (j = 0; j < yin->length; j++) { | |||
| tmp = input->data[j] - input->data[j + tau]; | |||
| yin->data[tau] += SQR (tmp); | |||
| } | |||
| } | |||
| } | |||
| /* cumulative mean normalized difference function */ | |||
| void | |||
| aubio_pitchyin_getcum (fvec_t * yin) | |||
| { | |||
| uint_t tau; | |||
| smpl_t tmp = 0.; | |||
| yin->data[0] = 1.; | |||
| //AUBIO_DBG("%f\t",yin->data[0]); | |||
| for (tau = 1; tau < yin->length; tau++) { | |||
| tmp += yin->data[tau]; | |||
| yin->data[tau] *= tau / tmp; | |||
| //AUBIO_DBG("%f\t",yin->data[tau]); | |||
| } | |||
| //AUBIO_DBG("\n"); | |||
| } | |||
| uint_t | |||
| aubio_pitchyin_getpitch (const fvec_t * yin) | |||
| { | |||
| uint_t tau = 1; | |||
| do { | |||
| if (yin->data[tau] < 0.1) { | |||
| while (yin->data[tau + 1] < yin->data[tau]) { | |||
| tau++; | |||
| } | |||
| return tau; | |||
| } | |||
| tau++; | |||
| } while (tau < yin->length); | |||
| //AUBIO_DBG("No pitch found"); | |||
| return 0; | |||
| } | |||
| #endif | |||
| /* all the above in one */ | |||
| void | |||
| aubio_pitchyin_do (aubio_pitchyin_t * o, const fvec_t * input, fvec_t * out) | |||
| { | |||
| const smpl_t tol = o->tol; | |||
| fvec_t* yin = o->yin; | |||
| const smpl_t *input_data = input->data; | |||
| const uint_t length = yin->length; | |||
| smpl_t *yin_data = yin->data; | |||
| uint_t j, tau; | |||
| sint_t period; | |||
| smpl_t tmp, tmp2 = 0.; | |||
| yin_data[0] = 1.; | |||
| for (tau = 1; tau < length; tau++) { | |||
| yin_data[tau] = 0.; | |||
| for (j = 0; j < length; j++) { | |||
| tmp = input_data[j] - input_data[j + tau]; | |||
| yin_data[tau] += SQR (tmp); | |||
| } | |||
| tmp2 += yin_data[tau]; | |||
| if (tmp2 != 0) { | |||
| yin->data[tau] *= tau / tmp2; | |||
| } else { | |||
| yin->data[tau] = 1.; | |||
| } | |||
| period = tau - 3; | |||
| if (tau > 4 && (yin_data[period] < tol) && | |||
| (yin_data[period] < yin_data[period + 1])) { | |||
| o->peak_pos = (uint_t)period; | |||
| out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos); | |||
| return; | |||
| } | |||
| } | |||
| o->peak_pos = (uint_t)fvec_min_elem (yin); | |||
| out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos); | |||
| } | |||
| smpl_t | |||
| aubio_pitchyin_get_confidence (aubio_pitchyin_t * o) { | |||
| return 1. - o->yin->data[o->peak_pos]; | |||
| } | |||
| uint_t | |||
| aubio_pitchyin_set_tolerance (aubio_pitchyin_t * o, smpl_t tol) | |||
| { | |||
| o->tol = tol; | |||
| return 0; | |||
| } | |||
| smpl_t | |||
| aubio_pitchyin_get_tolerance (aubio_pitchyin_t * o) | |||
| { | |||
| return o->tol; | |||
| } | |||
| @@ -0,0 +1,100 @@ | |||
| /* | |||
| Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** \file | |||
| Pitch detection using the YIN algorithm | |||
| This algorithm was developed by A. de Cheveigne and H. Kawahara and | |||
| published in: | |||
| De Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency | |||
| estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930. | |||
| see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html | |||
| http://recherche.ircam.fr/equipes/pcm/cheveign/ps/2002_JASA_YIN_proof.pdf | |||
| \example pitch/test-pitchyin.c | |||
| */ | |||
| #ifndef AUBIO_PITCHYIN_H | |||
| #define AUBIO_PITCHYIN_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** pitch detection object */ | |||
| typedef struct _aubio_pitchyin_t aubio_pitchyin_t; | |||
| /** creation of the pitch detection object | |||
| \param buf_size size of the input buffer to analyse | |||
| */ | |||
| aubio_pitchyin_t *new_aubio_pitchyin (uint_t buf_size); | |||
| /** deletion of the pitch detection object | |||
| \param o pitch detection object as returned by new_aubio_pitchyin() | |||
| */ | |||
| void del_aubio_pitchyin (aubio_pitchyin_t * o); | |||
| /** execute pitch detection an input buffer | |||
| \param o pitch detection object as returned by new_aubio_pitchyin() | |||
| \param samples_in input signal vector (length as specified at creation time) | |||
| \param cands_out pitch period candidates, in samples | |||
| */ | |||
| void aubio_pitchyin_do (aubio_pitchyin_t * o, const fvec_t * samples_in, fvec_t * cands_out); | |||
| /** set tolerance parameter for YIN algorithm | |||
| \param o YIN pitch detection object | |||
| \param tol tolerance parameter for minima selection [default 0.15] | |||
| */ | |||
| uint_t aubio_pitchyin_set_tolerance (aubio_pitchyin_t * o, smpl_t tol); | |||
| /** get tolerance parameter for YIN algorithm | |||
| \param o YIN pitch detection object | |||
| \return tolerance parameter for minima selection [default 0.15] | |||
| */ | |||
| smpl_t aubio_pitchyin_get_tolerance (aubio_pitchyin_t * o); | |||
| /** get current confidence of YIN algorithm | |||
| \param o YIN pitch detection object | |||
| \return confidence parameter | |||
| */ | |||
| smpl_t aubio_pitchyin_get_confidence (aubio_pitchyin_t * o); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_PITCHYIN_H */ | |||
| @@ -0,0 +1,201 @@ | |||
| /* | |||
| Copyright (C) 2003-2017 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /* This algorithm was developed by A. de Cheveigné and H. Kawahara and | |||
| * published in: | |||
| * | |||
| * de Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency | |||
| * estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930. | |||
| * | |||
| * see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "mathutils.h" | |||
| #include "cvec.h" | |||
| #include "spectral/fft.h" | |||
| #include "pitch/pitchyinfast.h" | |||
| struct _aubio_pitchyinfast_t | |||
| { | |||
| fvec_t *yin; | |||
| smpl_t tol; | |||
| uint_t peak_pos; | |||
| fvec_t *tmpdata; | |||
| fvec_t *sqdiff; | |||
| fvec_t *kernel; | |||
| fvec_t *samples_fft; | |||
| fvec_t *kernel_fft; | |||
| aubio_fft_t *fft; | |||
| }; | |||
| aubio_pitchyinfast_t * | |||
| new_aubio_pitchyinfast (uint_t bufsize) | |||
| { | |||
| aubio_pitchyinfast_t *o = AUBIO_NEW (aubio_pitchyinfast_t); | |||
| o->yin = new_fvec (bufsize / 2); | |||
| o->tmpdata = new_fvec (bufsize); | |||
| o->sqdiff = new_fvec (bufsize / 2); | |||
| o->kernel = new_fvec (bufsize); | |||
| o->samples_fft = new_fvec (bufsize); | |||
| o->kernel_fft = new_fvec (bufsize); | |||
| o->fft = new_aubio_fft (bufsize); | |||
| if (!o->yin || !o->tmpdata || !o->tmpdata || !o->sqdiff | |||
| || !o->kernel || !o->samples_fft || !o->kernel || !o->fft) | |||
| { | |||
| del_aubio_pitchyinfast(o); | |||
| return NULL; | |||
| } | |||
| o->tol = 0.15; | |||
| o->peak_pos = 0; | |||
| return o; | |||
| } | |||
| void | |||
| del_aubio_pitchyinfast (aubio_pitchyinfast_t * o) | |||
| { | |||
| if (o->yin) | |||
| del_fvec (o->yin); | |||
| if (o->tmpdata) | |||
| del_fvec (o->tmpdata); | |||
| if (o->sqdiff) | |||
| del_fvec (o->sqdiff); | |||
| if (o->kernel) | |||
| del_fvec (o->kernel); | |||
| if (o->samples_fft) | |||
| del_fvec (o->samples_fft); | |||
| if (o->kernel_fft) | |||
| del_fvec (o->kernel_fft); | |||
| if (o->fft) | |||
| del_aubio_fft (o->fft); | |||
| AUBIO_FREE (o); | |||
| } | |||
| /* all the above in one */ | |||
| void | |||
| aubio_pitchyinfast_do (aubio_pitchyinfast_t * o, const fvec_t * input, fvec_t * out) | |||
| { | |||
| const smpl_t tol = o->tol; | |||
| fvec_t* yin = o->yin; | |||
| const uint_t length = yin->length; | |||
| uint_t B = o->tmpdata->length; | |||
| uint_t W = o->yin->length; // B / 2 | |||
| fvec_t tmp_slice, kernel_ptr; | |||
| uint_t tau; | |||
| sint_t period; | |||
| smpl_t tmp2 = 0.; | |||
| // compute r_t(0) + r_t+tau(0) | |||
| { | |||
| fvec_t *squares = o->tmpdata; | |||
| fvec_weighted_copy(input, input, squares); | |||
| #if 0 | |||
| for (tau = 0; tau < W; tau++) { | |||
| tmp_slice.data = squares->data + tau; | |||
| tmp_slice.length = W; | |||
| o->sqdiff->data[tau] = fvec_sum(&tmp_slice); | |||
| } | |||
| #else | |||
| tmp_slice.data = squares->data; | |||
| tmp_slice.length = W; | |||
| o->sqdiff->data[0] = fvec_sum(&tmp_slice); | |||
| for (tau = 1; tau < W; tau++) { | |||
| o->sqdiff->data[tau] = o->sqdiff->data[tau-1]; | |||
| o->sqdiff->data[tau] -= squares->data[tau-1]; | |||
| o->sqdiff->data[tau] += squares->data[W+tau-1]; | |||
| } | |||
| #endif | |||
| fvec_add(o->sqdiff, o->sqdiff->data[0]); | |||
| } | |||
| // compute r_t(tau) = -2.*ifft(fft(samples)*fft(samples[W-1::-1])) | |||
| { | |||
| fvec_t *compmul = o->tmpdata; | |||
| fvec_t *rt_of_tau = o->samples_fft; | |||
| aubio_fft_do_complex(o->fft, input, o->samples_fft); | |||
| // build kernel, take a copy of first half of samples | |||
| tmp_slice.data = input->data; | |||
| tmp_slice.length = W; | |||
| kernel_ptr.data = o->kernel->data + 1; | |||
| kernel_ptr.length = W; | |||
| fvec_copy(&tmp_slice, &kernel_ptr); | |||
| // reverse them | |||
| fvec_rev(&kernel_ptr); | |||
| // compute fft(kernel) | |||
| aubio_fft_do_complex(o->fft, o->kernel, o->kernel_fft); | |||
| // compute complex product | |||
| compmul->data[0] = o->kernel_fft->data[0] * o->samples_fft->data[0]; | |||
| for (tau = 1; tau < W; tau++) { | |||
| compmul->data[tau] = o->kernel_fft->data[tau] * o->samples_fft->data[tau]; | |||
| compmul->data[tau] -= o->kernel_fft->data[B-tau] * o->samples_fft->data[B-tau]; | |||
| } | |||
| compmul->data[W] = o->kernel_fft->data[W] * o->samples_fft->data[W]; | |||
| for (tau = 1; tau < W; tau++) { | |||
| compmul->data[B-tau] = o->kernel_fft->data[B-tau] * o->samples_fft->data[tau]; | |||
| compmul->data[B-tau] += o->kernel_fft->data[tau] * o->samples_fft->data[B-tau]; | |||
| } | |||
| // compute inverse fft | |||
| aubio_fft_rdo_complex(o->fft, compmul, rt_of_tau); | |||
| // compute square difference r_t(tau) = sqdiff - 2 * r_t_tau[W-1:-1] | |||
| for (tau = 0; tau < W; tau++) { | |||
| yin->data[tau] = o->sqdiff->data[tau] - 2. * rt_of_tau->data[tau+W]; | |||
| } | |||
| } | |||
| // now build yin and look for first minimum | |||
| fvec_zeros(out); | |||
| yin->data[0] = 1.; | |||
| for (tau = 1; tau < length; tau++) { | |||
| tmp2 += yin->data[tau]; | |||
| if (tmp2 != 0) { | |||
| yin->data[tau] *= tau / tmp2; | |||
| } else { | |||
| yin->data[tau] = 1.; | |||
| } | |||
| period = tau - 3; | |||
| if (tau > 4 && (yin->data[period] < tol) && | |||
| (yin->data[period] < yin->data[period + 1])) { | |||
| o->peak_pos = (uint_t)period; | |||
| out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos); | |||
| return; | |||
| } | |||
| } | |||
| // use global minimum | |||
| o->peak_pos = (uint_t)fvec_min_elem (yin); | |||
| out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos); | |||
| } | |||
| smpl_t | |||
| aubio_pitchyinfast_get_confidence (aubio_pitchyinfast_t * o) { | |||
| return 1. - o->yin->data[o->peak_pos]; | |||
| } | |||
| uint_t | |||
| aubio_pitchyinfast_set_tolerance (aubio_pitchyinfast_t * o, smpl_t tol) | |||
| { | |||
| o->tol = tol; | |||
| return 0; | |||
| } | |||
| smpl_t | |||
| aubio_pitchyinfast_get_tolerance (aubio_pitchyinfast_t * o) | |||
| { | |||
| return o->tol; | |||
| } | |||
| @@ -0,0 +1,102 @@ | |||
| /* | |||
| Copyright (C) 2003-2017 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** \file | |||
| Pitch detection using YIN algorithm (fast implementation) | |||
| This algorithm was developed by A. de Cheveigne and H. Kawahara and | |||
| published in: | |||
| De Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency | |||
| estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930. | |||
| This implementation compute the autocorrelation function using time domain | |||
| convolution computed in the spectral domain. | |||
| see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html | |||
| http://recherche.ircam.fr/equipes/pcm/cheveign/ps/2002_JASA_YIN_proof.pdf | |||
| */ | |||
| #ifndef AUBIO_PITCHYINFAST_H | |||
| #define AUBIO_PITCHYINFAST_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** pitch detection object */ | |||
| typedef struct _aubio_pitchyinfast_t aubio_pitchyinfast_t; | |||
| /** creation of the pitch detection object | |||
| \param buf_size size of the input buffer to analyse | |||
| */ | |||
| aubio_pitchyinfast_t *new_aubio_pitchyinfast (uint_t buf_size); | |||
| /** deletion of the pitch detection object | |||
| \param o pitch detection object as returned by new_aubio_pitchyin() | |||
| */ | |||
| void del_aubio_pitchyinfast (aubio_pitchyinfast_t * o); | |||
| /** execute pitch detection an input buffer | |||
| \param o pitch detection object as returned by new_aubio_pitchyin() | |||
| \param samples_in input signal vector (length as specified at creation time) | |||
| \param cands_out pitch period candidates, in samples | |||
| */ | |||
| void aubio_pitchyinfast_do (aubio_pitchyinfast_t * o, const fvec_t * samples_in, fvec_t * cands_out); | |||
| /** set tolerance parameter for YIN algorithm | |||
| \param o YIN pitch detection object | |||
| \param tol tolerance parameter for minima selection [default 0.15] | |||
| */ | |||
| uint_t aubio_pitchyinfast_set_tolerance (aubio_pitchyinfast_t * o, smpl_t tol); | |||
| /** get tolerance parameter for YIN algorithm | |||
| \param o YIN pitch detection object | |||
| \return tolerance parameter for minima selection [default 0.15] | |||
| */ | |||
| smpl_t aubio_pitchyinfast_get_tolerance (aubio_pitchyinfast_t * o); | |||
| /** get current confidence of YIN algorithm | |||
| \param o YIN pitch detection object | |||
| \return confidence parameter | |||
| */ | |||
| smpl_t aubio_pitchyinfast_get_confidence (aubio_pitchyinfast_t * o); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_PITCHYINFAST_H */ | |||
| @@ -0,0 +1,208 @@ | |||
| /* | |||
| Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "cvec.h" | |||
| #include "mathutils.h" | |||
| #include "spectral/fft.h" | |||
| #include "pitch/pitchyinfft.h" | |||
| /** pitch yinfft structure */ | |||
| struct _aubio_pitchyinfft_t | |||
| { | |||
| fvec_t *win; /**< temporal weighting window */ | |||
| fvec_t *winput; /**< windowed spectrum */ | |||
| fvec_t *sqrmag; /**< square difference function */ | |||
| fvec_t *weight; /**< spectral weighting window (psychoacoustic model) */ | |||
| fvec_t *fftout; /**< Fourier transform output */ | |||
| aubio_fft_t *fft; /**< fft object to compute square difference function */ | |||
| fvec_t *yinfft; /**< Yin function */ | |||
| smpl_t tol; /**< Yin tolerance */ | |||
| uint_t peak_pos; /**< currently selected peak pos*/ | |||
| uint_t short_period; /** shortest period under which to check for octave error */ | |||
| }; | |||
| static const smpl_t freqs[] = { | |||
| 0., 20., 25., 31.5, 40., 50., 63., 80., 100., 125., | |||
| 160., 200., 250., 315., 400., 500., 630., 800., 1000., 1250., | |||
| 1600., 2000., 2500., 3150., 4000., 5000., 6300., 8000., 9000., 10000., | |||
| 12500., 15000., 20000., 25100., -1. | |||
| }; | |||
| static const smpl_t weight[] = { | |||
| -75.8, -70.1, -60.8, -52.1, -44.2, -37.5, -31.3, -25.6, -20.9, -16.5, | |||
| -12.6, -9.60, -7.00, -4.70, -3.00, -1.80, -0.80, -0.20, -0.00, 0.50, | |||
| 1.60, 3.20, 5.40, 7.80, 8.10, 5.30, -2.40, -11.1, -12.8, -12.2, | |||
| -7.40, -17.8, -17.8, -17.8 | |||
| }; | |||
| aubio_pitchyinfft_t * | |||
| new_aubio_pitchyinfft (uint_t samplerate, uint_t bufsize) | |||
| { | |||
| uint_t i = 0, j = 1; | |||
| smpl_t freq = 0, a0 = 0, a1 = 0, f0 = 0, f1 = 0; | |||
| aubio_pitchyinfft_t *p = AUBIO_NEW (aubio_pitchyinfft_t); | |||
| p->winput = new_fvec (bufsize); | |||
| p->fft = new_aubio_fft (bufsize); | |||
| if (!p->fft) goto beach; | |||
| p->fftout = new_fvec (bufsize); | |||
| p->sqrmag = new_fvec (bufsize); | |||
| p->yinfft = new_fvec (bufsize / 2 + 1); | |||
| p->tol = 0.85; | |||
| p->peak_pos = 0; | |||
| p->win = new_aubio_window ("hanningz", bufsize); | |||
| p->weight = new_fvec (bufsize / 2 + 1); | |||
| for (i = 0; i < p->weight->length; i++) { | |||
| freq = (smpl_t) i / (smpl_t) bufsize *(smpl_t) samplerate; | |||
| while (freq > freqs[j] && freqs[j] > 0) { | |||
| //AUBIO_DBG("freq %3.5f > %3.5f \tsamplerate %d (Hz) \t" | |||
| // "(weight length %d, bufsize %d) %d %d\n", freq, freqs[j], | |||
| // samplerate, p->weight->length, bufsize, i, j); | |||
| j += 1; | |||
| } | |||
| a0 = weight[j - 1]; | |||
| f0 = freqs[j - 1]; | |||
| a1 = weight[j]; | |||
| f1 = freqs[j]; | |||
| if (f0 == f1) { // just in case | |||
| p->weight->data[i] = a0; | |||
| } else if (f0 == 0) { // y = ax+b | |||
| p->weight->data[i] = (a1 - a0) / f1 * freq + a0; | |||
| } else { | |||
| p->weight->data[i] = (a1 - a0) / (f1 - f0) * freq + | |||
| (a0 - (a1 - a0) / (f1 / f0 - 1.)); | |||
| } | |||
| while (freq > freqs[j]) { | |||
| j += 1; | |||
| } | |||
| //AUBIO_DBG("%f\n",p->weight->data[i]); | |||
| p->weight->data[i] = DB2LIN (p->weight->data[i]); | |||
| //p->weight->data[i] = SQRT(DB2LIN(p->weight->data[i])); | |||
| } | |||
| // check for octave errors above 1300 Hz | |||
| p->short_period = (uint_t)ROUND(samplerate / 1300.); | |||
| return p; | |||
| beach: | |||
| if (p->winput) del_fvec(p->winput); | |||
| AUBIO_FREE(p); | |||
| return NULL; | |||
| } | |||
| void | |||
| aubio_pitchyinfft_do (aubio_pitchyinfft_t * p, const fvec_t * input, fvec_t * output) | |||
| { | |||
| uint_t tau, l; | |||
| uint_t length = p->fftout->length; | |||
| uint_t halfperiod; | |||
| fvec_t *fftout = p->fftout; | |||
| fvec_t *yin = p->yinfft; | |||
| smpl_t tmp = 0., sum = 0.; | |||
| // window the input | |||
| fvec_weighted_copy(input, p->win, p->winput); | |||
| // get the real / imag parts of its fft | |||
| aubio_fft_do_complex (p->fft, p->winput, fftout); | |||
| // get the squared magnitude spectrum, applying some weight | |||
| p->sqrmag->data[0] = SQR(fftout->data[0]); | |||
| p->sqrmag->data[0] *= p->weight->data[0]; | |||
| for (l = 1; l < length / 2; l++) { | |||
| p->sqrmag->data[l] = SQR(fftout->data[l]) + SQR(fftout->data[length - l]); | |||
| p->sqrmag->data[l] *= p->weight->data[l]; | |||
| p->sqrmag->data[length - l] = p->sqrmag->data[l]; | |||
| } | |||
| p->sqrmag->data[length / 2] = SQR(fftout->data[length / 2]); | |||
| p->sqrmag->data[length / 2] *= p->weight->data[length / 2]; | |||
| // get sum of weighted squared mags | |||
| for (l = 0; l < length / 2 + 1; l++) { | |||
| sum += p->sqrmag->data[l]; | |||
| } | |||
| sum *= 2.; | |||
| // get the real / imag parts of the fft of the squared magnitude | |||
| aubio_fft_do_complex (p->fft, p->sqrmag, fftout); | |||
| yin->data[0] = 1.; | |||
| for (tau = 1; tau < yin->length; tau++) { | |||
| // compute the square differences | |||
| yin->data[tau] = sum - fftout->data[tau]; | |||
| // and the cumulative mean normalized difference function | |||
| tmp += yin->data[tau]; | |||
| if (tmp != 0) { | |||
| yin->data[tau] *= tau / tmp; | |||
| } else { | |||
| yin->data[tau] = 1.; | |||
| } | |||
| } | |||
| // find best candidates | |||
| tau = fvec_min_elem (yin); | |||
| if (yin->data[tau] < p->tol) { | |||
| // no interpolation, directly return the period as an integer | |||
| //output->data[0] = tau; | |||
| //return; | |||
| // 3 point quadratic interpolation | |||
| //return fvec_quadratic_peak_pos (yin,tau,1); | |||
| /* additional check for (unlikely) octave doubling in higher frequencies */ | |||
| if (tau > p->short_period) { | |||
| output->data[0] = fvec_quadratic_peak_pos (yin, tau); | |||
| } else { | |||
| /* should compare the minimum value of each interpolated peaks */ | |||
| halfperiod = FLOOR (tau / 2 + .5); | |||
| if (yin->data[halfperiod] < p->tol) | |||
| p->peak_pos = halfperiod; | |||
| else | |||
| p->peak_pos = tau; | |||
| output->data[0] = fvec_quadratic_peak_pos (yin, p->peak_pos); | |||
| } | |||
| } else { | |||
| p->peak_pos = 0; | |||
| output->data[0] = 0.; | |||
| } | |||
| } | |||
| void | |||
| del_aubio_pitchyinfft (aubio_pitchyinfft_t * p) | |||
| { | |||
| del_fvec (p->win); | |||
| del_aubio_fft (p->fft); | |||
| del_fvec (p->yinfft); | |||
| del_fvec (p->sqrmag); | |||
| del_fvec (p->fftout); | |||
| del_fvec (p->winput); | |||
| del_fvec (p->weight); | |||
| AUBIO_FREE (p); | |||
| } | |||
| smpl_t | |||
| aubio_pitchyinfft_get_confidence (aubio_pitchyinfft_t * o) { | |||
| return 1. - o->yinfft->data[o->peak_pos]; | |||
| } | |||
| uint_t | |||
| aubio_pitchyinfft_set_tolerance (aubio_pitchyinfft_t * p, smpl_t tol) | |||
| { | |||
| p->tol = tol; | |||
| return 0; | |||
| } | |||
| smpl_t | |||
| aubio_pitchyinfft_get_tolerance (aubio_pitchyinfft_t * p) | |||
| { | |||
| return p->tol; | |||
| } | |||
| @@ -0,0 +1,99 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** \file | |||
| Pitch detection using a spectral implementation of the YIN algorithm | |||
| This algorithm was derived from the YIN algorithm. In this implementation, a | |||
| Fourier transform is used to compute a tapered square difference function, | |||
| which allows spectral weighting. Because the difference function is tapered, | |||
| the selection of the period is simplified. | |||
| Paul Brossier, [Automatic annotation of musical audio for interactive | |||
| systems](http://aubio.org/phd/), Chapter 3, Pitch Analysis, PhD thesis, | |||
| Centre for Digital music, Queen Mary University of London, London, UK, 2006. | |||
| \example pitch/test-pitchyinfft.c | |||
| */ | |||
| #ifndef AUBIO_PITCHYINFFT_H | |||
| #define AUBIO_PITCHYINFFT_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** pitch detection object */ | |||
| typedef struct _aubio_pitchyinfft_t aubio_pitchyinfft_t; | |||
| /** execute pitch detection on an input buffer | |||
| \param o pitch detection object as returned by new_aubio_pitchyinfft | |||
| \param samples_in input signal vector (length as specified at creation time) | |||
| \param cands_out pitch period candidates, in samples | |||
| */ | |||
| void aubio_pitchyinfft_do (aubio_pitchyinfft_t * o, const fvec_t * samples_in, fvec_t * cands_out); | |||
| /** creation of the pitch detection object | |||
| \param samplerate samplerate of the input signal | |||
| \param buf_size size of the input buffer to analyse | |||
| */ | |||
| aubio_pitchyinfft_t *new_aubio_pitchyinfft (uint_t samplerate, uint_t buf_size); | |||
| /** deletion of the pitch detection object | |||
| \param o pitch detection object as returned by new_aubio_pitchyinfft() | |||
| */ | |||
| void del_aubio_pitchyinfft (aubio_pitchyinfft_t * o); | |||
| /** get tolerance parameter for YIN algorithm | |||
| \param o YIN pitch detection object | |||
| \return tolerance parameter for minima selection [default 0.15] | |||
| */ | |||
| smpl_t aubio_pitchyinfft_get_tolerance (aubio_pitchyinfft_t * o); | |||
| /** set tolerance parameter for YIN algorithm | |||
| \param o YIN pitch detection object | |||
| \param tol tolerance parameter for minima selection [default 0.15] | |||
| */ | |||
| uint_t aubio_pitchyinfft_set_tolerance (aubio_pitchyinfft_t * o, smpl_t tol); | |||
| /** get current confidence of YIN algorithm | |||
| \param o YIN pitch detection object | |||
| \return confidence parameter | |||
| */ | |||
| smpl_t aubio_pitchyinfft_get_confidence (aubio_pitchyinfft_t * o); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_PITCHYINFFT_H */ | |||
| @@ -0,0 +1,582 @@ | |||
| /* | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "cvec.h" | |||
| #include "mathutils.h" | |||
| #include "spectral/fft.h" | |||
| #ifdef HAVE_FFTW3 // using FFTW3 | |||
| /* note that <complex.h> is not included here but only in aubio_priv.h, so that | |||
| * c++ projects can still use their own complex definition. */ | |||
| #include <fftw3.h> | |||
| #include <pthread.h> | |||
| #ifdef HAVE_COMPLEX_H | |||
| #ifdef HAVE_FFTW3F | |||
| /** fft data type with complex.h and fftw3f */ | |||
| #define FFTW_TYPE fftwf_complex | |||
| #else | |||
| /** fft data type with complex.h and fftw3 */ | |||
| #define FFTW_TYPE fftw_complex | |||
| #endif | |||
| #else | |||
| #ifdef HAVE_FFTW3F | |||
| /** fft data type without complex.h and with fftw3f */ | |||
| #define FFTW_TYPE float | |||
| #else | |||
| /** fft data type without complex.h and with fftw */ | |||
| #define FFTW_TYPE double | |||
| #endif | |||
| #endif | |||
| /** fft data type */ | |||
| typedef FFTW_TYPE fft_data_t; | |||
| #ifdef HAVE_FFTW3F | |||
| #define fftw_malloc fftwf_malloc | |||
| #define fftw_free fftwf_free | |||
| #define fftw_execute fftwf_execute | |||
| #define fftw_plan_dft_r2c_1d fftwf_plan_dft_r2c_1d | |||
| #define fftw_plan_dft_c2r_1d fftwf_plan_dft_c2r_1d | |||
| #define fftw_plan_r2r_1d fftwf_plan_r2r_1d | |||
| #define fftw_plan fftwf_plan | |||
| #define fftw_destroy_plan fftwf_destroy_plan | |||
| #endif | |||
| #ifdef HAVE_FFTW3F | |||
| #if HAVE_AUBIO_DOUBLE | |||
| #error "Using aubio in double precision with fftw3 in single precision" | |||
| #endif /* HAVE_AUBIO_DOUBLE */ | |||
| #define real_t float | |||
| #elif defined (HAVE_FFTW3) /* HAVE_FFTW3F */ | |||
| #if !HAVE_AUBIO_DOUBLE | |||
| #error "Using aubio in single precision with fftw3 in double precision" | |||
| #endif /* HAVE_AUBIO_DOUBLE */ | |||
| #define real_t double | |||
| #endif /* HAVE_FFTW3F */ | |||
| #ifndef __MOD_DEVICES__ | |||
| // a global mutex for FFTW thread safety | |||
| pthread_mutex_t aubio_fftw_mutex = PTHREAD_MUTEX_INITIALIZER; | |||
| #endif | |||
| #elif defined HAVE_ACCELERATE // using ACCELERATE | |||
| // https://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/reference.html | |||
| #include <Accelerate/Accelerate.h> | |||
| #if !HAVE_AUBIO_DOUBLE | |||
| #define aubio_vDSP_ctoz vDSP_ctoz | |||
| #define aubio_vDSP_fft_zrip vDSP_fft_zrip | |||
| #define aubio_vDSP_ztoc vDSP_ztoc | |||
| #define aubio_vDSP_zvmags vDSP_zvmags | |||
| #define aubio_vDSP_zvphas vDSP_zvphas | |||
| #define aubio_vDSP_vsadd vDSP_vsadd | |||
| #define aubio_vDSP_vsmul vDSP_vsmul | |||
| #define aubio_DSPComplex DSPComplex | |||
| #define aubio_DSPSplitComplex DSPSplitComplex | |||
| #define aubio_vDSP_DFT_Setup vDSP_DFT_Setup | |||
| #define aubio_vDSP_DFT_zrop_CreateSetup vDSP_DFT_zrop_CreateSetup | |||
| #define aubio_vDSP_DFT_Execute vDSP_DFT_Execute | |||
| #define aubio_vDSP_DFT_DestroySetup vDSP_DFT_DestroySetup | |||
| #define aubio_vvsqrt vvsqrtf | |||
| #else | |||
| #define aubio_vDSP_ctoz vDSP_ctozD | |||
| #define aubio_vDSP_fft_zrip vDSP_fft_zripD | |||
| #define aubio_vDSP_ztoc vDSP_ztocD | |||
| #define aubio_vDSP_zvmags vDSP_zvmagsD | |||
| #define aubio_vDSP_zvphas vDSP_zvphasD | |||
| #define aubio_vDSP_vsadd vDSP_vsaddD | |||
| #define aubio_vDSP_vsmul vDSP_vsmulD | |||
| #define aubio_DSPComplex DSPDoubleComplex | |||
| #define aubio_DSPSplitComplex DSPDoubleSplitComplex | |||
| #define aubio_vDSP_DFT_Setup vDSP_DFT_SetupD | |||
| #define aubio_vDSP_DFT_zrop_CreateSetup vDSP_DFT_zrop_CreateSetupD | |||
| #define aubio_vDSP_DFT_Execute vDSP_DFT_ExecuteD | |||
| #define aubio_vDSP_DFT_DestroySetup vDSP_DFT_DestroySetupD | |||
| #define aubio_vvsqrt vvsqrt | |||
| #endif /* HAVE_AUBIO_DOUBLE */ | |||
| #elif defined HAVE_INTEL_IPP // using INTEL IPP | |||
| #if !HAVE_AUBIO_DOUBLE | |||
| #define aubio_IppFloat Ipp32f | |||
| #define aubio_IppComplex Ipp32fc | |||
| #define aubio_FFTSpec FFTSpec_R_32f | |||
| #define aubio_ippsMalloc_complex ippsMalloc_32fc | |||
| #define aubio_ippsFFTInit_R ippsFFTInit_R_32f | |||
| #define aubio_ippsFFTGetSize_R ippsFFTGetSize_R_32f | |||
| #define aubio_ippsFFTInv_CCSToR ippsFFTInv_CCSToR_32f | |||
| #define aubio_ippsFFTFwd_RToCCS ippsFFTFwd_RToCCS_32f | |||
| #define aubio_ippsAtan2 ippsAtan2_32f_A21 | |||
| #else /* HAVE_AUBIO_DOUBLE */ | |||
| #define aubio_IppFloat Ipp64f | |||
| #define aubio_IppComplex Ipp64fc | |||
| #define aubio_FFTSpec FFTSpec_R_64f | |||
| #define aubio_ippsMalloc_complex ippsMalloc_64fc | |||
| #define aubio_ippsFFTInit_R ippsFFTInit_R_64f | |||
| #define aubio_ippsFFTGetSize_R ippsFFTGetSize_R_64f | |||
| #define aubio_ippsFFTInv_CCSToR ippsFFTInv_CCSToR_64f | |||
| #define aubio_ippsFFTFwd_RToCCS ippsFFTFwd_RToCCS_64f | |||
| #define aubio_ippsAtan2 ippsAtan2_64f_A50 | |||
| #endif | |||
| #else // using OOURA | |||
| // let's use ooura instead | |||
| extern void aubio_ooura_rdft(int, int, smpl_t *, int *, smpl_t *); | |||
| #endif | |||
| struct _aubio_fft_t { | |||
| uint_t winsize; | |||
| uint_t fft_size; | |||
| #ifdef HAVE_FFTW3 // using FFTW3 | |||
| real_t *in, *out; | |||
| fftw_plan pfw, pbw; | |||
| fft_data_t * specdata; /* complex spectral data */ | |||
| #elif defined HAVE_ACCELERATE // using ACCELERATE | |||
| aubio_vDSP_DFT_Setup fftSetupFwd; | |||
| aubio_vDSP_DFT_Setup fftSetupBwd; | |||
| aubio_DSPSplitComplex spec; | |||
| smpl_t *in, *out; | |||
| #elif defined HAVE_INTEL_IPP // using Intel IPP | |||
| smpl_t *in, *out; | |||
| Ipp8u* memSpec; | |||
| Ipp8u* memInit; | |||
| Ipp8u* memBuffer; | |||
| struct aubio_FFTSpec* fftSpec; | |||
| aubio_IppComplex* complexOut; | |||
| #else // using OOURA | |||
| smpl_t *in, *out; | |||
| smpl_t *w; | |||
| int *ip; | |||
| #endif /* using OOURA */ | |||
| fvec_t * compspec; | |||
| }; | |||
| aubio_fft_t * new_aubio_fft (uint_t winsize) { | |||
| aubio_fft_t * s = AUBIO_NEW(aubio_fft_t); | |||
| if ((sint_t)winsize < 2) { | |||
| AUBIO_ERR("fft: got winsize %d, but can not be < 2\n", winsize); | |||
| goto beach; | |||
| } | |||
| #ifdef HAVE_FFTW3 | |||
| uint_t i; | |||
| s->winsize = winsize; | |||
| /* allocate memory */ | |||
| s->in = AUBIO_ARRAY(real_t,winsize); | |||
| s->out = AUBIO_ARRAY(real_t,winsize); | |||
| s->compspec = new_fvec(winsize); | |||
| /* create plans */ | |||
| #ifndef __MOD_DEVICES__ | |||
| pthread_mutex_lock(&aubio_fftw_mutex); | |||
| #endif | |||
| #ifdef HAVE_COMPLEX_H | |||
| s->fft_size = winsize/2 + 1; | |||
| s->specdata = (fft_data_t*)fftw_malloc(sizeof(fft_data_t)*s->fft_size); | |||
| s->pfw = fftw_plan_dft_r2c_1d(winsize, s->in, s->specdata, FFTW_ESTIMATE); | |||
| s->pbw = fftw_plan_dft_c2r_1d(winsize, s->specdata, s->out, FFTW_ESTIMATE); | |||
| #else | |||
| s->fft_size = winsize; | |||
| s->specdata = (fft_data_t*)fftw_malloc(sizeof(fft_data_t)*s->fft_size); | |||
| s->pfw = fftw_plan_r2r_1d(winsize, s->in, s->specdata, FFTW_R2HC, FFTW_ESTIMATE); | |||
| s->pbw = fftw_plan_r2r_1d(winsize, s->specdata, s->out, FFTW_HC2R, FFTW_ESTIMATE); | |||
| #endif | |||
| #ifndef __MOD_DEVICES__ | |||
| pthread_mutex_unlock(&aubio_fftw_mutex); | |||
| #endif | |||
| for (i = 0; i < s->winsize; i++) { | |||
| s->in[i] = 0.; | |||
| s->out[i] = 0.; | |||
| } | |||
| for (i = 0; i < s->fft_size; i++) { | |||
| s->specdata[i] = 0.; | |||
| } | |||
| #elif defined HAVE_ACCELERATE // using ACCELERATE | |||
| { | |||
| uint_t radix = winsize; | |||
| uint_t order = 0; | |||
| while ((radix / 2) * 2 == radix) { | |||
| radix /= 2; | |||
| order++; | |||
| } | |||
| if (order < 4 || (radix != 1 && radix != 3 && radix != 5 && radix != 15)) { | |||
| AUBIO_ERR("fft: vDSP/Accelerate supports FFT with sizes = " | |||
| "f * 2 ** n, where n > 4 and f in [1, 3, 5, 15], but requested %d. " | |||
| "Use the closest power of two, or try recompiling aubio with " | |||
| "--enable-fftw3.\n", winsize); | |||
| goto beach; | |||
| } | |||
| } | |||
| s->winsize = winsize; | |||
| s->fft_size = winsize; | |||
| s->compspec = new_fvec(winsize); | |||
| s->in = AUBIO_ARRAY(smpl_t, s->fft_size); | |||
| s->out = AUBIO_ARRAY(smpl_t, s->fft_size); | |||
| s->spec.realp = AUBIO_ARRAY(smpl_t, s->fft_size/2); | |||
| s->spec.imagp = AUBIO_ARRAY(smpl_t, s->fft_size/2); | |||
| s->fftSetupFwd = aubio_vDSP_DFT_zrop_CreateSetup(NULL, | |||
| s->fft_size, vDSP_DFT_FORWARD); | |||
| s->fftSetupBwd = aubio_vDSP_DFT_zrop_CreateSetup(s->fftSetupFwd, | |||
| s->fft_size, vDSP_DFT_INVERSE); | |||
| #elif defined HAVE_INTEL_IPP // using Intel IPP | |||
| const IppHintAlgorithm qualityHint = ippAlgHintAccurate; // OR ippAlgHintFast; | |||
| const int flags = IPP_FFT_NODIV_BY_ANY; // we're scaling manually afterwards | |||
| int order = aubio_power_of_two_order(winsize); | |||
| int sizeSpec, sizeInit, sizeBuffer; | |||
| IppStatus status; | |||
| if (winsize <= 4 || aubio_is_power_of_two(winsize) != 1) | |||
| { | |||
| AUBIO_ERR("intel IPP fft: can only create with sizes > 4 and power of two, requested %d," | |||
| " try recompiling aubio with --enable-fftw3\n", winsize); | |||
| goto beach; | |||
| } | |||
| status = aubio_ippsFFTGetSize_R(order, flags, qualityHint, | |||
| &sizeSpec, &sizeInit, &sizeBuffer); | |||
| if (status != ippStsNoErr) { | |||
| AUBIO_ERR("fft: failed to initialize fft. IPP error: %d\n", status); | |||
| goto beach; | |||
| } | |||
| s->fft_size = s->winsize = winsize; | |||
| s->compspec = new_fvec(winsize); | |||
| s->in = AUBIO_ARRAY(smpl_t, s->winsize); | |||
| s->out = AUBIO_ARRAY(smpl_t, s->winsize); | |||
| s->memSpec = ippsMalloc_8u(sizeSpec); | |||
| s->memBuffer = ippsMalloc_8u(sizeBuffer); | |||
| if (sizeInit > 0 ) { | |||
| s->memInit = ippsMalloc_8u(sizeInit); | |||
| } | |||
| s->complexOut = aubio_ippsMalloc_complex(s->fft_size / 2 + 1); | |||
| status = aubio_ippsFFTInit_R( | |||
| &s->fftSpec, order, flags, qualityHint, s->memSpec, s->memInit); | |||
| if (status != ippStsNoErr) { | |||
| AUBIO_ERR("fft: failed to initialize. IPP error: %d\n", status); | |||
| goto beach; | |||
| } | |||
| #else // using OOURA | |||
| if (aubio_is_power_of_two(winsize) != 1) { | |||
| AUBIO_ERR("fft: can only create with sizes power of two, requested %d," | |||
| " try recompiling aubio with --enable-fftw3\n", winsize); | |||
| goto beach; | |||
| } | |||
| s->winsize = winsize; | |||
| s->fft_size = winsize / 2 + 1; | |||
| s->compspec = new_fvec(winsize); | |||
| s->in = AUBIO_ARRAY(smpl_t, s->winsize); | |||
| s->out = AUBIO_ARRAY(smpl_t, s->winsize); | |||
| s->ip = AUBIO_ARRAY(int , s->fft_size); | |||
| s->w = AUBIO_ARRAY(smpl_t, s->fft_size); | |||
| s->ip[0] = 0; | |||
| #endif /* using OOURA */ | |||
| return s; | |||
| beach: | |||
| AUBIO_FREE(s); | |||
| return NULL; | |||
| } | |||
| void del_aubio_fft(aubio_fft_t * s) { | |||
| /* destroy data */ | |||
| #ifdef HAVE_FFTW3 // using FFTW3 | |||
| #ifndef __MOD_DEVICES__ | |||
| pthread_mutex_lock(&aubio_fftw_mutex); | |||
| #endif | |||
| fftw_destroy_plan(s->pfw); | |||
| fftw_destroy_plan(s->pbw); | |||
| fftw_free(s->specdata); | |||
| #ifndef __MOD_DEVICES__ | |||
| pthread_mutex_unlock(&aubio_fftw_mutex); | |||
| #endif | |||
| #elif defined HAVE_ACCELERATE // using ACCELERATE | |||
| AUBIO_FREE(s->spec.realp); | |||
| AUBIO_FREE(s->spec.imagp); | |||
| aubio_vDSP_DFT_DestroySetup(s->fftSetupBwd); | |||
| aubio_vDSP_DFT_DestroySetup(s->fftSetupFwd); | |||
| #elif defined HAVE_INTEL_IPP // using Intel IPP | |||
| ippFree(s->memSpec); | |||
| ippFree(s->memInit); | |||
| ippFree(s->memBuffer); | |||
| ippFree(s->complexOut); | |||
| #else // using OOURA | |||
| AUBIO_FREE(s->w); | |||
| AUBIO_FREE(s->ip); | |||
| #endif | |||
| del_fvec(s->compspec); | |||
| AUBIO_FREE(s->in); | |||
| AUBIO_FREE(s->out); | |||
| AUBIO_FREE(s); | |||
| } | |||
| void aubio_fft_do(aubio_fft_t * s, const fvec_t * input, cvec_t * spectrum) { | |||
| aubio_fft_do_complex(s, input, s->compspec); | |||
| aubio_fft_get_spectrum(s->compspec, spectrum); | |||
| } | |||
| void aubio_fft_rdo(aubio_fft_t * s, const cvec_t * spectrum, fvec_t * output) { | |||
| aubio_fft_get_realimag(spectrum, s->compspec); | |||
| aubio_fft_rdo_complex(s, s->compspec, output); | |||
| } | |||
| void aubio_fft_do_complex(aubio_fft_t * s, const fvec_t * input, fvec_t * compspec) { | |||
| uint_t i; | |||
| #ifndef HAVE_MEMCPY_HACKS | |||
| for (i=0; i < s->winsize; i++) { | |||
| s->in[i] = input->data[i]; | |||
| } | |||
| #else | |||
| memcpy(s->in, input->data, s->winsize * sizeof(smpl_t)); | |||
| #endif /* HAVE_MEMCPY_HACKS */ | |||
| #ifdef HAVE_FFTW3 // using FFTW3 | |||
| fftw_execute(s->pfw); | |||
| #ifdef HAVE_COMPLEX_H | |||
| compspec->data[0] = REAL(s->specdata[0]); | |||
| for (i = 1; i < s->fft_size -1 ; i++) { | |||
| compspec->data[i] = REAL(s->specdata[i]); | |||
| compspec->data[compspec->length - i] = IMAG(s->specdata[i]); | |||
| } | |||
| compspec->data[s->fft_size-1] = REAL(s->specdata[s->fft_size-1]); | |||
| #else /* HAVE_COMPLEX_H */ | |||
| for (i = 0; i < s->fft_size; i++) { | |||
| compspec->data[i] = s->specdata[i]; | |||
| } | |||
| #endif /* HAVE_COMPLEX_H */ | |||
| #elif defined HAVE_ACCELERATE // using ACCELERATE | |||
| // convert real data to even/odd format used in vDSP | |||
| aubio_vDSP_ctoz((aubio_DSPComplex*)s->in, 2, &s->spec, 1, s->fft_size/2); | |||
| // compute the FFT | |||
| aubio_vDSP_DFT_Execute(s->fftSetupFwd, s->spec.realp, s->spec.imagp, | |||
| s->spec.realp, s->spec.imagp); | |||
| // convert from vDSP complex split to [ r0, r1, ..., rN, iN-1, .., i2, i1] | |||
| compspec->data[0] = s->spec.realp[0]; | |||
| compspec->data[s->fft_size / 2] = s->spec.imagp[0]; | |||
| for (i = 1; i < s->fft_size / 2; i++) { | |||
| compspec->data[i] = s->spec.realp[i]; | |||
| compspec->data[s->fft_size - i] = s->spec.imagp[i]; | |||
| } | |||
| // apply scaling | |||
| smpl_t scale = 1./2.; | |||
| aubio_vDSP_vsmul(compspec->data, 1, &scale, compspec->data, 1, s->fft_size); | |||
| #elif defined HAVE_INTEL_IPP // using Intel IPP | |||
| // apply fft | |||
| aubio_ippsFFTFwd_RToCCS(s->in, (aubio_IppFloat*)s->complexOut, s->fftSpec, s->memBuffer); | |||
| // convert complex buffer to [ r0, r1, ..., rN, iN-1, .., i2, i1] | |||
| compspec->data[0] = s->complexOut[0].re; | |||
| compspec->data[s->fft_size / 2] = s->complexOut[s->fft_size / 2].re; | |||
| for (i = 1; i < s->fft_size / 2; i++) { | |||
| compspec->data[i] = s->complexOut[i].re; | |||
| compspec->data[s->fft_size - i] = s->complexOut[i].im; | |||
| } | |||
| #else // using OOURA | |||
| aubio_ooura_rdft(s->winsize, 1, s->in, s->ip, s->w); | |||
| compspec->data[0] = s->in[0]; | |||
| compspec->data[s->winsize / 2] = s->in[1]; | |||
| for (i = 1; i < s->fft_size - 1; i++) { | |||
| compspec->data[i] = s->in[2 * i]; | |||
| compspec->data[s->winsize - i] = - s->in[2 * i + 1]; | |||
| } | |||
| #endif /* using OOURA */ | |||
| } | |||
| void aubio_fft_rdo_complex(aubio_fft_t * s, const fvec_t * compspec, fvec_t * output) { | |||
| uint_t i; | |||
| #ifdef HAVE_FFTW3 | |||
| const smpl_t renorm = 1./(smpl_t)s->winsize; | |||
| #ifdef HAVE_COMPLEX_H | |||
| s->specdata[0] = compspec->data[0]; | |||
| for (i=1; i < s->fft_size - 1; i++) { | |||
| s->specdata[i] = compspec->data[i] + | |||
| I * compspec->data[compspec->length - i]; | |||
| } | |||
| s->specdata[s->fft_size - 1] = compspec->data[s->fft_size - 1]; | |||
| #else | |||
| for (i=0; i < s->fft_size; i++) { | |||
| s->specdata[i] = compspec->data[i]; | |||
| } | |||
| #endif | |||
| fftw_execute(s->pbw); | |||
| for (i = 0; i < output->length; i++) { | |||
| output->data[i] = s->out[i]*renorm; | |||
| } | |||
| #elif defined HAVE_ACCELERATE // using ACCELERATE | |||
| // convert from real imag [ r0, r1, ..., rN, iN-1, .., i2, i1] | |||
| // to vDSP packed format [ r0, rN, r1, i1, ..., rN-1, iN-1 ] | |||
| s->out[0] = compspec->data[0]; | |||
| s->out[1] = compspec->data[s->winsize / 2]; | |||
| for (i = 1; i < s->fft_size / 2; i++) { | |||
| s->out[2 * i] = compspec->data[i]; | |||
| s->out[2 * i + 1] = compspec->data[s->winsize - i]; | |||
| } | |||
| // convert to split complex format used in vDSP | |||
| aubio_vDSP_ctoz((aubio_DSPComplex*)s->out, 2, &s->spec, 1, s->fft_size/2); | |||
| // compute the FFT | |||
| aubio_vDSP_DFT_Execute(s->fftSetupBwd, s->spec.realp, s->spec.imagp, | |||
| s->spec.realp, s->spec.imagp); | |||
| // convert result to real output | |||
| aubio_vDSP_ztoc(&s->spec, 1, (aubio_DSPComplex*)output->data, 2, s->fft_size/2); | |||
| // apply scaling | |||
| smpl_t scale = 1.0 / s->winsize; | |||
| aubio_vDSP_vsmul(output->data, 1, &scale, output->data, 1, s->fft_size); | |||
| #elif defined HAVE_INTEL_IPP // using Intel IPP | |||
| // convert from real imag [ r0, 0, ..., rN, iN-1, .., i2, i1, iN-1] to complex format | |||
| s->complexOut[0].re = compspec->data[0]; | |||
| s->complexOut[0].im = 0; | |||
| s->complexOut[s->fft_size / 2].re = compspec->data[s->fft_size / 2]; | |||
| s->complexOut[s->fft_size / 2].im = 0.0; | |||
| for (i = 1; i < s->fft_size / 2; i++) { | |||
| s->complexOut[i].re = compspec->data[i]; | |||
| s->complexOut[i].im = compspec->data[s->fft_size - i]; | |||
| } | |||
| // apply fft | |||
| aubio_ippsFFTInv_CCSToR((const aubio_IppFloat *)s->complexOut, output->data, s->fftSpec, s->memBuffer); | |||
| // apply scaling | |||
| aubio_ippsMulC(output->data, 1.0 / s->winsize, output->data, s->fft_size); | |||
| #else // using OOURA | |||
| smpl_t scale = 2.0 / s->winsize; | |||
| s->out[0] = compspec->data[0]; | |||
| s->out[1] = compspec->data[s->winsize / 2]; | |||
| for (i = 1; i < s->fft_size - 1; i++) { | |||
| s->out[2 * i] = compspec->data[i]; | |||
| s->out[2 * i + 1] = - compspec->data[s->winsize - i]; | |||
| } | |||
| aubio_ooura_rdft(s->winsize, -1, s->out, s->ip, s->w); | |||
| for (i=0; i < s->winsize; i++) { | |||
| output->data[i] = s->out[i] * scale; | |||
| } | |||
| #endif | |||
| } | |||
| void aubio_fft_get_spectrum(const fvec_t * compspec, cvec_t * spectrum) { | |||
| aubio_fft_get_phas(compspec, spectrum); | |||
| aubio_fft_get_norm(compspec, spectrum); | |||
| } | |||
| void aubio_fft_get_realimag(const cvec_t * spectrum, fvec_t * compspec) { | |||
| aubio_fft_get_imag(spectrum, compspec); | |||
| aubio_fft_get_real(spectrum, compspec); | |||
| } | |||
| void aubio_fft_get_phas(const fvec_t * compspec, cvec_t * spectrum) { | |||
| uint_t i; | |||
| if (compspec->data[0] < 0) { | |||
| spectrum->phas[0] = PI; | |||
| } else { | |||
| spectrum->phas[0] = 0.; | |||
| } | |||
| #if defined(HAVE_INTEL_IPP) | |||
| // convert from real imag [ r0, r1, ..., rN, iN-1, ..., i2, i1, i0] | |||
| // to [ r0, r1, ..., rN, i0, i1, i2, ..., iN-1] | |||
| for (i = 1; i < spectrum->length / 2; i++) { | |||
| ELEM_SWAP(compspec->data[compspec->length - i], | |||
| compspec->data[spectrum->length + i - 1]); | |||
| } | |||
| aubio_ippsAtan2(compspec->data + spectrum->length, | |||
| compspec->data + 1, spectrum->phas + 1, spectrum->length - 1); | |||
| // revert the imaginary part back again | |||
| for (i = 1; i < spectrum->length / 2; i++) { | |||
| ELEM_SWAP(compspec->data[spectrum->length + i - 1], | |||
| compspec->data[compspec->length - i]); | |||
| } | |||
| #else | |||
| for (i=1; i < spectrum->length - 1; i++) { | |||
| spectrum->phas[i] = ATAN2(compspec->data[compspec->length-i], | |||
| compspec->data[i]); | |||
| } | |||
| #endif | |||
| #ifdef HAVE_FFTW3 | |||
| // for even length only, make sure last element is 0 or PI | |||
| if (2 * (compspec->length / 2) == compspec->length) { | |||
| #endif | |||
| if (compspec->data[compspec->length/2] < 0) { | |||
| spectrum->phas[spectrum->length - 1] = PI; | |||
| } else { | |||
| spectrum->phas[spectrum->length - 1] = 0.; | |||
| } | |||
| #ifdef HAVE_FFTW3 | |||
| } else { | |||
| i = spectrum->length - 1; | |||
| spectrum->phas[i] = ATAN2(compspec->data[compspec->length-i], | |||
| compspec->data[i]); | |||
| } | |||
| #endif | |||
| } | |||
| void aubio_fft_get_norm(const fvec_t * compspec, cvec_t * spectrum) { | |||
| uint_t i = 0; | |||
| spectrum->norm[0] = ABS(compspec->data[0]); | |||
| for (i=1; i < spectrum->length - 1; i++) { | |||
| spectrum->norm[i] = SQRT(SQR(compspec->data[i]) | |||
| + SQR(compspec->data[compspec->length - i]) ); | |||
| } | |||
| #ifdef HAVE_FFTW3 | |||
| // for even length, make sure last element is > 0 | |||
| if (2 * (compspec->length / 2) == compspec->length) { | |||
| #endif | |||
| spectrum->norm[spectrum->length-1] = | |||
| ABS(compspec->data[compspec->length/2]); | |||
| #ifdef HAVE_FFTW3 | |||
| } else { | |||
| i = spectrum->length - 1; | |||
| spectrum->norm[i] = SQRT(SQR(compspec->data[i]) | |||
| + SQR(compspec->data[compspec->length - i]) ); | |||
| } | |||
| #endif | |||
| } | |||
| void aubio_fft_get_imag(const cvec_t * spectrum, fvec_t * compspec) { | |||
| uint_t i; | |||
| for (i = 1; i < ( compspec->length + 1 ) / 2 /*- 1 + 1*/; i++) { | |||
| compspec->data[compspec->length - i] = | |||
| spectrum->norm[i]*SIN(spectrum->phas[i]); | |||
| } | |||
| } | |||
| void aubio_fft_get_real(const cvec_t * spectrum, fvec_t * compspec) { | |||
| uint_t i; | |||
| for (i = 0; i < compspec->length / 2 + 1; i++) { | |||
| compspec->data[i] = | |||
| spectrum->norm[i]*COS(spectrum->phas[i]); | |||
| } | |||
| } | |||
| @@ -0,0 +1,144 @@ | |||
| /* | |||
| Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** \file | |||
| Fast Fourier Transform | |||
| Depending on how aubio was compiled, FFT are computed using one of: | |||
| - [Ooura](http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) | |||
| - [FFTW3](http://www.fftw.org) | |||
| - [vDSP](https://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/reference.html) | |||
| \example spectral/test-fft.c | |||
| */ | |||
| #ifndef AUBIO_FFT_H | |||
| #define AUBIO_FFT_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** FFT object | |||
| This object computes forward and backward FFTs. | |||
| */ | |||
| typedef struct _aubio_fft_t aubio_fft_t; | |||
| /** create new FFT computation object | |||
| \param size length of the FFT | |||
| */ | |||
| aubio_fft_t * new_aubio_fft (uint_t size); | |||
| /** delete FFT object | |||
| \param s fft object as returned by new_aubio_fft | |||
| */ | |||
| void del_aubio_fft(aubio_fft_t * s); | |||
| /** compute forward FFT | |||
| \param s fft object as returned by new_aubio_fft | |||
| \param input input signal | |||
| \param spectrum output spectrum | |||
| */ | |||
| void aubio_fft_do (aubio_fft_t *s, const fvec_t * input, cvec_t * spectrum); | |||
| /** compute backward (inverse) FFT | |||
| \param s fft object as returned by new_aubio_fft | |||
| \param spectrum input spectrum | |||
| \param output output signal | |||
| */ | |||
| void aubio_fft_rdo (aubio_fft_t *s, const cvec_t * spectrum, fvec_t * output); | |||
| /** compute forward FFT | |||
| \param s fft object as returned by new_aubio_fft | |||
| \param input real input signal | |||
| \param compspec complex output fft real/imag | |||
| */ | |||
| void aubio_fft_do_complex (aubio_fft_t *s, const fvec_t * input, fvec_t * compspec); | |||
| /** compute backward (inverse) FFT from real/imag | |||
| \param s fft object as returned by new_aubio_fft | |||
| \param compspec real/imag input fft array | |||
| \param output real output array | |||
| */ | |||
| void aubio_fft_rdo_complex (aubio_fft_t *s, const fvec_t * compspec, fvec_t * output); | |||
| /** convert real/imag spectrum to norm/phas spectrum | |||
| \param compspec real/imag input fft array | |||
| \param spectrum cvec norm/phas output array | |||
| */ | |||
| void aubio_fft_get_spectrum(const fvec_t * compspec, cvec_t * spectrum); | |||
| /** convert real/imag spectrum to norm/phas spectrum | |||
| \param compspec real/imag input fft array | |||
| \param spectrum cvec norm/phas output array | |||
| */ | |||
| void aubio_fft_get_realimag(const cvec_t * spectrum, fvec_t * compspec); | |||
| /** compute phas spectrum from real/imag parts | |||
| \param compspec real/imag input fft array | |||
| \param spectrum cvec norm/phas output array | |||
| */ | |||
| void aubio_fft_get_phas(const fvec_t * compspec, cvec_t * spectrum); | |||
| /** compute imaginary part from the norm/phas cvec | |||
| \param spectrum norm/phas input array | |||
| \param compspec real/imag output fft array | |||
| */ | |||
| void aubio_fft_get_imag(const cvec_t * spectrum, fvec_t * compspec); | |||
| /** compute norm component from real/imag parts | |||
| \param compspec real/imag input fft array | |||
| \param spectrum cvec norm/phas output array | |||
| */ | |||
| void aubio_fft_get_norm(const fvec_t * compspec, cvec_t * spectrum); | |||
| /** compute real part from norm/phas components | |||
| \param spectrum norm/phas input array | |||
| \param compspec real/imag output fft array | |||
| */ | |||
| void aubio_fft_get_real(const cvec_t * spectrum, fvec_t * compspec); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_FFT_H */ | |||
| @@ -0,0 +1,224 @@ | |||
| /* | |||
| Copyright (C) 2003-2014 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "cvec.h" | |||
| #include "mathutils.h" | |||
| #include "spectral/fft.h" | |||
| #include "spectral/phasevoc.h" | |||
| /** phasevocoder internal object */ | |||
| struct _aubio_pvoc_t { | |||
| uint_t win_s; /** grain length */ | |||
| uint_t hop_s; /** overlap step */ | |||
| aubio_fft_t * fft; /** fft object */ | |||
| fvec_t * data; /** current input grain, [win_s] frames */ | |||
| fvec_t * dataold; /** memory of past grain, [win_s-hop_s] frames */ | |||
| fvec_t * synth; /** current output grain, [win_s] frames */ | |||
| fvec_t * synthold; /** memory of past grain, [win_s-hop_s] frames */ | |||
| fvec_t * w; /** grain window [win_s] */ | |||
| uint_t start; /** where to start additive synthesis */ | |||
| uint_t end; /** where to end it */ | |||
| smpl_t scale; /** scaling factor for synthesis */ | |||
| uint_t end_datasize; /** size of memory to end */ | |||
| uint_t hop_datasize; /** size of memory to hop_s */ | |||
| }; | |||
| /** returns data and dataold slided by hop_s */ | |||
| static void aubio_pvoc_swapbuffers(aubio_pvoc_t *pv, const fvec_t *new); | |||
| /** do additive synthesis from 'old' and 'cur' */ | |||
| static void aubio_pvoc_addsynth(aubio_pvoc_t *pv, fvec_t * synthnew); | |||
| void aubio_pvoc_do(aubio_pvoc_t *pv, const fvec_t * datanew, cvec_t *fftgrain) { | |||
| /* slide */ | |||
| aubio_pvoc_swapbuffers(pv, datanew); | |||
| /* windowing */ | |||
| fvec_weight(pv->data, pv->w); | |||
| /* shift */ | |||
| fvec_shift(pv->data); | |||
| /* calculate fft */ | |||
| aubio_fft_do (pv->fft,pv->data,fftgrain); | |||
| } | |||
| void aubio_pvoc_rdo(aubio_pvoc_t *pv,cvec_t * fftgrain, fvec_t * synthnew) { | |||
| /* calculate rfft */ | |||
| aubio_fft_rdo(pv->fft,fftgrain,pv->synth); | |||
| /* unshift */ | |||
| fvec_ishift(pv->synth); | |||
| /* windowing */ | |||
| // if overlap = 50%, do not apply window (identity) | |||
| if (pv->hop_s * 2 < pv->win_s) { | |||
| fvec_weight(pv->synth, pv->w); | |||
| } | |||
| /* additive synthesis */ | |||
| aubio_pvoc_addsynth(pv, synthnew); | |||
| } | |||
| aubio_pvoc_t * new_aubio_pvoc (uint_t win_s, uint_t hop_s) { | |||
| aubio_pvoc_t * pv = AUBIO_NEW(aubio_pvoc_t); | |||
| /* if (win_s < 2*hop_s) { | |||
| AUBIO_WRN("Hop size bigger than half the window size!\n"); | |||
| } */ | |||
| if ((sint_t)hop_s < 1) { | |||
| AUBIO_ERR("pvoc: got hop_size %d, but can not be < 1\n", hop_s); | |||
| goto beach; | |||
| } else if ((sint_t)win_s < 2) { | |||
| AUBIO_ERR("pvoc: got buffer_size %d, but can not be < 2\n", win_s); | |||
| goto beach; | |||
| } else if (win_s < hop_s) { | |||
| AUBIO_ERR("pvoc: hop size (%d) is larger than win size (%d)\n", hop_s, win_s); | |||
| goto beach; | |||
| } | |||
| pv->fft = new_aubio_fft (win_s); | |||
| if (pv->fft == NULL) { | |||
| goto beach; | |||
| } | |||
| /* remember old */ | |||
| pv->data = new_fvec (win_s); | |||
| pv->synth = new_fvec (win_s); | |||
| /* new input output */ | |||
| if (win_s > hop_s) { | |||
| pv->dataold = new_fvec (win_s-hop_s); | |||
| pv->synthold = new_fvec (win_s-hop_s); | |||
| } else { | |||
| pv->dataold = new_fvec (1); | |||
| pv->synthold = new_fvec (1); | |||
| } | |||
| pv->w = new_aubio_window ("hanningz", win_s); | |||
| pv->hop_s = hop_s; | |||
| pv->win_s = win_s; | |||
| /* more than 50% overlap, overlap anyway */ | |||
| if (win_s < 2 * hop_s) pv->start = 0; | |||
| /* less than 50% overlap, reset latest grain trail */ | |||
| else pv->start = win_s - hop_s - hop_s; | |||
| if (win_s > hop_s) pv->end = win_s - hop_s; | |||
| else pv->end = 0; | |||
| pv->end_datasize = pv->end * sizeof(smpl_t); | |||
| pv->hop_datasize = pv->hop_s * sizeof(smpl_t); | |||
| // for reconstruction with 75% overlap | |||
| if (win_s == hop_s * 4) { | |||
| pv->scale = 2./3.; | |||
| } else if (win_s == hop_s * 8) { | |||
| pv->scale = 1./3.; | |||
| } else if (win_s == hop_s * 2) { | |||
| pv->scale = 1.; | |||
| } else { | |||
| pv->scale = .5; | |||
| } | |||
| return pv; | |||
| beach: | |||
| AUBIO_FREE (pv); | |||
| return NULL; | |||
| } | |||
| uint_t aubio_pvoc_set_window(aubio_pvoc_t *pv, const char_t *window) { | |||
| return fvec_set_window(pv->w, (char_t*)window); | |||
| } | |||
| void del_aubio_pvoc(aubio_pvoc_t *pv) { | |||
| del_fvec(pv->data); | |||
| del_fvec(pv->synth); | |||
| del_fvec(pv->dataold); | |||
| del_fvec(pv->synthold); | |||
| del_fvec(pv->w); | |||
| del_aubio_fft(pv->fft); | |||
| AUBIO_FREE(pv); | |||
| } | |||
| static void aubio_pvoc_swapbuffers(aubio_pvoc_t *pv, const fvec_t *new) | |||
| { | |||
| /* some convenience pointers */ | |||
| smpl_t * data = pv->data->data; | |||
| smpl_t * dataold = pv->dataold->data; | |||
| smpl_t * datanew = new->data; | |||
| #ifndef HAVE_MEMCPY_HACKS | |||
| uint_t i; | |||
| for (i = 0; i < pv->end; i++) | |||
| data[i] = dataold[i]; | |||
| for (i = 0; i < pv->hop_s; i++) | |||
| data[pv->end + i] = datanew[i]; | |||
| for (i = 0; i < pv->end; i++) | |||
| dataold[i] = data[i + pv->hop_s]; | |||
| #else | |||
| memcpy(data, dataold, pv->end_datasize); | |||
| data += pv->end; | |||
| memcpy(data, datanew, pv->hop_datasize); | |||
| data -= pv->end; | |||
| data += pv->hop_s; | |||
| memcpy(dataold, data, pv->end_datasize); | |||
| #endif | |||
| } | |||
| static void aubio_pvoc_addsynth(aubio_pvoc_t *pv, fvec_t *synth_new) | |||
| { | |||
| uint_t i; | |||
| /* some convenience pointers */ | |||
| smpl_t * synth = pv->synth->data; | |||
| smpl_t * synthold = pv->synthold->data; | |||
| smpl_t * synthnew = synth_new->data; | |||
| /* put new result in synthnew */ | |||
| for (i = 0; i < pv->hop_s; i++) | |||
| synthnew[i] = synth[i] * pv->scale; | |||
| /* no overlap, nothing else to do */ | |||
| if (pv->end == 0) return; | |||
| /* add new synth to old one */ | |||
| for (i = 0; i < pv->hop_s; i++) | |||
| synthnew[i] += synthold[i]; | |||
| /* shift synthold */ | |||
| for (i = 0; i < pv->start; i++) | |||
| synthold[i] = synthold[i + pv->hop_s]; | |||
| /* erase last frame in synthold */ | |||
| for (i = pv->start; i < pv->end; i++) | |||
| synthold[i] = 0.; | |||
| /* additive synth */ | |||
| for (i = 0; i < pv->end; i++) | |||
| synthold[i] += synth[i + pv->hop_s] * pv->scale; | |||
| } | |||
| uint_t aubio_pvoc_get_win(aubio_pvoc_t* pv) | |||
| { | |||
| return pv->win_s; | |||
| } | |||
| uint_t aubio_pvoc_get_hop(aubio_pvoc_t* pv) | |||
| { | |||
| return pv->hop_s; | |||
| } | |||
| @@ -0,0 +1,113 @@ | |||
| /* | |||
| Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /** \file | |||
| Phase vocoder object | |||
| This object implements a phase vocoder. The spectral frames are computed | |||
| using a HanningZ window and a swapped version of the signal to simplify the | |||
| phase relationships across frames. The window sizes and overlap are specified | |||
| at creation time. | |||
| \example spectral/test-phasevoc.c | |||
| */ | |||
| #ifndef AUBIO_PHASEVOC_H | |||
| #define AUBIO_PHASEVOC_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** phasevocoder object */ | |||
| typedef struct _aubio_pvoc_t aubio_pvoc_t; | |||
| /** create phase vocoder object | |||
| \param win_s size of analysis buffer (and length the FFT transform) | |||
| \param hop_s step size between two consecutive analysis | |||
| */ | |||
| aubio_pvoc_t * new_aubio_pvoc (uint_t win_s, uint_t hop_s); | |||
| /** delete phase vocoder object | |||
| \param pv phase vocoder object as returned by new_aubio_pvoc | |||
| */ | |||
| void del_aubio_pvoc(aubio_pvoc_t *pv); | |||
| /** compute spectral frame | |||
| This function accepts an input vector of size [hop_s]. The | |||
| analysis buffer is rotated and filled with the new data. After windowing of | |||
| this signal window, the Fourier transform is computed and returned in | |||
| fftgrain as two vectors, magnitude and phase. | |||
| \param pv phase vocoder object as returned by new_aubio_pvoc | |||
| \param in new input signal (hop_s long) | |||
| \param fftgrain output spectral frame | |||
| */ | |||
| void aubio_pvoc_do(aubio_pvoc_t *pv, const fvec_t *in, cvec_t * fftgrain); | |||
| /** compute signal from spectral frame | |||
| This function takes an input spectral frame fftgrain of size | |||
| [buf_s] and computes its inverse Fourier transform. Overlap-add | |||
| synthesis is then computed using the previously synthetised frames, and the | |||
| output stored in out. | |||
| \param pv phase vocoder object as returned by new_aubio_pvoc | |||
| \param fftgrain input spectral frame | |||
| \param out output signal (hop_s long) | |||
| */ | |||
| void aubio_pvoc_rdo(aubio_pvoc_t *pv, cvec_t * fftgrain, fvec_t *out); | |||
| /** get window size | |||
| \param pv phase vocoder to get the window size from | |||
| */ | |||
| uint_t aubio_pvoc_get_win(aubio_pvoc_t* pv); | |||
| /** get hop size | |||
| \param pv phase vocoder to get the hop size from | |||
| */ | |||
| uint_t aubio_pvoc_get_hop(aubio_pvoc_t* pv); | |||
| /** set window type | |||
| \param pv phase vocoder to set the window type | |||
| \param window_type a string representing a window | |||
| \return 0 if successful, non-zero otherwise | |||
| */ | |||
| uint_t aubio_pvoc_set_window(aubio_pvoc_t *pv, const char_t *window_type); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_PHASEVOC_H */ | |||
| @@ -0,0 +1,262 @@ | |||
| /* | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "types.h" | |||
| #include "fvec.h" | |||
| #include "lvec.h" | |||
| #include "temporal/filter.h" | |||
| #include "temporal/a_weighting.h" | |||
| uint_t | |||
| aubio_filter_set_a_weighting (aubio_filter_t * f, uint_t samplerate) | |||
| { | |||
| uint_t order; lsmp_t *a, *b; lvec_t *as, *bs; | |||
| if ((sint_t)samplerate <= 0) { | |||
| AUBIO_ERROR("aubio_filter: failed setting A-weighting with samplerate %d\n", samplerate); | |||
| return AUBIO_FAIL; | |||
| } | |||
| if (f == NULL) { | |||
| AUBIO_ERROR("aubio_filter: failed setting A-weighting with filter NULL\n"); | |||
| return AUBIO_FAIL; | |||
| } | |||
| order = aubio_filter_get_order (f); | |||
| if (order != 7) { | |||
| AUBIO_ERROR ("aubio_filter: order of A-weighting filter must be 7, not %d\n", order); | |||
| return 1; | |||
| } | |||
| aubio_filter_set_samplerate (f, samplerate); | |||
| bs = aubio_filter_get_feedforward (f); | |||
| as = aubio_filter_get_feedback (f); | |||
| b = bs->data, a = as->data; | |||
| /* select coefficients according to sampling frequency */ | |||
| switch (samplerate) { | |||
| case 8000: | |||
| b[0] = 6.306209468238731519207362907764036208391189575195312500e-01; | |||
| b[1] = -1.261241893647746525886077506584115326404571533203125000e+00; | |||
| b[2] = -6.306209468238730408984338282607495784759521484375000000e-01; | |||
| b[3] = 2.522483787295493051772155013168230652809143066406250000e+00; | |||
| b[4] = -6.306209468238730408984338282607495784759521484375000000e-01; | |||
| b[5] = -1.261241893647746525886077506584115326404571533203125000e+00; | |||
| b[6] = 6.306209468238731519207362907764036208391189575195312500e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -2.128467193009123015201566886389628052711486816406250000e+00; | |||
| a[2] = 2.948668980101234460278192273108288645744323730468750000e-01; | |||
| a[3] = 1.824183830735050637628091863007284700870513916015625000e+00; | |||
| a[4] = -8.056628943119792385374466903158463537693023681640625000e-01; | |||
| a[5] = -3.947497982842933517133587884018197655677795410156250000e-01; | |||
| a[6] = 2.098548546080332977137317129745497368276119232177734375e-01; | |||
| break; | |||
| case 11025: | |||
| b[0] = 6.014684165832374640459079273568931967020034790039062500e-01; | |||
| b[1] = -1.202936833166475150136420779745094478130340576171875000e+00; | |||
| b[2] = -6.014684165832373530236054648412391543388366699218750000e-01; | |||
| b[3] = 2.405873666332950300272841559490188956260681152343750000e+00; | |||
| b[4] = -6.014684165832373530236054648412391543388366699218750000e-01; | |||
| b[5] = -1.202936833166475150136420779745094478130340576171875000e+00; | |||
| b[6] = 6.014684165832374640459079273568931967020034790039062500e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -2.463578747722854345170162559952586889266967773437500000e+00; | |||
| a[2] = 1.096799662705210121060872552334330976009368896484375000e+00; | |||
| a[3] = 1.381222210556041218865175324026495218276977539062500000e+00; | |||
| a[4] = -1.013875696476876031582037285261321812868118286132812500e+00; | |||
| a[5] = -1.839132734476921215982514468123554252088069915771484375e-01; | |||
| a[6] = 1.833526393172056623281918064094497822225093841552734375e-01; | |||
| break; | |||
| case 16000: | |||
| b[0] = 5.314898298235570806014038680586963891983032226562500000e-01; | |||
| b[1] = -1.062979659647114161202807736117392778396606445312500000e+00; | |||
| b[2] = -5.314898298235570806014038680586963891983032226562500000e-01; | |||
| b[3] = 2.125959319294228322405615472234785556793212890625000000e+00; | |||
| b[4] = -5.314898298235570806014038680586963891983032226562500000e-01; | |||
| b[5] = -1.062979659647114161202807736117392778396606445312500000e+00; | |||
| b[6] = 5.314898298235570806014038680586963891983032226562500000e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -2.867832572992162987191022693878039717674255371093750000e+00; | |||
| a[2] = 2.221144410202312347024644623161293566226959228515625000e+00; | |||
| a[3] = 4.552683347886614662058946123579517006874084472656250000e-01; | |||
| a[4] = -9.833868636162828025248927588108927011489868164062500000e-01; | |||
| a[5] = 5.592994142413361402521587706360151059925556182861328125e-02; | |||
| a[6] = 1.188781038285612462468421313133148942142724990844726562e-01; | |||
| break; | |||
| case 22050: | |||
| b[0] = 4.492998504299193784916610638902056962251663208007812500e-01; | |||
| b[1] = -8.985997008598388680056245902960654348134994506835937500e-01; | |||
| b[2] = -4.492998504299192674693586013745516538619995117187500000e-01; | |||
| b[3] = 1.797199401719677958055854105623438954353332519531250000e+00; | |||
| b[4] = -4.492998504299192674693586013745516538619995117187500000e-01; | |||
| b[5] = -8.985997008598388680056245902960654348134994506835937500e-01; | |||
| b[6] = 4.492998504299193784916610638902056962251663208007812500e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -3.229078805225074955131958631682209670543670654296875000e+00; | |||
| a[2] = 3.354494881236033787530459449044428765773773193359375000e+00; | |||
| a[3] = -7.317843680657351024265722116979304701089859008789062500e-01; | |||
| a[4] = -6.271627581807257545420952737913466989994049072265625000e-01; | |||
| a[5] = 1.772142005020879151899748649157118052244186401367187500e-01; | |||
| a[6] = 5.631716697383508385410522123493137769401073455810546875e-02; | |||
| break; | |||
| case 24000: | |||
| b[0] = 4.256263892891054001488271296693710610270500183105468750e-01; | |||
| b[1] = -8.512527785782106892753517968230880796909332275390625000e-01; | |||
| b[2] = -4.256263892891054556599783609271980822086334228515625000e-01; | |||
| b[3] = 1.702505557156421378550703593646176159381866455078125000e+00; | |||
| b[4] = -4.256263892891054556599783609271980822086334228515625000e-01; | |||
| b[5] = -8.512527785782106892753517968230880796909332275390625000e-01; | |||
| b[6] = 4.256263892891054001488271296693710610270500183105468750e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -3.325996004241962733516402295208536088466644287109375000e+00; | |||
| a[2] = 3.677161079286316969216841243905946612358093261718750000e+00; | |||
| a[3] = -1.106476076828482035807610373012721538543701171875000000e+00; | |||
| a[4] = -4.726706734908718843257702246773988008499145507812500000e-01; | |||
| a[5] = 1.861941760230954034938122276798821985721588134765625000e-01; | |||
| a[6] = 4.178771337829546850262119050967157818377017974853515625e-02; | |||
| break; | |||
| case 32000: | |||
| b[0] = 3.434583386824304196416335344110848382115364074707031250e-01; | |||
| b[1] = -6.869166773648609503055695313378237187862396240234375000e-01; | |||
| b[2] = -3.434583386824303641304823031532578170299530029296875000e-01; | |||
| b[3] = 1.373833354729721900611139062675647437572479248046875000e+00; | |||
| b[4] = -3.434583386824303641304823031532578170299530029296875000e-01; | |||
| b[5] = -6.869166773648609503055695313378237187862396240234375000e-01; | |||
| b[6] = 3.434583386824304196416335344110848382115364074707031250e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -3.656446043233668063976438133977353572845458984375000000e+00; | |||
| a[2] = 4.831468450652579349480220116674900054931640625000000000e+00; | |||
| a[3] = -2.557597496581567764195597192156128585338592529296875000e+00; | |||
| a[4] = 2.533680394205302666144064005493419244885444641113281250e-01; | |||
| a[5] = 1.224430322452567110325105659285327419638633728027343750e-01; | |||
| a[6] = 6.764072168342137418572956875095769646577537059783935547e-03; | |||
| break; | |||
| case 44100: | |||
| b[0] = 2.557411252042575133813784304948057979345321655273437500e-01; | |||
| b[1] = -5.114822504085150267627568609896115958690643310546875000e-01; | |||
| b[2] = -2.557411252042575133813784304948057979345321655273437500e-01; | |||
| b[3] = 1.022964500817030053525513721979223191738128662109375000e+00; | |||
| b[4] = -2.557411252042575133813784304948057979345321655273437500e-01; | |||
| b[5] = -5.114822504085150267627568609896115958690643310546875000e-01; | |||
| b[6] = 2.557411252042575133813784304948057979345321655273437500e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -4.019576181115832369528106937650591135025024414062500000e+00; | |||
| a[2] = 6.189406442920693862674852425698190927505493164062500000e+00; | |||
| a[3] = -4.453198903544116404873420833609998226165771484375000000e+00; | |||
| a[4] = 1.420842949621876627475103305187076330184936523437500000e+00; | |||
| a[5] = -1.418254738303044160119270600262098014354705810546875000e-01; | |||
| a[6] = 4.351177233495117681327801761881346465088427066802978516e-03; | |||
| break; | |||
| case 48000: | |||
| b[0] = 2.343017922995132285013397677175817079842090606689453125e-01; | |||
| b[1] = -4.686035845990265125138307666929904371500015258789062500e-01; | |||
| b[2] = -2.343017922995132007457641520886681973934173583984375000e-01; | |||
| b[3] = 9.372071691980530250276615333859808743000030517578125000e-01; | |||
| b[4] = -2.343017922995132007457641520886681973934173583984375000e-01; | |||
| b[5] = -4.686035845990265125138307666929904371500015258789062500e-01; | |||
| b[6] = 2.343017922995132285013397677175817079842090606689453125e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -4.113043408775872045168853219365701079368591308593750000e+00; | |||
| a[2] = 6.553121752655050258340452273841947317123413085937500000e+00; | |||
| a[3] = -4.990849294163385074796224216697737574577331542968750000e+00; | |||
| a[4] = 1.785737302937575599059982778271660208702087402343750000e+00; | |||
| a[5] = -2.461905953194876706113802811159985139966011047363281250e-01; | |||
| a[6] = 1.122425003323123879339640041052916785702109336853027344e-02; | |||
| break; | |||
| case 88200: | |||
| b[0] = 1.118876366882113199130444058937428053468465805053710938e-01; | |||
| b[1] = -2.237752733764226120705131961585721001029014587402343750e-01; | |||
| b[2] = -1.118876366882113337908322137081995606422424316406250000e-01; | |||
| b[3] = 4.475505467528452241410263923171442002058029174804687500e-01; | |||
| b[4] = -1.118876366882113337908322137081995606422424316406250000e-01; | |||
| b[5] = -2.237752733764226120705131961585721001029014587402343750e-01; | |||
| b[6] = 1.118876366882113199130444058937428053468465805053710938e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -4.726938565651158441482948546763509511947631835937500000e+00; | |||
| a[2] = 9.076897983832765248735086061060428619384765625000000000e+00; | |||
| a[3] = -9.014855113464800950850985827855765819549560546875000000e+00; | |||
| a[4] = 4.852772261031594425162438710685819387435913085937500000e+00; | |||
| a[5] = -1.333877820398965186043938047077972441911697387695312500e+00; | |||
| a[6] = 1.460012549591642450064199465487035922706127166748046875e-01; | |||
| break; | |||
| case 96000: | |||
| b[0] = 9.951898975972744976203898659150581806898117065429687500e-02; | |||
| b[1] = -1.990379795194548995240779731830116361379623413085937500e-01; | |||
| b[2] = -9.951898975972744976203898659150581806898117065429687500e-02; | |||
| b[3] = 3.980759590389097990481559463660232722759246826171875000e-01; | |||
| b[4] = -9.951898975972744976203898659150581806898117065429687500e-02; | |||
| b[5] = -1.990379795194548995240779731830116361379623413085937500e-01; | |||
| b[6] = 9.951898975972744976203898659150581806898117065429687500e-02; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -4.802203044225376693532325589330866932868957519531250000e+00; | |||
| a[2] = 9.401807218627226347962277941405773162841796875000000000e+00; | |||
| a[3] = -9.566143943569164420637207513209432363510131835937500000e+00; | |||
| a[4] = 5.309775930392619081032989925006404519081115722656250000e+00; | |||
| a[5] = -1.517333360452622237346531619550660252571105957031250000e+00; | |||
| a[6] = 1.740971994228911745583587844521389342844486236572265625e-01; | |||
| break; | |||
| case 192000: | |||
| b[0] = 3.433213424548713782469278044118254911154508590698242188e-02; | |||
| b[1] = -6.866426849097426177159775306790834292769432067871093750e-02; | |||
| b[2] = -3.433213424548714476358668434841092675924301147460937500e-02; | |||
| b[3] = 1.373285369819485235431955061358166858553886413574218750e-01; | |||
| b[4] = -3.433213424548714476358668434841092675924301147460937500e-02; | |||
| b[5] = -6.866426849097426177159775306790834292769432067871093750e-02; | |||
| b[6] = 3.433213424548713782469278044118254911154508590698242188e-02; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -5.305923689674640009172890131594613194465637207031250000e+00; | |||
| a[2] = 1.165952437466175695135461864992976188659667968750000000e+01; | |||
| a[3] = -1.357560092700591525272102444432675838470458984375000000e+01; | |||
| a[4] = 8.828906932824192921316353022120893001556396484375000000e+00; | |||
| a[5] = -3.039490120988216581565666274400427937507629394531250000e+00; | |||
| a[6] = 4.325834301870381537469256727490574121475219726562500000e-01; | |||
| break; | |||
| default: | |||
| AUBIO_ERROR ("sampling rate of A-weighting filter is %d, should be one of\ | |||
| 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, 192000.\n", samplerate); | |||
| return 1; | |||
| } | |||
| return 0; | |||
| } | |||
| aubio_filter_t * | |||
| new_aubio_filter_a_weighting (uint_t samplerate) | |||
| { | |||
| aubio_filter_t *f = new_aubio_filter (7); | |||
| if (aubio_filter_set_a_weighting(f,samplerate) != AUBIO_OK) { | |||
| del_aubio_filter(f); | |||
| return NULL; | |||
| } | |||
| return f; | |||
| } | |||
| @@ -0,0 +1,88 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #ifndef AUBIO_FILTER_A_DESIGN_H | |||
| #define AUBIO_FILTER_A_DESIGN_H | |||
| /** \file | |||
| A-weighting filter coefficients | |||
| This file creates an A-weighting digital filter, which reduces low and high | |||
| frequencies and enhance the middle ones to reflect the ability of the human | |||
| hearing. | |||
| The implementation is based on the following standard: | |||
| - IEC/CD 1672: Electroacoustics-Sound Level Meters, IEC, Geneva, Nov. 1996, | |||
| for A- and C-weighting filters. | |||
| See also: | |||
| - <a href="http://en.wikipedia.org/wiki/A-weighting">A-Weighting on | |||
| Wikipedia</a> | |||
| - <a href="http://en.wikipedia.org/wiki/Weighting_filter">Weighting filter on | |||
| Wikipedia</a> | |||
| - <a href="http://www.mathworks.com/matlabcentral/fileexchange/69">Christophe | |||
| Couvreur's 'octave' toolbox</a> | |||
| The coefficients in this file have been computed using Christophe Couvreur's | |||
| scripts in octave 3.0 (debian package 1:3.0.5-6+b2 with octave-signal | |||
| 1.0.9-1+b1 on i386), with <pre> [b, a] = adsign(1/Fs) </pre> for various | |||
| sampling frequencies (8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, | |||
| 88200, 96000, and 192000 Hz). | |||
| The sampling frequency should normally be higher than 20kHz, but most common | |||
| file sampling rates have been included for completeness. | |||
| \example temporal/test-a_weighting.c | |||
| */ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** create new A-design filter | |||
| \param samplerate sampling frequency of the signal to filter. Should be one of | |||
| 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, and | |||
| 192000 Hz | |||
| \return a new filter object | |||
| */ | |||
| aubio_filter_t *new_aubio_filter_a_weighting (uint_t samplerate); | |||
| /** set feedback and feedforward coefficients of a A-weighting filter | |||
| \param f filter object to get coefficients from | |||
| \param samplerate sampling frequency of the signal to filter. Should be one of | |||
| 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, and | |||
| 192000 Hz | |||
| */ | |||
| uint_t aubio_filter_set_a_weighting (aubio_filter_t * f, uint_t samplerate); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_FILTER_A_DESIGN_H */ | |||
| @@ -0,0 +1,54 @@ | |||
| /* | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "lvec.h" | |||
| #include "temporal/filter.h" | |||
| #include "temporal/biquad.h" | |||
| uint_t | |||
| aubio_filter_set_biquad (aubio_filter_t * f, lsmp_t b0, lsmp_t b1, lsmp_t b2, | |||
| lsmp_t a1, lsmp_t a2) | |||
| { | |||
| uint_t order = aubio_filter_get_order (f); | |||
| lvec_t *bs = aubio_filter_get_feedforward (f); | |||
| lvec_t *as = aubio_filter_get_feedback (f); | |||
| if (order != 3) { | |||
| AUBIO_ERROR ("order of biquad filter must be 3, not %d\n", order); | |||
| return AUBIO_FAIL; | |||
| } | |||
| bs->data[0] = b0; | |||
| bs->data[1] = b1; | |||
| bs->data[2] = b2; | |||
| as->data[0] = 1.; | |||
| as->data[1] = a1; | |||
| as->data[2] = a2; | |||
| return AUBIO_OK; | |||
| } | |||
| aubio_filter_t * | |||
| new_aubio_filter_biquad (lsmp_t b0, lsmp_t b1, lsmp_t b2, lsmp_t a1, lsmp_t a2) | |||
| { | |||
| aubio_filter_t *f = new_aubio_filter (3); | |||
| aubio_filter_set_biquad (f, b0, b1, b2, a1, a2); | |||
| return f; | |||
| } | |||
| @@ -0,0 +1,75 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #ifndef AUBIO_FILTER_BIQUAD_H | |||
| #define AUBIO_FILTER_BIQUAD_H | |||
| /** \file | |||
| Second order Infinite Impulse Response filter | |||
| This file implements a normalised biquad filter (second order IIR): | |||
| \f$ y[n] = b_0 x[n] + b_1 x[n-1] + b_2 x[n-2] - a_1 y[n-1] - a_2 y[n-2] \f$ | |||
| The filtfilt version runs the filter twice, forward and backward, to | |||
| compensate the phase shifting of the forward operation. | |||
| See also <a href="http://en.wikipedia.org/wiki/Digital_biquad_filter">Digital | |||
| biquad filter</a> on wikipedia. | |||
| \example temporal/test-biquad.c | |||
| */ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** set coefficients of a biquad filter | |||
| \param f filter object as returned by new_aubio_filter() | |||
| \param b0 forward filter coefficient | |||
| \param b1 forward filter coefficient | |||
| \param b2 forward filter coefficient | |||
| \param a1 feedback filter coefficient | |||
| \param a2 feedback filter coefficient | |||
| */ | |||
| uint_t aubio_filter_set_biquad (aubio_filter_t * f, lsmp_t b0, lsmp_t b1, | |||
| lsmp_t b2, lsmp_t a1, lsmp_t a2); | |||
| /** create biquad filter with `b0`, `b1`, `b2`, `a1`, `a2` coeffs | |||
| \param b0 forward filter coefficient | |||
| \param b1 forward filter coefficient | |||
| \param b2 forward filter coefficient | |||
| \param a1 feedback filter coefficient | |||
| \param a2 feedback filter coefficient | |||
| */ | |||
| aubio_filter_t *new_aubio_filter_biquad (lsmp_t b0, lsmp_t b1, lsmp_t b2, | |||
| lsmp_t a1, lsmp_t a2); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_FILTER_BIQUAD_H */ | |||
| @@ -0,0 +1,217 @@ | |||
| /* | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "types.h" | |||
| #include "fvec.h" | |||
| #include "lvec.h" | |||
| #include "temporal/filter.h" | |||
| #include "temporal/c_weighting.h" | |||
| uint_t | |||
| aubio_filter_set_c_weighting (aubio_filter_t * f, uint_t samplerate) | |||
| { | |||
| uint_t order; lsmp_t *a, *b; lvec_t *as, *bs; | |||
| if ((sint_t)samplerate <= 0) { | |||
| AUBIO_ERROR("aubio_filter: failed setting C-weighting with samplerate %d\n", samplerate); | |||
| return AUBIO_FAIL; | |||
| } | |||
| if (f == NULL) { | |||
| AUBIO_ERROR("aubio_filter: failed setting C-weighting with filter NULL\n"); | |||
| return AUBIO_FAIL; | |||
| } | |||
| order = aubio_filter_get_order (f); | |||
| if ( order != 5 ) { | |||
| AUBIO_ERROR ("aubio_filter: order of C-weighting filter must be 5, not %d\n", order); | |||
| return 1; | |||
| } | |||
| aubio_filter_set_samplerate (f, samplerate); | |||
| bs = aubio_filter_get_feedforward (f); | |||
| as = aubio_filter_get_feedback (f); | |||
| b = bs->data, a = as->data; | |||
| /* select coefficients according to sampling frequency */ | |||
| switch (samplerate) { | |||
| case 8000: | |||
| b[0] = 6.782173932405135552414776611840352416038513183593750000e-01; | |||
| b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[2] = -1.356434786481027110482955322368070483207702636718750000e+00; | |||
| b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[4] = 6.782173932405135552414776611840352416038513183593750000e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -6.589092811505605773447769024642184376716613769531250000e-01; | |||
| a[2] = -1.179445664897062595599663836765103042125701904296875000e+00; | |||
| a[3] = 4.243329729632123736848825501510873436927795410156250000e-01; | |||
| a[4] = 4.147270002091348328754349950031610205769538879394531250e-01; | |||
| break; | |||
| case 11025: | |||
| b[0] = 6.002357155402652244546857218665536493062973022460937500e-01; | |||
| b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[2] = -1.200471431080530448909371443733107298612594604492187500e+00; | |||
| b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[4] = 6.002357155402652244546857218665536493062973022460937500e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -8.705602141280316397242700077185872942209243774414062500e-01; | |||
| a[2] = -9.037199507150940336330791069485712796449661254882812500e-01; | |||
| a[3] = 4.758433040929530011275971901341108605265617370605468750e-01; | |||
| a[4] = 2.987653956523212417373258631414500996470451354980468750e-01; | |||
| break; | |||
| case 16000: | |||
| b[0] = 4.971057193673903418229542694461997598409652709960937500e-01; | |||
| b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[2] = -9.942114387347806836459085388923995196819305419921875000e-01; | |||
| b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[4] = 4.971057193673903418229542694461997598409652709960937500e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -1.162322939286873690889478893950581550598144531250000000e+00; | |||
| a[2] = -4.771961355734982701548574368644040077924728393554687500e-01; | |||
| a[3] = 4.736145114694704227886745684372726827859878540039062500e-01; | |||
| a[4] = 1.660337524309875301131711466950946487486362457275390625e-01; | |||
| break; | |||
| case 22050: | |||
| b[0] = 4.033381299002754549754001800465630367398262023925781250e-01; | |||
| b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[2] = -8.066762598005509099508003600931260734796524047851562500e-01; | |||
| b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[4] = 4.033381299002754549754001800465630367398262023925781250e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -1.449545371157945350404361306573264300823211669921875000e+00; | |||
| a[2] = -1.030104190885922088583015465701464563608169555664062500e-02; | |||
| a[3] = 3.881857047554073680828423675848171114921569824218750000e-01; | |||
| a[4] = 7.171589940116777917022972133054281584918498992919921875e-02; | |||
| break; | |||
| case 24000: | |||
| b[0] = 3.786678621924967069745093795063439756631851196289062500e-01; | |||
| b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[2] = -7.573357243849934139490187590126879513263702392578125000e-01; | |||
| b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[4] = 3.786678621924967069745093795063439756631851196289062500e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -1.529945307555420797029910318087786436080932617187500000e+00; | |||
| a[2] = 1.283553182116208835061854642844991758465766906738281250e-01; | |||
| a[3] = 3.494608072385725350272878131363540887832641601562500000e-01; | |||
| a[4] = 5.217291949300089520802359288609295617789030075073242188e-02; | |||
| break; | |||
| case 32000: | |||
| b[0] = 2.977986488230693340462096330156782642006874084472656250e-01; | |||
| b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[2] = -5.955972976461386680924192660313565284013748168945312500e-01; | |||
| b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[4] = 2.977986488230693340462096330156782642006874084472656250e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -1.812455387128179218336754274787381291389465332031250000e+00; | |||
| a[2] = 6.425013281155662614452239722595550119876861572265625000e-01; | |||
| a[3] = 1.619857574578579817448087396769551560282707214355468750e-01; | |||
| a[4] = 7.987649713547682189807019881300220731645822525024414062e-03; | |||
| break; | |||
| case 44100: | |||
| b[0] = 2.170085619492190254220531642204150557518005371093750000e-01; | |||
| b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[2] = -4.340171238984380508441063284408301115036010742187500000e-01; | |||
| b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[4] = 2.170085619492190254220531642204150557518005371093750000e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -2.134674963687040794013682898366823792457580566406250000e+00; | |||
| a[2] = 1.279333533236062692139967111870646476745605468750000000e+00; | |||
| a[3] = -1.495598460893957093453821016737492755055427551269531250e-01; | |||
| a[4] = 4.908700174624683852664386307651511742733418941497802734e-03; | |||
| break; | |||
| case 48000: | |||
| b[0] = 1.978871200263932761398422144338837824761867523193359375e-01; | |||
| b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[2] = -3.957742400527865522796844288677675649523735046386718750e-01; | |||
| b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[4] = 1.978871200263932761398422144338837824761867523193359375e-01; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -2.219172914052801814932536217384040355682373046875000000e+00; | |||
| a[2] = 1.455135878947171557129536267893854528665542602539062500e+00; | |||
| a[3] = -2.484960738877830532800317087094299495220184326171875000e-01; | |||
| a[4] = 1.253882314727246607977129144728678511455655097961425781e-02; | |||
| break; | |||
| case 88200: | |||
| b[0] = 9.221909851156021020734954163344809785485267639160156250e-02; | |||
| b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[2] = -1.844381970231204204146990832668961957097053527832031250e-01; | |||
| b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[4] = 9.221909851156021020734954163344809785485267639160156250e-02; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -2.785795902923448696952846148633398115634918212890625000e+00; | |||
| a[2] = 2.727736758747444145711824603495188057422637939453125000e+00; | |||
| a[3] = -1.097007502819661528548067508381791412830352783203125000e+00; | |||
| a[4] = 1.550674356752141103132913713125162757933139801025390625e-01; | |||
| break; | |||
| case 96000: | |||
| b[0] = 8.182864044979756834585771230194950476288795471191406250e-02; | |||
| b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[2] = -1.636572808995951366917154246038990095257759094238281250e-01; | |||
| b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[4] = 8.182864044979756834585771230194950476288795471191406250e-02; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -2.856378516857566829401093855267390608787536621093750000e+00; | |||
| a[2] = 2.897640237559524045707348705036565661430358886718750000e+00; | |||
| a[3] = -1.225265958339703198376469117647502571344375610351562500e+00; | |||
| a[4] = 1.840048283551226071530493300087982788681983947753906250e-01; | |||
| break; | |||
| case 192000: | |||
| b[0] = 2.784755468532278815940728122768632601946592330932617188e-02; | |||
| b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[2] = -5.569510937064557631881456245537265203893184661865234375e-02; | |||
| b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
| b[4] = 2.784755468532278815940728122768632601946592330932617188e-02; | |||
| a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
| a[1] = -3.333298856144166322224009491037577390670776367187500000e+00; | |||
| a[2] = 4.111467536240339448738723149290308356285095214843750000e+00; | |||
| a[3] = -2.222889041651291641699117462849244475364685058593750000e+00; | |||
| a[4] = 4.447204118126878991112960193277103826403617858886718750e-01; | |||
| break; | |||
| default: | |||
| AUBIO_ERROR ( "sampling rate of C-weighting filter is %d, should be one of\ | |||
| 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, 192000.\n", | |||
| samplerate ); | |||
| return 1; | |||
| } | |||
| return 0; | |||
| } | |||
| aubio_filter_t * new_aubio_filter_c_weighting (uint_t samplerate) { | |||
| aubio_filter_t * f = new_aubio_filter(5); | |||
| if (aubio_filter_set_c_weighting(f,samplerate) != AUBIO_OK) { | |||
| del_aubio_filter(f); | |||
| return NULL; | |||
| } | |||
| return f; | |||
| } | |||
| @@ -0,0 +1,88 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #ifndef AUBIO_FILTER_C_DESIGN_H | |||
| #define AUBIO_FILTER_C_DESIGN_H | |||
| /** \file | |||
| C-weighting filter coefficients | |||
| This file creates a C-weighting digital filter, which reduces low and high | |||
| frequencies and enhance the middle ones to reflect the ability of the human | |||
| hearing. | |||
| The implementation is based on the following standard: | |||
| - IEC/CD 1672: Electroacoustics-Sound Level Meters, IEC, Geneva, Nov. 1996, | |||
| for A- and C-weighting filters. | |||
| See also: | |||
| - <a href="http://en.wikipedia.org/wiki/A-weighting">A-Weighting on | |||
| Wikipedia</a> | |||
| - <a href="http://en.wikipedia.org/wiki/Weighting_filter">Weighting filter on | |||
| Wikipedia</a> | |||
| - <a href="http://www.mathworks.com/matlabcentral/fileexchange/69">Christophe | |||
| Couvreur's 'octave' toolbox</a> | |||
| The coefficients in this file have been computed using Christophe Couvreur's | |||
| scripts in octave 3.0 (debian package 1:3.0.5-6+b2 with octave-signal | |||
| 1.0.9-1+b1 on i386), with <pre> [b, a] = cdsign(1/Fs) </pre> for various | |||
| sampling frequencies (8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, | |||
| 88200, 96000, and 192000 Hz). | |||
| The sampling frequency should normally be higher than 20kHz, but most common | |||
| file sampling rates have been included for completeness. | |||
| \example temporal/test-c_weighting.c | |||
| */ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** create new C-design filter | |||
| \param samplerate sampling frequency of the signal to filter. Should be one of | |||
| 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, and | |||
| 192000 Hz | |||
| \return a new filter object | |||
| */ | |||
| aubio_filter_t *new_aubio_filter_c_weighting (uint_t samplerate); | |||
| /** set feedback and feedforward coefficients of a C-weighting filter | |||
| \param f filter object to get coefficients from | |||
| \param samplerate sampling frequency of the signal to filter. Should be one of | |||
| 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, and | |||
| 192000 Hz | |||
| */ | |||
| uint_t aubio_filter_set_c_weighting (aubio_filter_t * f, uint_t samplerate); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_FILTER_C_DESIGN_H */ | |||
| @@ -0,0 +1,163 @@ | |||
| /* | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| /* Requires lsmp_t to be long or double. float will NOT give reliable | |||
| * results */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "lvec.h" | |||
| #include "mathutils.h" | |||
| #include "temporal/filter.h" | |||
| struct _aubio_filter_t | |||
| { | |||
| uint_t order; | |||
| uint_t samplerate; | |||
| lvec_t *a; | |||
| lvec_t *b; | |||
| lvec_t *y; | |||
| lvec_t *x; | |||
| }; | |||
| void | |||
| aubio_filter_do_outplace (aubio_filter_t * f, const fvec_t * in, fvec_t * out) | |||
| { | |||
| fvec_copy (in, out); | |||
| aubio_filter_do (f, out); | |||
| } | |||
| void | |||
| aubio_filter_do (aubio_filter_t * f, fvec_t * in) | |||
| { | |||
| uint_t j, l, order = f->order; | |||
| lsmp_t *x = f->x->data; | |||
| lsmp_t *y = f->y->data; | |||
| lsmp_t *a = f->a->data; | |||
| lsmp_t *b = f->b->data; | |||
| for (j = 0; j < in->length; j++) { | |||
| /* new input */ | |||
| x[0] = KILL_DENORMAL (in->data[j]); | |||
| y[0] = b[0] * x[0]; | |||
| for (l = 1; l < order; l++) { | |||
| y[0] += b[l] * x[l]; | |||
| y[0] -= a[l] * y[l]; | |||
| } | |||
| /* new output */ | |||
| in->data[j] = y[0]; | |||
| /* store for next sample */ | |||
| for (l = order - 1; l > 0; l--) { | |||
| x[l] = x[l - 1]; | |||
| y[l] = y[l - 1]; | |||
| } | |||
| } | |||
| } | |||
| /* The rough way: reset memory of filter between each run to avoid end effects. */ | |||
| void | |||
| aubio_filter_do_filtfilt (aubio_filter_t * f, fvec_t * in, fvec_t * tmp) | |||
| { | |||
| uint_t j; | |||
| uint_t length = in->length; | |||
| /* apply filtering */ | |||
| aubio_filter_do (f, in); | |||
| aubio_filter_do_reset (f); | |||
| /* mirror */ | |||
| for (j = 0; j < length; j++) | |||
| tmp->data[length - j - 1] = in->data[j]; | |||
| /* apply filtering on mirrored */ | |||
| aubio_filter_do (f, tmp); | |||
| aubio_filter_do_reset (f); | |||
| /* invert back */ | |||
| for (j = 0; j < length; j++) | |||
| in->data[j] = tmp->data[length - j - 1]; | |||
| } | |||
| lvec_t * | |||
| aubio_filter_get_feedback (const aubio_filter_t * f) | |||
| { | |||
| return f->a; | |||
| } | |||
| lvec_t * | |||
| aubio_filter_get_feedforward (const aubio_filter_t * f) | |||
| { | |||
| return f->b; | |||
| } | |||
| uint_t | |||
| aubio_filter_get_order (const aubio_filter_t * f) | |||
| { | |||
| return f->order; | |||
| } | |||
| uint_t | |||
| aubio_filter_get_samplerate (const aubio_filter_t * f) | |||
| { | |||
| return f->samplerate; | |||
| } | |||
| uint_t | |||
| aubio_filter_set_samplerate (aubio_filter_t * f, uint_t samplerate) | |||
| { | |||
| f->samplerate = samplerate; | |||
| return AUBIO_OK; | |||
| } | |||
| void | |||
| aubio_filter_do_reset (aubio_filter_t * f) | |||
| { | |||
| lvec_zeros (f->x); | |||
| lvec_zeros (f->y); | |||
| } | |||
| aubio_filter_t * | |||
| new_aubio_filter (uint_t order) | |||
| { | |||
| aubio_filter_t *f = AUBIO_NEW (aubio_filter_t); | |||
| if ((sint_t)order < 1) { | |||
| AUBIO_FREE(f); | |||
| return NULL; | |||
| } | |||
| f->x = new_lvec (order); | |||
| f->y = new_lvec (order); | |||
| f->a = new_lvec (order); | |||
| f->b = new_lvec (order); | |||
| /* by default, samplerate is not set */ | |||
| f->samplerate = 0; | |||
| f->order = order; | |||
| /* set default to identity */ | |||
| f->a->data[0] = 1.; | |||
| f->b->data[0] = 1.; | |||
| return f; | |||
| } | |||
| void | |||
| del_aubio_filter (aubio_filter_t * f) | |||
| { | |||
| del_lvec (f->a); | |||
| del_lvec (f->b); | |||
| del_lvec (f->x); | |||
| del_lvec (f->y); | |||
| AUBIO_FREE (f); | |||
| return; | |||
| } | |||
| @@ -0,0 +1,176 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #ifndef AUBIO_FILTER_H | |||
| #define AUBIO_FILTER_H | |||
| /** \file | |||
| Digital filter | |||
| This object stores a digital filter of order \f$n\f$. | |||
| It contains the following data: | |||
| - \f$ n*1 b_i \f$ feedforward coefficients | |||
| - \f$ n*1 a_i \f$ feedback coefficients | |||
| - \f$ n*c x_i \f$ input signal | |||
| - \f$ n*c y_i \f$ output signal | |||
| For convenience, the samplerate of the input signal is also stored in the | |||
| object. | |||
| Feedforward and feedback parameters can be modified using | |||
| aubio_filter_get_feedback() and aubio_filter_get_feedforward(). | |||
| The function aubio_filter_do_outplace() computes the following output signal | |||
| \f$ y[n] \f$ from the input signal \f$ x[n] \f$: | |||
| \f{eqnarray*}{ | |||
| y[n] = b_0 x[n] & + & b_1 x[n-1] + b_2 x[n-2] + ... + b_P x[n-P] \\ | |||
| & - & a_1 y[n-1] - a_2 y[n-2] - ... - a_P y[n-P] \\ | |||
| \f} | |||
| The function aubio_filter_do() executes the same computation but modifies | |||
| directly the input signal (in-place). | |||
| The function aubio_filter_do_filtfilt() version runs the filter twice, first | |||
| forward then backward, to compensate with the phase shifting of the forward | |||
| operation. | |||
| Some convenience functions are provided: | |||
| - new_aubio_filter_a_weighting() and aubio_filter_set_a_weighting(), | |||
| - new_aubio_filter_c_weighting() and aubio_filter_set_c_weighting(). | |||
| - new_aubio_filter_biquad() and aubio_filter_set_biquad(). | |||
| \example temporal/test-filter.c | |||
| */ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** Digital filter | |||
| */ | |||
| typedef struct _aubio_filter_t aubio_filter_t; | |||
| /** filter input vector (in-place) | |||
| \param f filter object as returned by new_aubio_filter() | |||
| \param in input vector to filter | |||
| */ | |||
| void aubio_filter_do (aubio_filter_t * f, fvec_t * in); | |||
| /** filter input vector (out-of-place) | |||
| \param f filter object as returned by new_aubio_filter() | |||
| \param in input vector to filter | |||
| \param out output vector to store filtered input | |||
| */ | |||
| void aubio_filter_do_outplace (aubio_filter_t * f, const fvec_t * in, fvec_t * out); | |||
| /** filter input vector forward and backward | |||
| \param f ::aubio_filter_t object as returned by new_aubio_filter() | |||
| \param in ::fvec_t input vector to filter | |||
| \param tmp memory space to use for computation | |||
| */ | |||
| void aubio_filter_do_filtfilt (aubio_filter_t * f, fvec_t * in, fvec_t * tmp); | |||
| /** returns a pointer to feedback coefficients \f$ a_i \f$ | |||
| \param f filter object to get parameters from | |||
| \return a pointer to the \f$ a_0 ... a_i ... a_P \f$ coefficients | |||
| */ | |||
| lvec_t *aubio_filter_get_feedback (const aubio_filter_t * f); | |||
| /** returns a pointer to feedforward coefficients \f$ b_i \f$ | |||
| \param f filter object to get coefficients from | |||
| \return a pointer to the \f$ b_0 ... b_i ... b_P \f$ coefficients | |||
| */ | |||
| lvec_t *aubio_filter_get_feedforward (const aubio_filter_t * f); | |||
| /** get order of the filter | |||
| \param f filter to get order from | |||
| \return the order of the filter | |||
| */ | |||
| uint_t aubio_filter_get_order (const aubio_filter_t * f); | |||
| /** get sampling rate of the filter | |||
| \param f filter to get sampling rate from | |||
| \return the sampling rate of the filter, in Hz | |||
| */ | |||
| uint_t aubio_filter_get_samplerate (const aubio_filter_t * f); | |||
| /** get sampling rate of the filter | |||
| \param f filter to get sampling rate from | |||
| \param samplerate sample rate to set the filter to | |||
| \return the sampling rate of the filter, in Hz | |||
| */ | |||
| uint_t aubio_filter_set_samplerate (aubio_filter_t * f, uint_t samplerate); | |||
| /** reset filter memory | |||
| \param f filter object as returned by new_aubio_filter() | |||
| */ | |||
| void aubio_filter_do_reset (aubio_filter_t * f); | |||
| /** create new filter object | |||
| This function creates a new ::aubio_filter_t object, given the order of the | |||
| filter. | |||
| \param order order of the filter (number of coefficients) | |||
| \return the newly created filter object | |||
| */ | |||
| aubio_filter_t *new_aubio_filter (uint_t order); | |||
| /** delete a filter object | |||
| \param f filter object to delete | |||
| */ | |||
| void del_aubio_filter (aubio_filter_t * f); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_FILTER_H */ | |||
| @@ -0,0 +1,100 @@ | |||
| /* | |||
| Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "fvec.h" | |||
| #include "temporal/resampler.h" | |||
| #ifdef HAVE_SAMPLERATE | |||
| #if HAVE_AUBIO_DOUBLE | |||
| #error "Should not use libsamplerate with aubio in double precision" | |||
| #endif | |||
| #include <samplerate.h> /* from libsamplerate */ | |||
| struct _aubio_resampler_t | |||
| { | |||
| SRC_DATA *proc; | |||
| SRC_STATE *stat; | |||
| smpl_t ratio; | |||
| uint_t type; | |||
| }; | |||
| aubio_resampler_t * | |||
| new_aubio_resampler (smpl_t ratio, uint_t type) | |||
| { | |||
| aubio_resampler_t *s = AUBIO_NEW (aubio_resampler_t); | |||
| int error = 0; | |||
| s->stat = src_new (type, 1, &error); /* only one channel */ | |||
| if (error) { | |||
| AUBIO_ERR ("Failed creating resampler: %s\n", src_strerror (error)); | |||
| del_aubio_resampler(s); | |||
| return NULL; | |||
| } | |||
| s->proc = AUBIO_NEW (SRC_DATA); | |||
| s->ratio = ratio; | |||
| return s; | |||
| } | |||
| void | |||
| del_aubio_resampler (aubio_resampler_t * s) | |||
| { | |||
| if (s->stat) src_delete (s->stat); | |||
| AUBIO_FREE (s->proc); | |||
| AUBIO_FREE (s); | |||
| } | |||
| void | |||
| aubio_resampler_do (aubio_resampler_t * s, const fvec_t * input, fvec_t * output) | |||
| { | |||
| s->proc->input_frames = input->length; | |||
| s->proc->output_frames = output->length; | |||
| s->proc->src_ratio = (double) s->ratio; | |||
| /* make SRC_PROC data point to input outputs */ | |||
| s->proc->data_in = (float *) input->data; | |||
| s->proc->data_out = (float *) output->data; | |||
| /* do resampling */ | |||
| src_process (s->stat, s->proc); | |||
| } | |||
| #else | |||
| struct _aubio_resampler_t | |||
| { | |||
| void *dummy; | |||
| }; | |||
| aubio_resampler_t * | |||
| new_aubio_resampler (smpl_t ratio UNUSED, uint_t type UNUSED) | |||
| { | |||
| AUBIO_ERR ("aubio was not compiled with libsamplerate\n"); | |||
| return NULL; | |||
| } | |||
| void | |||
| del_aubio_resampler (aubio_resampler_t * s UNUSED) | |||
| { | |||
| } | |||
| void | |||
| aubio_resampler_do (aubio_resampler_t * s UNUSED, const fvec_t * input UNUSED, fvec_t * output UNUSED) | |||
| { | |||
| } | |||
| #endif /* HAVE_SAMPLERATE */ | |||
| @@ -0,0 +1,65 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #ifndef AUBIO_RESAMPLER_H | |||
| #define AUBIO_RESAMPLER_H | |||
| /** \file | |||
| Resampling object | |||
| This object resamples an input vector into an output vector using | |||
| libsamplerate. See http://www.mega-nerd.com/SRC/ | |||
| */ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** resampler object */ | |||
| typedef struct _aubio_resampler_t aubio_resampler_t; | |||
| /** create resampler object | |||
| \param ratio output_sample_rate / input_sample_rate | |||
| \param type libsamplerate resampling type, see http://www.mega-nerd.com/SRC/api_misc.html#Converters | |||
| */ | |||
| aubio_resampler_t *new_aubio_resampler (smpl_t ratio, uint_t type); | |||
| /** delete resampler object */ | |||
| void del_aubio_resampler (aubio_resampler_t * s); | |||
| /** resample input in output | |||
| \param s resampler object | |||
| \param input input buffer of size N | |||
| \param output output buffer of size N*ratio | |||
| */ | |||
| void aubio_resampler_do (aubio_resampler_t * s, const fvec_t * input, | |||
| fvec_t * output); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_RESAMPLER_H */ | |||
| @@ -0,0 +1,70 @@ | |||
| /* | |||
| Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #ifndef AUBIO_TYPES_H | |||
| #define AUBIO_TYPES_H | |||
| /** \file | |||
| Definition of data types used in aubio | |||
| */ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| #ifndef HAVE_AUBIO_DOUBLE | |||
| /** defined to 1 if aubio is compiled in double precision */ | |||
| #define HAVE_AUBIO_DOUBLE 0 | |||
| #endif | |||
| /** short sample format (32 or 64 bits) */ | |||
| #if !HAVE_AUBIO_DOUBLE | |||
| typedef float smpl_t; | |||
| /** print format for sample in single precision */ | |||
| #define AUBIO_SMPL_FMT "%f" | |||
| #else | |||
| typedef double smpl_t; | |||
| /** print format for double in single precision */ | |||
| #define AUBIO_SMPL_FMT "%lf" | |||
| #endif | |||
| /** long sample format (64 bits or more) */ | |||
| #if !HAVE_AUBIO_DOUBLE | |||
| typedef double lsmp_t; | |||
| /** print format for sample in double precision */ | |||
| #define AUBIO_LSMP_FMT "%lf" | |||
| #else | |||
| typedef long double lsmp_t; | |||
| /** print format for double in double precision */ | |||
| #define AUBIO_LSMP_FMT "%Lf" | |||
| #endif | |||
| /** unsigned integer */ | |||
| typedef unsigned int uint_t; | |||
| /** signed integer */ | |||
| typedef int sint_t; | |||
| /** character */ | |||
| typedef char char_t; | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_TYPES_H */ | |||
| @@ -0,0 +1,92 @@ | |||
| /* | |||
| Copyright (C) 2016 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #include "aubio_priv.h" | |||
| #include "log.h" | |||
| /** array of pointers to logging functions, one per level */ | |||
| static aubio_log_function_t aubio_log_function[AUBIO_LOG_LAST_LEVEL]; | |||
| /** array of pointers to closure passed to logging functions, one per level */ | |||
| static void* aubio_log_user_data[AUBIO_LOG_LAST_LEVEL]; | |||
| /** buffer for logging messages */ | |||
| static char aubio_log_buffer[512]; | |||
| /** private function used by default by logging functions */ | |||
| void | |||
| aubio_default_log(sint_t level, const char_t *message, void * data UNUSED) | |||
| { | |||
| FILE *out; | |||
| out = stdout; | |||
| if (level == AUBIO_LOG_ERR || level == AUBIO_LOG_DBG || level == AUBIO_LOG_WRN) { | |||
| out = stderr; | |||
| } | |||
| fprintf(out, "%s", message); | |||
| //fflush(out); | |||
| } | |||
| uint_t | |||
| aubio_log(sint_t level, const char_t *fmt, ...) | |||
| { | |||
| aubio_log_function_t fun = NULL; | |||
| va_list args; | |||
| va_start(args, fmt); | |||
| vsnprintf(aubio_log_buffer, sizeof(aubio_log_buffer), fmt, args); | |||
| va_end(args); | |||
| if ((level >= 0) && (level < AUBIO_LOG_LAST_LEVEL)) { | |||
| fun = aubio_log_function[level]; | |||
| if (fun != NULL) { | |||
| (*fun)(level, aubio_log_buffer, aubio_log_user_data[level]); | |||
| } else { | |||
| aubio_default_log(level, aubio_log_buffer, NULL); | |||
| } | |||
| } | |||
| return AUBIO_FAIL; | |||
| } | |||
| void | |||
| aubio_log_reset(void) | |||
| { | |||
| uint_t i = 0; | |||
| for (i = 0; i < AUBIO_LOG_LAST_LEVEL; i++) { | |||
| aubio_log_set_level_function(i, aubio_default_log, NULL); | |||
| } | |||
| } | |||
| aubio_log_function_t | |||
| aubio_log_set_level_function(sint_t level, aubio_log_function_t fun, void * data) | |||
| { | |||
| aubio_log_function_t old = NULL; | |||
| if ((level >= 0) && (level < AUBIO_LOG_LAST_LEVEL)) { | |||
| old = aubio_log_function[level]; | |||
| aubio_log_function[level] = fun; | |||
| aubio_log_user_data[level] = data; | |||
| } | |||
| return old; | |||
| } | |||
| void | |||
| aubio_log_set_function(aubio_log_function_t fun, void * data) { | |||
| uint_t i = 0; | |||
| for (i = 0; i < AUBIO_LOG_LAST_LEVEL; i++) { | |||
| aubio_log_set_level_function(i, fun, data); | |||
| } | |||
| } | |||
| @@ -0,0 +1,99 @@ | |||
| /* | |||
| Copyright (C) 2016 Paul Brossier <piem@aubio.org> | |||
| This file is part of aubio. | |||
| aubio 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. | |||
| aubio is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
| */ | |||
| #ifndef AUBIO_LOG_H | |||
| #define AUBIO_LOG_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** \file | |||
| Logging features | |||
| This file specifies ::aubio_log_set_function and | |||
| ::aubio_log_set_level_function, which let you define one or several custom | |||
| logging functions to redirect warnings and errors from aubio to your | |||
| application. The custom function should have the prototype defined in | |||
| ::aubio_log_function_t. | |||
| After a call to ::aubio_log_set_level_function, ::aubio_log_reset can be used | |||
| to reset each logging functions to the default ones. | |||
| \example utils/test-log.c | |||
| */ | |||
| /** list of logging levels */ | |||
| enum aubio_log_level { | |||
| AUBIO_LOG_ERR, /**< critical errors */ | |||
| AUBIO_LOG_INF, /**< infos */ | |||
| AUBIO_LOG_MSG, /**< general messages */ | |||
| AUBIO_LOG_DBG, /**< debug messages */ | |||
| AUBIO_LOG_WRN, /**< warnings */ | |||
| AUBIO_LOG_LAST_LEVEL, /**< number of valid levels */ | |||
| }; | |||
| /** Logging function prototype, to be passed to ::aubio_log_set_function | |||
| \param level log level | |||
| \param message text to log | |||
| \param data optional closure used by the callback | |||
| See @ref utils/test-log.c for an example of logging function. | |||
| */ | |||
| typedef void (*aubio_log_function_t)(sint_t level, const char_t *message, void | |||
| *data); | |||
| /** Set logging function for all levels | |||
| \param fun the function to be used to log, of type ::aubio_log_function_t | |||
| \param data optional closure to be passed to the function (can be NULL if | |||
| nothing to pass) | |||
| */ | |||
| void aubio_log_set_function(aubio_log_function_t fun, void* data); | |||
| /** Set logging function for a given level | |||
| \param level the level for which to set the logging function | |||
| \param fun the function to be used to log, of type ::aubio_log_function_t | |||
| \param data optional closure to be passed to the function (can be NULL if | |||
| nothing to pass) | |||
| */ | |||
| aubio_log_function_t aubio_log_set_level_function(sint_t level, | |||
| aubio_log_function_t fun, void* data); | |||
| /** Reset all logging functions to the default one | |||
| After calling this function, the default logging function will be used to | |||
| print error, warning, normal, and debug messages to `stdout` or `stderr`. | |||
| */ | |||
| void aubio_log_reset(void); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* AUBIO_LOG_H */ | |||
| @@ -120,7 +120,7 @@ struct AudioToCVPitch : Module { | |||
| if (detectedPitchInHz > 0.f && pitchConfidence >= params[PARAM_CONFIDENCETHRESHOLD].getValue() * 0.01f) | |||
| { | |||
| const float linearPitch = 12.f * (log2f(detectedPitchInHz / 440.f) + octave - 1) + 69.f; | |||
| const float linearPitch = 12.f * (log2f(detectedPitchInHz / 440.f) + octave - 5) + 69.f; | |||
| cvPitch = std::max(-10.f, std::min(10.f, linearPitch * (1.f/12.f))); | |||
| lastKnownPitchInHz = detectedPitchInHz; | |||
| cvSignal = 10.f; | |||