@@ -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; | ||||