| @@ -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) | 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))); | cvPitch = std::max(-10.f, std::min(10.f, linearPitch * (1.f/12.f))); | ||||
| lastKnownPitchInHz = detectedPitchInHz; | lastKnownPitchInHz = detectedPitchInHz; | ||||
| cvSignal = 10.f; | cvSignal = 10.f; | ||||