@@ -0,0 +1,674 @@ | |||
GNU GENERAL PUBLIC LICENSE | |||
Version 3, 29 June 2007 | |||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> | |||
Everyone is permitted to copy and distribute verbatim copies | |||
of this license document, but changing it is not allowed. | |||
Preamble | |||
The GNU General Public License is a free, copyleft license for | |||
software and other kinds of works. | |||
The licenses for most software and other practical works are designed | |||
to take away your freedom to share and change the works. By contrast, | |||
the GNU General Public License is intended to guarantee your freedom to | |||
share and change all versions of a program--to make sure it remains free | |||
software for all its users. We, the Free Software Foundation, use the | |||
GNU General Public License for most of our software; it applies also to | |||
any other work released this way by its authors. You can apply it to | |||
your programs, too. | |||
When we speak of free software, we are referring to freedom, not | |||
price. Our General Public Licenses are designed to make sure that you | |||
have the freedom to distribute copies of free software (and charge for | |||
them if you wish), that you receive source code or can get it if you | |||
want it, that you can change the software or use pieces of it in new | |||
free programs, and that you know you can do these things. | |||
To protect your rights, we need to prevent others from denying you | |||
these rights or asking you to surrender the rights. Therefore, you have | |||
certain responsibilities if you distribute copies of the software, or if | |||
you modify it: responsibilities to respect the freedom of others. | |||
For example, if you distribute copies of such a program, whether | |||
gratis or for a fee, you must pass on to the recipients the same | |||
freedoms that you received. You must make sure that they, too, receive | |||
or can get the source code. And you must show them these terms so they | |||
know their rights. | |||
Developers that use the GNU GPL protect your rights with two steps: | |||
(1) assert copyright on the software, and (2) offer you this License | |||
giving you legal permission to copy, distribute and/or modify it. | |||
For the developers' and authors' protection, the GPL clearly explains | |||
that there is no warranty for this free software. For both users' and | |||
authors' sake, the GPL requires that modified versions be marked as | |||
changed, so that their problems will not be attributed erroneously to | |||
authors of previous versions. | |||
Some devices are designed to deny users access to install or run | |||
modified versions of the software inside them, although the manufacturer | |||
can do so. This is fundamentally incompatible with the aim of | |||
protecting users' freedom to change the software. The systematic | |||
pattern of such abuse occurs in the area of products for individuals to | |||
use, which is precisely where it is most unacceptable. Therefore, we | |||
have designed this version of the GPL to prohibit the practice for those | |||
products. If such problems arise substantially in other domains, we | |||
stand ready to extend this provision to those domains in future versions | |||
of the GPL, as needed to protect the freedom of users. | |||
Finally, every program is threatened constantly by software patents. | |||
States should not allow patents to restrict development and use of | |||
software on general-purpose computers, but in those that do, we wish to | |||
avoid the special danger that patents applied to a free program could | |||
make it effectively proprietary. To prevent this, the GPL assures that | |||
patents cannot be used to render the program non-free. | |||
The precise terms and conditions for copying, distribution and | |||
modification follow. | |||
TERMS AND CONDITIONS | |||
0. Definitions. | |||
"This License" refers to version 3 of the GNU General Public License. | |||
"Copyright" also means copyright-like laws that apply to other kinds of | |||
works, such as semiconductor masks. | |||
"The Program" refers to any copyrightable work licensed under this | |||
License. Each licensee is addressed as "you". "Licensees" and | |||
"recipients" may be individuals or organizations. | |||
To "modify" a work means to copy from or adapt all or part of the work | |||
in a fashion requiring copyright permission, other than the making of an | |||
exact copy. The resulting work is called a "modified version" of the | |||
earlier work or a work "based on" the earlier work. | |||
A "covered work" means either the unmodified Program or a work based | |||
on the Program. | |||
To "propagate" a work means to do anything with it that, without | |||
permission, would make you directly or secondarily liable for | |||
infringement under applicable copyright law, except executing it on a | |||
computer or modifying a private copy. Propagation includes copying, | |||
distribution (with or without modification), making available to the | |||
public, and in some countries other activities as well. | |||
To "convey" a work means any kind of propagation that enables other | |||
parties to make or receive copies. Mere interaction with a user through | |||
a computer network, with no transfer of a copy, is not conveying. | |||
An interactive user interface displays "Appropriate Legal Notices" | |||
to the extent that it includes a convenient and prominently visible | |||
feature that (1) displays an appropriate copyright notice, and (2) | |||
tells the user that there is no warranty for the work (except to the | |||
extent that warranties are provided), that licensees may convey the | |||
work under this License, and how to view a copy of this License. If | |||
the interface presents a list of user commands or options, such as a | |||
menu, a prominent item in the list meets this criterion. | |||
1. Source Code. | |||
The "source code" for a work means the preferred form of the work | |||
for making modifications to it. "Object code" means any non-source | |||
form of a work. | |||
A "Standard Interface" means an interface that either is an official | |||
standard defined by a recognized standards body, or, in the case of | |||
interfaces specified for a particular programming language, one that | |||
is widely used among developers working in that language. | |||
The "System Libraries" of an executable work include anything, other | |||
than the work as a whole, that (a) is included in the normal form of | |||
packaging a Major Component, but which is not part of that Major | |||
Component, and (b) serves only to enable use of the work with that | |||
Major Component, or to implement a Standard Interface for which an | |||
implementation is available to the public in source code form. A | |||
"Major Component", in this context, means a major essential component | |||
(kernel, window system, and so on) of the specific operating system | |||
(if any) on which the executable work runs, or a compiler used to | |||
produce the work, or an object code interpreter used to run it. | |||
The "Corresponding Source" for a work in object code form means all | |||
the source code needed to generate, install, and (for an executable | |||
work) run the object code and to modify the work, including scripts to | |||
control those activities. However, it does not include the work's | |||
System Libraries, or general-purpose tools or generally available free | |||
programs which are used unmodified in performing those activities but | |||
which are not part of the work. For example, Corresponding Source | |||
includes interface definition files associated with source files for | |||
the work, and the source code for shared libraries and dynamically | |||
linked subprograms that the work is specifically designed to require, | |||
such as by intimate data communication or control flow between those | |||
subprograms and other parts of the work. | |||
The Corresponding Source need not include anything that users | |||
can regenerate automatically from other parts of the Corresponding | |||
Source. | |||
The Corresponding Source for a work in source code form is that | |||
same work. | |||
2. Basic Permissions. | |||
All rights granted under this License are granted for the term of | |||
copyright on the Program, and are irrevocable provided the stated | |||
conditions are met. This License explicitly affirms your unlimited | |||
permission to run the unmodified Program. The output from running a | |||
covered work is covered by this License only if the output, given its | |||
content, constitutes a covered work. This License acknowledges your | |||
rights of fair use or other equivalent, as provided by copyright law. | |||
You may make, run and propagate covered works that you do not | |||
convey, without conditions so long as your license otherwise remains | |||
in force. You may convey covered works to others for the sole purpose | |||
of having them make modifications exclusively for you, or provide you | |||
with facilities for running those works, provided that you comply with | |||
the terms of this License in conveying all material for which you do | |||
not control copyright. Those thus making or running the covered works | |||
for you must do so exclusively on your behalf, under your direction | |||
and control, on terms that prohibit them from making any copies of | |||
your copyrighted material outside their relationship with you. | |||
Conveying under any other circumstances is permitted solely under | |||
the conditions stated below. Sublicensing is not allowed; section 10 | |||
makes it unnecessary. | |||
3. Protecting Users' Legal Rights From Anti-Circumvention Law. | |||
No covered work shall be deemed part of an effective technological | |||
measure under any applicable law fulfilling obligations under article | |||
11 of the WIPO copyright treaty adopted on 20 December 1996, or | |||
similar laws prohibiting or restricting circumvention of such | |||
measures. | |||
When you convey a covered work, you waive any legal power to forbid | |||
circumvention of technological measures to the extent such circumvention | |||
is effected by exercising rights under this License with respect to | |||
the covered work, and you disclaim any intention to limit operation or | |||
modification of the work as a means of enforcing, against the work's | |||
users, your or third parties' legal rights to forbid circumvention of | |||
technological measures. | |||
4. Conveying Verbatim Copies. | |||
You may convey verbatim copies of the Program's source code as you | |||
receive it, in any medium, provided that you conspicuously and | |||
appropriately publish on each copy an appropriate copyright notice; | |||
keep intact all notices stating that this License and any | |||
non-permissive terms added in accord with section 7 apply to the code; | |||
keep intact all notices of the absence of any warranty; and give all | |||
recipients a copy of this License along with the Program. | |||
You may charge any price or no price for each copy that you convey, | |||
and you may offer support or warranty protection for a fee. | |||
5. Conveying Modified Source Versions. | |||
You may convey a work based on the Program, or the modifications to | |||
produce it from the Program, in the form of source code under the | |||
terms of section 4, provided that you also meet all of these conditions: | |||
a) The work must carry prominent notices stating that you modified | |||
it, and giving a relevant date. | |||
b) The work must carry prominent notices stating that it is | |||
released under this License and any conditions added under section | |||
7. This requirement modifies the requirement in section 4 to | |||
"keep intact all notices". | |||
c) You must license the entire work, as a whole, under this | |||
License to anyone who comes into possession of a copy. This | |||
License will therefore apply, along with any applicable section 7 | |||
additional terms, to the whole of the work, and all its parts, | |||
regardless of how they are packaged. This License gives no | |||
permission to license the work in any other way, but it does not | |||
invalidate such permission if you have separately received it. | |||
d) If the work has interactive user interfaces, each must display | |||
Appropriate Legal Notices; however, if the Program has interactive | |||
interfaces that do not display Appropriate Legal Notices, your | |||
work need not make them do so. | |||
A compilation of a covered work with other separate and independent | |||
works, which are not by their nature extensions of the covered work, | |||
and which are not combined with it such as to form a larger program, | |||
in or on a volume of a storage or distribution medium, is called an | |||
"aggregate" if the compilation and its resulting copyright are not | |||
used to limit the access or legal rights of the compilation's users | |||
beyond what the individual works permit. Inclusion of a covered work | |||
in an aggregate does not cause this License to apply to the other | |||
parts of the aggregate. | |||
6. Conveying Non-Source Forms. | |||
You may convey a covered work in object code form under the terms | |||
of sections 4 and 5, provided that you also convey the | |||
machine-readable Corresponding Source under the terms of this License, | |||
in one of these ways: | |||
a) Convey the object code in, or embodied in, a physical product | |||
(including a physical distribution medium), accompanied by the | |||
Corresponding Source fixed on a durable physical medium | |||
customarily used for software interchange. | |||
b) Convey the object code in, or embodied in, a physical product | |||
(including a physical distribution medium), accompanied by a | |||
written offer, valid for at least three years and valid for as | |||
long as you offer spare parts or customer support for that product | |||
model, to give anyone who possesses the object code either (1) a | |||
copy of the Corresponding Source for all the software in the | |||
product that is covered by this License, on a durable physical | |||
medium customarily used for software interchange, for a price no | |||
more than your reasonable cost of physically performing this | |||
conveying of source, or (2) access to copy the | |||
Corresponding Source from a network server at no charge. | |||
c) Convey individual copies of the object code with a copy of the | |||
written offer to provide the Corresponding Source. This | |||
alternative is allowed only occasionally and noncommercially, and | |||
only if you received the object code with such an offer, in accord | |||
with subsection 6b. | |||
d) Convey the object code by offering access from a designated | |||
place (gratis or for a charge), and offer equivalent access to the | |||
Corresponding Source in the same way through the same place at no | |||
further charge. You need not require recipients to copy the | |||
Corresponding Source along with the object code. If the place to | |||
copy the object code is a network server, the Corresponding Source | |||
may be on a different server (operated by you or a third party) | |||
that supports equivalent copying facilities, provided you maintain | |||
clear directions next to the object code saying where to find the | |||
Corresponding Source. Regardless of what server hosts the | |||
Corresponding Source, you remain obligated to ensure that it is | |||
available for as long as needed to satisfy these requirements. | |||
e) Convey the object code using peer-to-peer transmission, provided | |||
you inform other peers where the object code and Corresponding | |||
Source of the work are being offered to the general public at no | |||
charge under subsection 6d. | |||
A separable portion of the object code, whose source code is excluded | |||
from the Corresponding Source as a System Library, need not be | |||
included in conveying the object code work. | |||
A "User Product" is either (1) a "consumer product", which means any | |||
tangible personal property which is normally used for personal, family, | |||
or household purposes, or (2) anything designed or sold for incorporation | |||
into a dwelling. In determining whether a product is a consumer product, | |||
doubtful cases shall be resolved in favor of coverage. For a particular | |||
product received by a particular user, "normally used" refers to a | |||
typical or common use of that class of product, regardless of the status | |||
of the particular user or of the way in which the particular user | |||
actually uses, or expects or is expected to use, the product. A product | |||
is a consumer product regardless of whether the product has substantial | |||
commercial, industrial or non-consumer uses, unless such uses represent | |||
the only significant mode of use of the product. | |||
"Installation Information" for a User Product means any methods, | |||
procedures, authorization keys, or other information required to install | |||
and execute modified versions of a covered work in that User Product from | |||
a modified version of its Corresponding Source. The information must | |||
suffice to ensure that the continued functioning of the modified object | |||
code is in no case prevented or interfered with solely because | |||
modification has been made. | |||
If you convey an object code work under this section in, or with, or | |||
specifically for use in, a User Product, and the conveying occurs as | |||
part of a transaction in which the right of possession and use of the | |||
User Product is transferred to the recipient in perpetuity or for a | |||
fixed term (regardless of how the transaction is characterized), the | |||
Corresponding Source conveyed under this section must be accompanied | |||
by the Installation Information. But this requirement does not apply | |||
if neither you nor any third party retains the ability to install | |||
modified object code on the User Product (for example, the work has | |||
been installed in ROM). | |||
The requirement to provide Installation Information does not include a | |||
requirement to continue to provide support service, warranty, or updates | |||
for a work that has been modified or installed by the recipient, or for | |||
the User Product in which it has been modified or installed. Access to a | |||
network may be denied when the modification itself materially and | |||
adversely affects the operation of the network or violates the rules and | |||
protocols for communication across the network. | |||
Corresponding Source conveyed, and Installation Information provided, | |||
in accord with this section must be in a format that is publicly | |||
documented (and with an implementation available to the public in | |||
source code form), and must require no special password or key for | |||
unpacking, reading or copying. | |||
7. Additional Terms. | |||
"Additional permissions" are terms that supplement the terms of this | |||
License by making exceptions from one or more of its conditions. | |||
Additional permissions that are applicable to the entire Program shall | |||
be treated as though they were included in this License, to the extent | |||
that they are valid under applicable law. If additional permissions | |||
apply only to part of the Program, that part may be used separately | |||
under those permissions, but the entire Program remains governed by | |||
this License without regard to the additional permissions. | |||
When you convey a copy of a covered work, you may at your option | |||
remove any additional permissions from that copy, or from any part of | |||
it. (Additional permissions may be written to require their own | |||
removal in certain cases when you modify the work.) You may place | |||
additional permissions on material, added by you to a covered work, | |||
for which you have or can give appropriate copyright permission. | |||
Notwithstanding any other provision of this License, for material you | |||
add to a covered work, you may (if authorized by the copyright holders of | |||
that material) supplement the terms of this License with terms: | |||
a) Disclaiming warranty or limiting liability differently from the | |||
terms of sections 15 and 16 of this License; or | |||
b) Requiring preservation of specified reasonable legal notices or | |||
author attributions in that material or in the Appropriate Legal | |||
Notices displayed by works containing it; or | |||
c) Prohibiting misrepresentation of the origin of that material, or | |||
requiring that modified versions of such material be marked in | |||
reasonable ways as different from the original version; or | |||
d) Limiting the use for publicity purposes of names of licensors or | |||
authors of the material; or | |||
e) Declining to grant rights under trademark law for use of some | |||
trade names, trademarks, or service marks; or | |||
f) Requiring indemnification of licensors and authors of that | |||
material by anyone who conveys the material (or modified versions of | |||
it) with contractual assumptions of liability to the recipient, for | |||
any liability that these contractual assumptions directly impose on | |||
those licensors and authors. | |||
All other non-permissive additional terms are considered "further | |||
restrictions" within the meaning of section 10. If the Program as you | |||
received it, or any part of it, contains a notice stating that it is | |||
governed by this License along with a term that is a further | |||
restriction, you may remove that term. If a license document contains | |||
a further restriction but permits relicensing or conveying under this | |||
License, you may add to a covered work material governed by the terms | |||
of that license document, provided that the further restriction does | |||
not survive such relicensing or conveying. | |||
If you add terms to a covered work in accord with this section, you | |||
must place, in the relevant source files, a statement of the | |||
additional terms that apply to those files, or a notice indicating | |||
where to find the applicable terms. | |||
Additional terms, permissive or non-permissive, may be stated in the | |||
form of a separately written license, or stated as exceptions; | |||
the above requirements apply either way. | |||
8. Termination. | |||
You may not propagate or modify a covered work except as expressly | |||
provided under this License. Any attempt otherwise to propagate or | |||
modify it is void, and will automatically terminate your rights under | |||
this License (including any patent licenses granted under the third | |||
paragraph of section 11). | |||
However, if you cease all violation of this License, then your | |||
license from a particular copyright holder is reinstated (a) | |||
provisionally, unless and until the copyright holder explicitly and | |||
finally terminates your license, and (b) permanently, if the copyright | |||
holder fails to notify you of the violation by some reasonable means | |||
prior to 60 days after the cessation. | |||
Moreover, your license from a particular copyright holder is | |||
reinstated permanently if the copyright holder notifies you of the | |||
violation by some reasonable means, this is the first time you have | |||
received notice of violation of this License (for any work) from that | |||
copyright holder, and you cure the violation prior to 30 days after | |||
your receipt of the notice. | |||
Termination of your rights under this section does not terminate the | |||
licenses of parties who have received copies or rights from you under | |||
this License. If your rights have been terminated and not permanently | |||
reinstated, you do not qualify to receive new licenses for the same | |||
material under section 10. | |||
9. Acceptance Not Required for Having Copies. | |||
You are not required to accept this License in order to receive or | |||
run a copy of the Program. Ancillary propagation of a covered work | |||
occurring solely as a consequence of using peer-to-peer transmission | |||
to receive a copy likewise does not require acceptance. However, | |||
nothing other than this License grants you permission to propagate or | |||
modify any covered work. These actions infringe copyright if you do | |||
not accept this License. Therefore, by modifying or propagating a | |||
covered work, you indicate your acceptance of this License to do so. | |||
10. Automatic Licensing of Downstream Recipients. | |||
Each time you convey a covered work, the recipient automatically | |||
receives a license from the original licensors, to run, modify and | |||
propagate that work, subject to this License. You are not responsible | |||
for enforcing compliance by third parties with this License. | |||
An "entity transaction" is a transaction transferring control of an | |||
organization, or substantially all assets of one, or subdividing an | |||
organization, or merging organizations. If propagation of a covered | |||
work results from an entity transaction, each party to that | |||
transaction who receives a copy of the work also receives whatever | |||
licenses to the work the party's predecessor in interest had or could | |||
give under the previous paragraph, plus a right to possession of the | |||
Corresponding Source of the work from the predecessor in interest, if | |||
the predecessor has it or can get it with reasonable efforts. | |||
You may not impose any further restrictions on the exercise of the | |||
rights granted or affirmed under this License. For example, you may | |||
not impose a license fee, royalty, or other charge for exercise of | |||
rights granted under this License, and you may not initiate litigation | |||
(including a cross-claim or counterclaim in a lawsuit) alleging that | |||
any patent claim is infringed by making, using, selling, offering for | |||
sale, or importing the Program or any portion of it. | |||
11. Patents. | |||
A "contributor" is a copyright holder who authorizes use under this | |||
License of the Program or a work on which the Program is based. The | |||
work thus licensed is called the contributor's "contributor version". | |||
A contributor's "essential patent claims" are all patent claims | |||
owned or controlled by the contributor, whether already acquired or | |||
hereafter acquired, that would be infringed by some manner, permitted | |||
by this License, of making, using, or selling its contributor version, | |||
but do not include claims that would be infringed only as a | |||
consequence of further modification of the contributor version. For | |||
purposes of this definition, "control" includes the right to grant | |||
patent sublicenses in a manner consistent with the requirements of | |||
this License. | |||
Each contributor grants you a non-exclusive, worldwide, royalty-free | |||
patent license under the contributor's essential patent claims, to | |||
make, use, sell, offer for sale, import and otherwise run, modify and | |||
propagate the contents of its contributor version. | |||
In the following three paragraphs, a "patent license" is any express | |||
agreement or commitment, however denominated, not to enforce a patent | |||
(such as an express permission to practice a patent or covenant not to | |||
sue for patent infringement). To "grant" such a patent license to a | |||
party means to make such an agreement or commitment not to enforce a | |||
patent against the party. | |||
If you convey a covered work, knowingly relying on a patent license, | |||
and the Corresponding Source of the work is not available for anyone | |||
to copy, free of charge and under the terms of this License, through a | |||
publicly available network server or other readily accessible means, | |||
then you must either (1) cause the Corresponding Source to be so | |||
available, or (2) arrange to deprive yourself of the benefit of the | |||
patent license for this particular work, or (3) arrange, in a manner | |||
consistent with the requirements of this License, to extend the patent | |||
license to downstream recipients. "Knowingly relying" means you have | |||
actual knowledge that, but for the patent license, your conveying the | |||
covered work in a country, or your recipient's use of the covered work | |||
in a country, would infringe one or more identifiable patents in that | |||
country that you have reason to believe are valid. | |||
If, pursuant to or in connection with a single transaction or | |||
arrangement, you convey, or propagate by procuring conveyance of, a | |||
covered work, and grant a patent license to some of the parties | |||
receiving the covered work authorizing them to use, propagate, modify | |||
or convey a specific copy of the covered work, then the patent license | |||
you grant is automatically extended to all recipients of the covered | |||
work and works based on it. | |||
A patent license is "discriminatory" if it does not include within | |||
the scope of its coverage, prohibits the exercise of, or is | |||
conditioned on the non-exercise of one or more of the rights that are | |||
specifically granted under this License. You may not convey a covered | |||
work if you are a party to an arrangement with a third party that is | |||
in the business of distributing software, under which you make payment | |||
to the third party based on the extent of your activity of conveying | |||
the work, and under which the third party grants, to any of the | |||
parties who would receive the covered work from you, a discriminatory | |||
patent license (a) in connection with copies of the covered work | |||
conveyed by you (or copies made from those copies), or (b) primarily | |||
for and in connection with specific products or compilations that | |||
contain the covered work, unless you entered into that arrangement, | |||
or that patent license was granted, prior to 28 March 2007. | |||
Nothing in this License shall be construed as excluding or limiting | |||
any implied license or other defenses to infringement that may | |||
otherwise be available to you under applicable patent law. | |||
12. No Surrender of Others' Freedom. | |||
If conditions are imposed on you (whether by court order, agreement or | |||
otherwise) that contradict the conditions of this License, they do not | |||
excuse you from the conditions of this License. If you cannot convey a | |||
covered work so as to satisfy simultaneously your obligations under this | |||
License and any other pertinent obligations, then as a consequence you may | |||
not convey it at all. For example, if you agree to terms that obligate you | |||
to collect a royalty for further conveying from those to whom you convey | |||
the Program, the only way you could satisfy both those terms and this | |||
License would be to refrain entirely from conveying the Program. | |||
13. Use with the GNU Affero General Public License. | |||
Notwithstanding any other provision of this License, you have | |||
permission to link or combine any covered work with a work licensed | |||
under version 3 of the GNU Affero General Public License into a single | |||
combined work, and to convey the resulting work. The terms of this | |||
License will continue to apply to the part which is the covered work, | |||
but the special requirements of the GNU Affero General Public License, | |||
section 13, concerning interaction through a network will apply to the | |||
combination as such. | |||
14. Revised Versions of this License. | |||
The Free Software Foundation may publish revised and/or new versions of | |||
the GNU General Public License from time to time. Such new versions will | |||
be similar in spirit to the present version, but may differ in detail to | |||
address new problems or concerns. | |||
Each version is given a distinguishing version number. If the | |||
Program specifies that a certain numbered version of the GNU General | |||
Public License "or any later version" applies to it, you have the | |||
option of following the terms and conditions either of that numbered | |||
version or of any later version published by the Free Software | |||
Foundation. If the Program does not specify a version number of the | |||
GNU General Public License, you may choose any version ever published | |||
by the Free Software Foundation. | |||
If the Program specifies that a proxy can decide which future | |||
versions of the GNU General Public License can be used, that proxy's | |||
public statement of acceptance of a version permanently authorizes you | |||
to choose that version for the Program. | |||
Later license versions may give you additional or different | |||
permissions. However, no additional obligations are imposed on any | |||
author or copyright holder as a result of your choosing to follow a | |||
later version. | |||
15. Disclaimer of Warranty. | |||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY | |||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT | |||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY | |||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, | |||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM | |||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF | |||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | |||
16. Limitation of Liability. | |||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS | |||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY | |||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE | |||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF | |||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD | |||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), | |||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF | |||
SUCH DAMAGES. | |||
17. Interpretation of Sections 15 and 16. | |||
If the disclaimer of warranty and limitation of liability provided | |||
above cannot be given local legal effect according to their terms, | |||
reviewing courts shall apply local law that most closely approximates | |||
an absolute waiver of all civil liability in connection with the | |||
Program, unless a warranty or assumption of liability accompanies a | |||
copy of the Program in return for a fee. | |||
END OF TERMS AND CONDITIONS | |||
How to Apply These Terms to Your New Programs | |||
If you develop a new program, and you want it to be of the greatest | |||
possible use to the public, the best way to achieve this is to make it | |||
free software which everyone can redistribute and change under these terms. | |||
To do so, attach the following notices to the program. It is safest | |||
to attach them to the start of each source file to most effectively | |||
state the exclusion of warranty; and each file should have at least | |||
the "copyright" line and a pointer to where the full notice is found. | |||
<one line to give the program's name and a brief idea of what it does.> | |||
Copyright (C) <year> <name of author> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
Also add information on how to contact you by electronic and paper mail. | |||
If the program does terminal interaction, make it output a short | |||
notice like this when it starts in an interactive mode: | |||
<program> Copyright (C) <year> <name of author> | |||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |||
This is free software, and you are welcome to redistribute it | |||
under certain conditions; type `show c' for details. | |||
The hypothetical commands `show w' and `show c' should show the appropriate | |||
parts of the General Public License. Of course, your program's commands | |||
might be different; for a GUI interface, you would use an "about box". | |||
You should also get your employer (if you work as a programmer) or school, | |||
if any, to sign a "copyright disclaimer" for the program, if necessary. | |||
For more information on this, and how to apply and follow the GNU GPL, see | |||
<http://www.gnu.org/licenses/>. | |||
The GNU General Public License does not permit incorporating your program | |||
into proprietary programs. If your program is a subroutine library, you | |||
may consider it more useful to permit linking proprietary applications with | |||
the library. If this is what you want to do, use the GNU Lesser General | |||
Public License instead of this License. But first, please read | |||
<http://www.gnu.org/philosophy/why-not-lgpl.html>. |
@@ -0,0 +1,62 @@ | |||
#!/usr/bin/make -f | |||
# Makefile for static aubio # | |||
# ------------------------- # | |||
# Created by falkTX | |||
# | |||
# -------------------------------------------------------------- | |||
# Import base definitions | |||
USE_NANOVG_FBO = true | |||
include ../../dpf/Makefile.base.mk | |||
# -------------------------------------------------------------- | |||
BUILD_C_FLAGS += -DHAVE_CONFIG_H | |||
BUILD_C_FLAGS += -I. | |||
BUILD_C_FLAGS += -Isrc | |||
BUILD_C_FLAGS += $(shell pkg-config --cflags fftw3f) | |||
OBJS = \ | |||
src/cvec.c.o \ | |||
src/fvec.c.o \ | |||
src/lvec.c.o \ | |||
src/mathutils.c.o \ | |||
src/pitch/pitch.c.o \ | |||
src/pitch/pitchfcomb.c.o \ | |||
src/pitch/pitchmcomb.c.o \ | |||
src/pitch/pitchschmitt.c.o \ | |||
src/pitch/pitchspecacf.c.o \ | |||
src/pitch/pitchyin.c.o \ | |||
src/pitch/pitchyinfast.c.o \ | |||
src/pitch/pitchyinfft.c.o \ | |||
src/spectral/fft.c.o \ | |||
src/spectral/phasevoc.c.o \ | |||
src/temporal/a_weighting.c.o \ | |||
src/temporal/biquad.c.o \ | |||
src/temporal/c_weighting.c.o \ | |||
src/temporal/filter.c.o \ | |||
src/temporal/resampler.c.o \ | |||
src/utils/log.c.o \ | |||
# -------------------------------------------------------------- | |||
all: libaubio.a | |||
clean: | |||
rm -f *.a src/*.d src/*.o src/*/*.d src/*/*.o | |||
libaubio.a: $(OBJS) | |||
rm -f $@ | |||
$(AR) crs $@ $^ | |||
# -------------------------------------------------------------- | |||
%.c.o: %.c | |||
$(CC) $< $(BUILD_C_FLAGS) -c -o $@ | |||
# -------------------------------------------------------------- | |||
-include $(OBJS:%.o=%.d) | |||
# -------------------------------------------------------------- |
@@ -0,0 +1,20 @@ | |||
#ifndef AUBIO_CONFIG_H | |||
#define AUBIO_CONFIG_H | |||
#define HAVE_STDLIB_H 1 | |||
#define HAVE_STDIO_H 1 | |||
#define HAVE_MATH_H 1 | |||
#define HAVE_STRING_H 1 | |||
#define HAVE_LIMITS_H 1 | |||
#define HAVE_STDARG_H 1 | |||
#define HAVE_GETOPT_H 1 | |||
#define HAVE_UNISTD_H 1 | |||
#define HAVE_C99_VARARGS_MACROS 1 | |||
#define HAVE_MEMCPY_HACKS 1 | |||
#define HAVE_FFTW3 | |||
#define HAVE_FFTW3F | |||
#define HAVE_COMPLEX_H | |||
#endif /* AUBIO_CONFIG_H */ |
@@ -0,0 +1,208 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** \mainpage | |||
\section introduction Introduction | |||
aubio is a library to extract annotations from audio signals: it provides a | |||
set of functions that take an input audio signal, and output pitch estimates, | |||
attack times (onset), beat location estimates, and other annotation tasks. | |||
\section basics Basics | |||
All object structures in aubio share the same function prefixes and suffixes: | |||
- \p new_aubio_foo creates the object \p foo | |||
- \p aubio_foo_do executes the object \p foo | |||
- \p del_aubio_foo destroys the object \p foo | |||
All memory allocation and deallocation take place in the \p new_ and \p del_ | |||
functions. Optionally, more than one \p _do methods are available. | |||
Additional parameters can be adjusted and observed using: | |||
- \p aubio_foo_get_param, getter function, gets the value of a parameter | |||
- \p aubio_foo_set_param, setter function, changes the value of a parameter | |||
Unless specified in its documentation, no memory operations take place in the | |||
getter functions. However, memory resizing can take place in setter | |||
functions. | |||
\subsection vectors Vectors | |||
Two basic structures are being used in aubio: ::fvec_t and ::cvec_t. The | |||
::fvec_t structures are used to store vectors of floating pointer number. | |||
::cvec_t are used to store complex number, as two vectors of norm and phase | |||
elements. | |||
Additionally, the ::lvec_t structure can be used to store floating point | |||
numbers in double precision. They are mostly used to store filter | |||
coefficients, to avoid instability. | |||
\subsection objects Available objects | |||
Here is a list of some of the most common objects for aubio: | |||
\code | |||
// fast Fourier transform (FFT) | |||
aubio_fft_t *fft = new_aubio_fft (winsize); | |||
// phase vocoder | |||
aubio_pvoc_t *pv = new_aubio_pvoc (winsize, stepsize); | |||
// onset detection | |||
aubio_onset_t *onset = new_aubio_onset (method, winsize, stepsize, samplerate); | |||
// pitch detection | |||
aubio_pitch_t *pitch = new_aubio_pitch (method, winsize, stepsize, samplerate); | |||
// beat tracking | |||
aubio_tempo_t *tempo = new_aubio_tempo (method, winsize, stepsize, samplerate); | |||
\endcode | |||
See the <a href="globals_type.html">list of typedefs</a> for a complete list. | |||
\subsection example Example | |||
Here is a simple example that creates an A-Weighting filter and applies it to a | |||
vector. | |||
\code | |||
// set window size, and sampling rate | |||
uint_t winsize = 1024, sr = 44100; | |||
// create a vector | |||
fvec_t *this_buffer = new_fvec (winsize); | |||
// create the a-weighting filter | |||
aubio_filter_t *this_filter = new_aubio_filter_a_weighting (sr); | |||
while (running) { | |||
// here some code to put some data in this_buffer | |||
// ... | |||
// apply the filter, in place | |||
aubio_filter_do (this_filter, this_buffer); | |||
// here some code to get some data from this_buffer | |||
// ... | |||
} | |||
// and free the structures | |||
del_aubio_filter (this_filter); | |||
del_fvec (this_buffer); | |||
\endcode | |||
Several examples of C programs are available in the \p examples/ and \p tests/src | |||
directories of the source tree. | |||
Some examples: | |||
- @ref spectral/test-fft.c | |||
- @ref spectral/test-phasevoc.c | |||
- @ref onset/test-onset.c | |||
- @ref pitch/test-pitch.c | |||
- @ref tempo/test-tempo.c | |||
- @ref test-fvec.c | |||
- @ref test-cvec.c | |||
\subsection unstable_api Unstable API | |||
Several more functions are available and used within aubio, but not | |||
documented here, either because they are not considered useful to the user, | |||
or because they may need to be changed in the future. However, they can still | |||
be used by defining AUBIO_UNSTABLE to 1 before including the aubio header: | |||
\code | |||
#define AUBIO_UNSTABLE 1 | |||
#include <aubio/aubio.h> | |||
\endcode | |||
Future versions of aubio could break API compatibility with these functions | |||
without warning. If you choose to use functions in AUBIO_UNSTABLE, you are on | |||
your own. | |||
\section download Download | |||
Latest versions, further documentation, examples, wiki, and mailing lists can | |||
be found at https://aubio.org . | |||
*/ | |||
#ifndef AUBIO_H | |||
#define AUBIO_H | |||
/** @file aubio.h Global aubio include file. | |||
You will want to include this file as: | |||
@code | |||
#include <aubio/aubio.h> | |||
@endcode | |||
To access headers with unstable prototypes, use: | |||
@code | |||
#define AUBIO_UNSTABLE 1 | |||
#include <aubio/aubio.h> | |||
@endcode | |||
*/ | |||
#ifdef __cplusplus | |||
extern "C" | |||
{ | |||
#endif | |||
/* in this order */ | |||
#include "types.h" | |||
#include "fvec.h" | |||
// #include "cvec.h" | |||
// #include "lvec.h" | |||
// // #include "fmat.h" | |||
// #include "musicutils.h" | |||
// // #include "vecutils.h" | |||
// #include "temporal/resampler.h" | |||
// #include "temporal/filter.h" | |||
// #include "temporal/biquad.h" | |||
// #include "temporal/a_weighting.h" | |||
// #include "temporal/c_weighting.h" | |||
// #include "spectral/fft.h" | |||
// // #include "spectral/dct.h" | |||
// #include "spectral/phasevoc.h" | |||
// // #include "spectral/filterbank.h" | |||
// // #include "spectral/filterbank_mel.h" | |||
// // #include "spectral/mfcc.h" | |||
// // #include "spectral/specdesc.h" | |||
// // #include "spectral/awhitening.h" | |||
// // #include "spectral/tss.h" | |||
#include "pitch/pitch.h" | |||
// // #include "onset/onset.h" | |||
// // #include "tempo/tempo.h" | |||
// // #include "notes/notes.h" | |||
// // #include "io/source.h" | |||
// // #include "io/sink.h" | |||
// // #include "synth/sampler.h" | |||
// // #include "synth/wavetable.h" | |||
// // #include "utils/parameter.h" | |||
// #include "utils/log.h" | |||
#ifdef __cplusplus | |||
} /* extern "C" */ | |||
#endif | |||
#endif |
@@ -0,0 +1,359 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** @file | |||
* Private include file | |||
* | |||
* This file is for inclusion from _within_ the library only. | |||
*/ | |||
#ifndef AUBIO_PRIV_H | |||
#define AUBIO_PRIV_H | |||
/********************* | |||
* | |||
* External includes | |||
* | |||
*/ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#ifdef HAVE_STDLIB_H | |||
#include <stdlib.h> | |||
#endif | |||
#ifdef HAVE_STDIO_H | |||
#include <stdio.h> | |||
#endif | |||
/* must be included before fftw3.h */ | |||
#ifdef HAVE_COMPLEX_H | |||
#include <complex.h> | |||
#endif | |||
#if defined(HAVE_FFTW3) || defined(HAVE_FFTW3F) | |||
#include <fftw3.h> | |||
#endif | |||
#ifdef HAVE_MATH_H | |||
#include <math.h> | |||
#endif | |||
#ifdef HAVE_STRING_H | |||
#include <string.h> | |||
#endif | |||
#ifdef HAVE_LIMITS_H | |||
#include <limits.h> // for CHAR_BIT, in C99 standard | |||
#endif | |||
#ifdef HAVE_STDARG_H | |||
#include <stdarg.h> | |||
#endif | |||
#ifdef HAVE_ACCELERATE | |||
#define HAVE_ATLAS 1 | |||
#include <Accelerate/Accelerate.h> | |||
#elif defined(HAVE_ATLAS_CBLAS_H) | |||
#define HAVE_ATLAS 1 | |||
#include <atlas/cblas.h> | |||
#else | |||
#undef HAVE_ATLAS | |||
#endif | |||
#ifdef HAVE_ACCELERATE | |||
#include <Accelerate/Accelerate.h> | |||
#ifndef HAVE_AUBIO_DOUBLE | |||
#define aubio_vDSP_mmov vDSP_mmov | |||
#define aubio_vDSP_vmul vDSP_vmul | |||
#define aubio_vDSP_vfill vDSP_vfill | |||
#define aubio_vDSP_meanv vDSP_meanv | |||
#define aubio_vDSP_sve vDSP_sve | |||
#define aubio_vDSP_maxv vDSP_maxv | |||
#define aubio_vDSP_maxvi vDSP_maxvi | |||
#define aubio_vDSP_minv vDSP_minv | |||
#define aubio_vDSP_minvi vDSP_minvi | |||
#define aubio_vDSP_dotpr vDSP_dotpr | |||
#define aubio_vDSP_vclr vDSP_vclr | |||
#else /* HAVE_AUBIO_DOUBLE */ | |||
#define aubio_vDSP_mmov vDSP_mmovD | |||
#define aubio_vDSP_vmul vDSP_vmulD | |||
#define aubio_vDSP_vfill vDSP_vfillD | |||
#define aubio_vDSP_meanv vDSP_meanvD | |||
#define aubio_vDSP_sve vDSP_sveD | |||
#define aubio_vDSP_maxv vDSP_maxvD | |||
#define aubio_vDSP_maxvi vDSP_maxviD | |||
#define aubio_vDSP_minv vDSP_minvD | |||
#define aubio_vDSP_minvi vDSP_minviD | |||
#define aubio_vDSP_dotpr vDSP_dotprD | |||
#define aubio_vDSP_vclr vDSP_vclrD | |||
#endif /* HAVE_AUBIO_DOUBLE */ | |||
#endif /* HAVE_ACCELERATE */ | |||
#ifdef HAVE_ATLAS | |||
#ifndef HAVE_AUBIO_DOUBLE | |||
#define aubio_catlas_set catlas_sset | |||
#define aubio_cblas_copy cblas_scopy | |||
#define aubio_cblas_swap cblas_sswap | |||
#define aubio_cblas_dot cblas_sdot | |||
#else /* HAVE_AUBIO_DOUBLE */ | |||
#define aubio_catlas_set catlas_dset | |||
#define aubio_cblas_copy cblas_dcopy | |||
#define aubio_cblas_swap cblas_dswap | |||
#define aubio_cblas_dot cblas_ddot | |||
#endif /* HAVE_AUBIO_DOUBLE */ | |||
#endif /* HAVE_ATLAS */ | |||
#if defined HAVE_INTEL_IPP | |||
#include <ippcore.h> | |||
#include <ippvm.h> | |||
#include <ipps.h> | |||
#ifndef HAVE_AUBIO_DOUBLE | |||
#define aubio_ippsSet ippsSet_32f | |||
#define aubio_ippsZero ippsZero_32f | |||
#define aubio_ippsCopy ippsCopy_32f | |||
#define aubio_ippsMul ippsMul_32f | |||
#define aubio_ippsMulC ippsMulC_32f | |||
#define aubio_ippsAddC ippsAddC_32f | |||
#define aubio_ippsLn ippsLn_32f_A21 | |||
#define aubio_ippsMean(a,b,c) ippsMean_32f(a, b, c, ippAlgHintFast) | |||
#define aubio_ippsSum(a,b,c) ippsSum_32f(a, b, c, ippAlgHintFast) | |||
#define aubio_ippsMax ippsMax_32f | |||
#define aubio_ippsMin ippsMin_32f | |||
#else /* HAVE_AUBIO_DOUBLE */ | |||
#define aubio_ippsSet ippsSet_64f | |||
#define aubio_ippsZero ippsZero_64f | |||
#define aubio_ippsCopy ippsCopy_64f | |||
#define aubio_ippsMul ippsMul_64f | |||
#define aubio_ippsMulC ippsMulC_64f | |||
#define aubio_ippsAddC ippsAddC_64f | |||
#define aubio_ippsLn ippsLn_64f_A26 | |||
#define aubio_ippsMean ippsMean_64f | |||
#define aubio_ippsSum ippsSum_64f | |||
#define aubio_ippsMax ippsMax_64f | |||
#define aubio_ippsMin ippsMin_64f | |||
#endif /* HAVE_AUBIO_DOUBLE */ | |||
#endif | |||
#if !defined(HAVE_MEMCPY_HACKS) && !defined(HAVE_ACCELERATE) && !defined(HAVE_ATLAS) && !defined(HAVE_INTEL_IPP) | |||
#define HAVE_NOOPT 1 | |||
#else | |||
#undef HAVE_NOOPT | |||
#endif | |||
#include "types.h" | |||
#define AUBIO_UNSTABLE 1 | |||
#include "mathutils.h" | |||
/**** | |||
* | |||
* SYSTEM INTERFACE | |||
* | |||
*/ | |||
/* Memory management */ | |||
#define AUBIO_MALLOC(_n) malloc(_n) | |||
#define AUBIO_REALLOC(_p,_n) realloc(_p,_n) | |||
#define AUBIO_NEW(_t) (_t*)calloc(sizeof(_t), 1) | |||
#define AUBIO_ARRAY(_t,_n) (_t*)calloc((_n)*sizeof(_t), 1) | |||
#define AUBIO_MEMCPY(_dst,_src,_n) memcpy(_dst,_src,_n) | |||
#define AUBIO_MEMSET(_dst,_src,_t) memset(_dst,_src,_t) | |||
#define AUBIO_FREE(_p) free(_p) | |||
/* file interface */ | |||
#define AUBIO_FOPEN(_f,_m) fopen(_f,_m) | |||
#define AUBIO_FCLOSE(_f) fclose(_f) | |||
#define AUBIO_FREAD(_p,_s,_n,_f) fread(_p,_s,_n,_f) | |||
#define AUBIO_FSEEK(_f,_n,_set) fseek(_f,_n,_set) | |||
/* strings */ | |||
#define AUBIO_STRLEN(_s) strlen(_s) | |||
#define AUBIO_STRCMP(_s,_t) strcmp(_s,_t) | |||
#define AUBIO_STRNCMP(_s,_t,_n) strncmp(_s,_t,_n) | |||
#define AUBIO_STRCPY(_dst,_src) strcpy(_dst,_src) | |||
#define AUBIO_STRCHR(_s,_c) strchr(_s,_c) | |||
#ifdef strdup | |||
#define AUBIO_STRDUP(s) strdup(s) | |||
#else | |||
#define AUBIO_STRDUP(s) AUBIO_STRCPY(AUBIO_MALLOC(AUBIO_STRLEN(s) + 1), s) | |||
#endif | |||
/* Error reporting */ | |||
typedef enum { | |||
AUBIO_OK = 0, | |||
AUBIO_FAIL = 1 | |||
} aubio_status; | |||
/* Logging */ | |||
#include "utils/log.h" | |||
/** internal logging function, defined in utils/log.c */ | |||
uint_t aubio_log(sint_t level, const char_t *fmt, ...); | |||
#ifdef HAVE_C99_VARARGS_MACROS | |||
#define AUBIO_ERR(...) aubio_log(AUBIO_LOG_ERR, "AUBIO ERROR: " __VA_ARGS__) | |||
#define AUBIO_INF(...) aubio_log(AUBIO_LOG_INF, "AUBIO INFO: " __VA_ARGS__) | |||
#define AUBIO_MSG(...) aubio_log(AUBIO_LOG_MSG, __VA_ARGS__) | |||
#define AUBIO_DBG(...) aubio_log(AUBIO_LOG_DBG, __VA_ARGS__) | |||
#define AUBIO_WRN(...) aubio_log(AUBIO_LOG_WRN, "AUBIO WARNING: " __VA_ARGS__) | |||
#else | |||
#define AUBIO_ERR(format, args...) aubio_log(AUBIO_LOG_ERR, "AUBIO ERROR: " format , ##args) | |||
#define AUBIO_INF(format, args...) aubio_log(AUBIO_LOG_INF, "AUBIO INFO: " format , ##args) | |||
#define AUBIO_MSG(format, args...) aubio_log(AUBIO_LOG_MSG, format , ##args) | |||
#define AUBIO_DBG(format, args...) aubio_log(AUBIO_LOG_DBG, format , ##args) | |||
#define AUBIO_WRN(format, args...) aubio_log(AUBIO_LOG_WRN, "AUBIO WARNING: " format, ##args) | |||
#endif | |||
#define AUBIO_ERROR AUBIO_ERR | |||
#define AUBIO_QUIT(_s) exit(_s) | |||
#define AUBIO_SPRINTF sprintf | |||
#define AUBIO_MAX_SAMPLERATE (192000*8) | |||
#define AUBIO_MAX_CHANNELS 1024 | |||
/* pi and 2*pi */ | |||
#ifndef M_PI | |||
#define PI (3.14159265358979323846) | |||
#else | |||
#define PI (M_PI) | |||
#endif | |||
#define TWO_PI (PI*2.) | |||
#ifndef PATH_MAX | |||
#define PATH_MAX 1024 | |||
#endif | |||
/* aliases to math.h functions */ | |||
#if !HAVE_AUBIO_DOUBLE | |||
#define EXP expf | |||
#define COS cosf | |||
#define SIN sinf | |||
#define ABS fabsf | |||
#define POW powf | |||
#define SQRT sqrtf | |||
#define LOG10 log10f | |||
#define LOG logf | |||
#define FLOOR floorf | |||
#define CEIL ceilf | |||
#define ATAN atanf | |||
#define ATAN2 atan2f | |||
#else | |||
#error using double | |||
#define EXP exp | |||
#define COS cos | |||
#define SIN sin | |||
#define ABS fabs | |||
#define POW pow | |||
#define SQRT sqrt | |||
#define LOG10 log10 | |||
#define LOG log | |||
#define FLOOR floor | |||
#define CEIL ceil | |||
#define ATAN atan | |||
#define ATAN2 atan2 | |||
#endif | |||
#define ROUND(x) FLOOR(x+.5) | |||
/* aliases to complex.h functions */ | |||
#if HAVE_AUBIO_DOUBLE || !defined(HAVE_COMPLEX_H) || defined(WIN32) | |||
/* mingw32 does not know about c*f functions */ | |||
#define EXPC cexp | |||
/** complex = CEXPC(complex) */ | |||
#define CEXPC cexp | |||
/** sample = ARGC(complex) */ | |||
#define ARGC carg | |||
/** sample = ABSC(complex) norm */ | |||
#define ABSC cabs | |||
/** sample = REAL(complex) */ | |||
#define REAL creal | |||
/** sample = IMAG(complex) */ | |||
#define IMAG cimag | |||
#else | |||
/** sample = EXPC(complex) */ | |||
#define EXPC cexpf | |||
/** complex = CEXPC(complex) */ | |||
#define CEXPC cexp | |||
/** sample = ARGC(complex) */ | |||
#define ARGC cargf | |||
/** sample = ABSC(complex) norm */ | |||
#define ABSC cabsf | |||
/** sample = REAL(complex) */ | |||
#define REAL crealf | |||
/** sample = IMAG(complex) */ | |||
#define IMAG cimagf | |||
#endif | |||
/* avoid unresolved symbol with msvc 9 */ | |||
#if defined(_MSC_VER) && (_MSC_VER < 1900) | |||
#define isnan _isnan | |||
#endif | |||
/* handy shortcuts */ | |||
#define DB2LIN(g) (POW(10.0,(g)*0.05f)) | |||
#define LIN2DB(v) (20.0*LOG10(v)) | |||
#define SQR(_a) ((_a)*(_a)) | |||
#ifndef MAX | |||
#define MAX(a,b) (((a)>(b))?(a):(b)) | |||
#endif /* MAX */ | |||
#ifndef MIN | |||
#define MIN(a,b) (((a)<(b))?(a):(b)) | |||
#endif /* MIN */ | |||
#define ELEM_SWAP(a,b) { register smpl_t t=(a);(a)=(b);(b)=t; } | |||
#define VERY_SMALL_NUMBER 2.e-42 //1.e-37 | |||
/** if ABS(f) < VERY_SMALL_NUMBER, returns 1, else 0 */ | |||
#define IS_DENORMAL(f) ABS(f) < VERY_SMALL_NUMBER | |||
/** if ABS(f) < VERY_SMALL_NUMBER, returns 0., else f */ | |||
#define KILL_DENORMAL(f) IS_DENORMAL(f) ? 0. : f | |||
/** if f > VERY_SMALL_NUMBER, returns f, else returns VERY_SMALL_NUMBER */ | |||
#define CEIL_DENORMAL(f) f < VERY_SMALL_NUMBER ? VERY_SMALL_NUMBER : f | |||
#define SAFE_LOG10(f) LOG10(CEIL_DENORMAL(f)) | |||
#define SAFE_LOG(f) LOG(CEIL_DENORMAL(f)) | |||
/** silence unused parameter warning by adding an attribute */ | |||
#if defined(__GNUC__) | |||
#define UNUSED __attribute__((unused)) | |||
#else | |||
#define UNUSED | |||
#endif | |||
/* are we using gcc -std=c99 ? */ | |||
#if defined(__STRICT_ANSI__) | |||
#define strnlen(a,b) MIN(strlen(a),b) | |||
#if !HAVE_AUBIO_DOUBLE | |||
#define floorf floor | |||
#endif | |||
#endif /* __STRICT_ANSI__ */ | |||
#endif /* AUBIO_PRIV_H */ |
@@ -0,0 +1,169 @@ | |||
/* | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "cvec.h" | |||
cvec_t * new_cvec(uint_t length) { | |||
cvec_t * s; | |||
if ((sint_t)length <= 0) { | |||
return NULL; | |||
} | |||
s = AUBIO_NEW(cvec_t); | |||
s->length = length/2 + 1; | |||
s->norm = AUBIO_ARRAY(smpl_t,s->length); | |||
s->phas = AUBIO_ARRAY(smpl_t,s->length); | |||
return s; | |||
} | |||
void del_cvec(cvec_t *s) { | |||
AUBIO_FREE(s->norm); | |||
AUBIO_FREE(s->phas); | |||
AUBIO_FREE(s); | |||
} | |||
void cvec_norm_set_sample (cvec_t *s, smpl_t data, uint_t position) { | |||
s->norm[position] = data; | |||
} | |||
void cvec_phas_set_sample (cvec_t *s, smpl_t data, uint_t position) { | |||
s->phas[position] = data; | |||
} | |||
smpl_t cvec_norm_get_sample (cvec_t *s, uint_t position) { | |||
return s->norm[position]; | |||
} | |||
smpl_t cvec_phas_get_sample (cvec_t *s, uint_t position) { | |||
return s->phas[position]; | |||
} | |||
smpl_t * cvec_norm_get_data (const cvec_t *s) { | |||
return s->norm; | |||
} | |||
smpl_t * cvec_phas_get_data (const cvec_t *s) { | |||
return s->phas; | |||
} | |||
/* helper functions */ | |||
void cvec_print(const cvec_t *s) { | |||
uint_t j; | |||
AUBIO_MSG("norm: "); | |||
for (j=0; j< s->length; j++) { | |||
AUBIO_MSG(AUBIO_SMPL_FMT " ", s->norm[j]); | |||
} | |||
AUBIO_MSG("\n"); | |||
AUBIO_MSG("phas: "); | |||
for (j=0; j< s->length; j++) { | |||
AUBIO_MSG(AUBIO_SMPL_FMT " ", s->phas[j]); | |||
} | |||
AUBIO_MSG("\n"); | |||
} | |||
void cvec_copy(const cvec_t *s, cvec_t *t) { | |||
if (s->length != t->length) { | |||
AUBIO_ERR("trying to copy %d elements to %d elements \n", | |||
s->length, t->length); | |||
return; | |||
} | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsCopy(s->phas, t->phas, (int)s->length); | |||
aubio_ippsCopy(s->norm, t->norm, (int)s->length); | |||
#elif defined(HAVE_MEMCPY_HACKS) | |||
memcpy(t->norm, s->norm, t->length * sizeof(smpl_t)); | |||
memcpy(t->phas, s->phas, t->length * sizeof(smpl_t)); | |||
#else | |||
uint_t j; | |||
for (j=0; j< t->length; j++) { | |||
t->norm[j] = s->norm[j]; | |||
t->phas[j] = s->phas[j]; | |||
} | |||
#endif | |||
} | |||
void cvec_norm_set_all(cvec_t *s, smpl_t val) { | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsSet(val, s->norm, (int)s->length); | |||
#else | |||
uint_t j; | |||
for (j=0; j< s->length; j++) { | |||
s->norm[j] = val; | |||
} | |||
#endif | |||
} | |||
void cvec_norm_zeros(cvec_t *s) { | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsZero(s->norm, (int)s->length); | |||
#elif defined(HAVE_MEMCPY_HACKS) | |||
memset(s->norm, 0, s->length * sizeof(smpl_t)); | |||
#else | |||
cvec_norm_set_all (s, 0.); | |||
#endif | |||
} | |||
void cvec_norm_ones(cvec_t *s) { | |||
cvec_norm_set_all (s, 1.); | |||
} | |||
void cvec_phas_set_all (cvec_t *s, smpl_t val) { | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsSet(val, s->phas, (int)s->length); | |||
#else | |||
uint_t j; | |||
for (j=0; j< s->length; j++) { | |||
s->phas[j] = val; | |||
} | |||
#endif | |||
} | |||
void cvec_phas_zeros(cvec_t *s) { | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsZero(s->phas, (int)s->length); | |||
#elif defined(HAVE_MEMCPY_HACKS) | |||
memset(s->phas, 0, s->length * sizeof(smpl_t)); | |||
#else | |||
cvec_phas_set_all (s, 0.); | |||
#endif | |||
} | |||
void cvec_phas_ones(cvec_t *s) { | |||
cvec_phas_set_all (s, 1.); | |||
} | |||
void cvec_zeros(cvec_t *s) { | |||
cvec_norm_zeros(s); | |||
cvec_phas_zeros(s); | |||
} | |||
void cvec_logmag(cvec_t *s, smpl_t lambda) { | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsMulC(s->norm, lambda, s->norm, (int)s->length); | |||
aubio_ippsAddC(s->norm, 1.0, s->norm, (int)s->length); | |||
aubio_ippsLn(s->norm, s->norm, (int)s->length); | |||
#else | |||
uint_t j; | |||
for (j=0; j< s->length; j++) { | |||
s->norm[j] = LOG(lambda * s->norm[j] + 1); | |||
} | |||
#endif | |||
} |
@@ -0,0 +1,247 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef AUBIO_CVEC_H | |||
#define AUBIO_CVEC_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** \file | |||
Vector of complex-valued data, stored in polar coordinates | |||
This file specifies the ::cvec_t buffer type, which is used throughout aubio | |||
to store complex data. Complex values are stored in terms of ::cvec_t.phas | |||
and norm, within 2 vectors of ::smpl_t of size (size/2+1) each. | |||
\example test-cvec.c | |||
*/ | |||
/** Vector of real-valued phase and spectrum data | |||
\code | |||
uint_t buffer_size = 1024; | |||
// create a complex vector of 512 values | |||
cvec_t * input = new_cvec (buffer_size); | |||
// set some values of the vector | |||
input->norm[23] = 2.; | |||
input->phas[23] = M_PI; | |||
// .. | |||
// compute the mean of the vector | |||
mean = cvec_mean(input); | |||
// destroy the vector | |||
del_cvec (input); | |||
\endcode | |||
*/ | |||
typedef struct { | |||
uint_t length; /**< length of buffer = (requested length)/2 + 1 */ | |||
smpl_t *norm; /**< norm array of size ::cvec_t.length */ | |||
smpl_t *phas; /**< phase array of size ::cvec_t.length */ | |||
} cvec_t; | |||
/** cvec_t buffer creation function | |||
This function creates a cvec_t structure holding two arrays of size | |||
[length/2+1], corresponding to the norm and phase values of the | |||
spectral frame. The length stored in the structure is the actual size of both | |||
arrays, not the length of the complex and symmetrical vector, specified as | |||
creation argument. | |||
\param length the length of the buffer to create | |||
*/ | |||
cvec_t * new_cvec(uint_t length); | |||
/** cvec_t buffer deletion function | |||
\param s buffer to delete as returned by new_cvec() | |||
*/ | |||
void del_cvec(cvec_t *s); | |||
/** write norm value in a complex buffer | |||
This is equivalent to: | |||
\code | |||
s->norm[position] = val; | |||
\endcode | |||
\param s vector to write to | |||
\param val norm value to write in s->norm[position] | |||
\param position sample position to write to | |||
*/ | |||
void cvec_norm_set_sample (cvec_t *s, smpl_t val, uint_t position); | |||
/** write phase value in a complex buffer | |||
This is equivalent to: | |||
\code | |||
s->phas[position] = val; | |||
\endcode | |||
\param s vector to write to | |||
\param val phase value to write in s->phas[position] | |||
\param position sample position to write to | |||
*/ | |||
void cvec_phas_set_sample (cvec_t *s, smpl_t val, uint_t position); | |||
/** read norm value from a complex buffer | |||
This is equivalent to: | |||
\code | |||
smpl_t foo = s->norm[position]; | |||
\endcode | |||
\param s vector to read from | |||
\param position sample position to read from | |||
*/ | |||
smpl_t cvec_norm_get_sample (cvec_t *s, uint_t position); | |||
/** read phase value from a complex buffer | |||
This is equivalent to: | |||
\code | |||
smpl_t foo = s->phas[position]; | |||
\endcode | |||
\param s vector to read from | |||
\param position sample position to read from | |||
\returns the value of the sample at position | |||
*/ | |||
smpl_t cvec_phas_get_sample (cvec_t *s, uint_t position); | |||
/** read norm data from a complex buffer | |||
\code | |||
smpl_t *data = s->norm; | |||
\endcode | |||
\param s vector to read from | |||
*/ | |||
smpl_t * cvec_norm_get_data (const cvec_t *s); | |||
/** read phase data from a complex buffer | |||
This is equivalent to: | |||
\code | |||
smpl_t *data = s->phas; | |||
\endcode | |||
\param s vector to read from | |||
*/ | |||
smpl_t * cvec_phas_get_data (const cvec_t *s); | |||
/** print out cvec data | |||
\param s vector to print out | |||
*/ | |||
void cvec_print(const cvec_t *s); | |||
/** make a copy of a vector | |||
\param s source vector | |||
\param t vector to copy to | |||
*/ | |||
void cvec_copy(const cvec_t *s, cvec_t *t); | |||
/** set all norm elements to a given value | |||
\param s vector to modify | |||
\param val value to set elements to | |||
*/ | |||
void cvec_norm_set_all (cvec_t *s, smpl_t val); | |||
/** set all norm elements to zero | |||
\param s vector to modify | |||
*/ | |||
void cvec_norm_zeros(cvec_t *s); | |||
/** set all norm elements to one | |||
\param s vector to modify | |||
*/ | |||
void cvec_norm_ones(cvec_t *s); | |||
/** set all phase elements to a given value | |||
\param s vector to modify | |||
\param val value to set elements to | |||
*/ | |||
void cvec_phas_set_all (cvec_t *s, smpl_t val); | |||
/** set all phase elements to zero | |||
\param s vector to modify | |||
*/ | |||
void cvec_phas_zeros(cvec_t *s); | |||
/** set all phase elements to one | |||
\param s vector to modify | |||
*/ | |||
void cvec_phas_ones(cvec_t *s); | |||
/** set all norm and phas elements to zero | |||
\param s vector to modify | |||
*/ | |||
void cvec_zeros(cvec_t *s); | |||
/** take logarithmic magnitude | |||
\param s input cvec to compress | |||
\param lambda value to use for normalisation | |||
\f$ S_k = log( \lambda * S_k + 1 ) \f$ | |||
*/ | |||
void cvec_logmag(cvec_t *s, smpl_t lambda); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_CVEC_H */ |
@@ -0,0 +1,149 @@ | |||
/* | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
fvec_t * new_fvec(uint_t length) { | |||
fvec_t * s; | |||
if ((sint_t)length <= 0) { | |||
return NULL; | |||
} | |||
s = AUBIO_NEW(fvec_t); | |||
s->length = length; | |||
s->data = AUBIO_ARRAY(smpl_t, s->length); | |||
return s; | |||
} | |||
void del_fvec(fvec_t *s) { | |||
AUBIO_FREE(s->data); | |||
AUBIO_FREE(s); | |||
} | |||
void fvec_set_sample(fvec_t *s, smpl_t data, uint_t position) { | |||
s->data[position] = data; | |||
} | |||
smpl_t fvec_get_sample(const fvec_t *s, uint_t position) { | |||
return s->data[position]; | |||
} | |||
smpl_t * fvec_get_data(const fvec_t *s) { | |||
return s->data; | |||
} | |||
/* helper functions */ | |||
void fvec_print(const fvec_t *s) { | |||
uint_t j; | |||
for (j=0; j< s->length; j++) { | |||
AUBIO_MSG(AUBIO_SMPL_FMT " ", s->data[j]); | |||
} | |||
AUBIO_MSG("\n"); | |||
} | |||
void fvec_set_all (fvec_t *s, smpl_t val) { | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsSet(val, s->data, (int)s->length); | |||
#elif defined(HAVE_ATLAS) | |||
aubio_catlas_set(s->length, val, s->data, 1); | |||
#elif defined(HAVE_ACCELERATE) | |||
aubio_vDSP_vfill(&val, s->data, 1, s->length); | |||
#else | |||
uint_t j; | |||
for ( j = 0; j< s->length; j++ ) | |||
{ | |||
s->data[j] = val; | |||
} | |||
#endif | |||
} | |||
void fvec_zeros(fvec_t *s) { | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsZero(s->data, (int)s->length); | |||
#elif defined(HAVE_ACCELERATE) | |||
aubio_vDSP_vclr(s->data, 1, s->length); | |||
#elif defined(HAVE_MEMCPY_HACKS) | |||
memset(s->data, 0, s->length * sizeof(smpl_t)); | |||
#else | |||
fvec_set_all(s, 0.); | |||
#endif | |||
} | |||
void fvec_ones(fvec_t *s) { | |||
fvec_set_all (s, 1.); | |||
} | |||
void fvec_rev(fvec_t *s) { | |||
uint_t j; | |||
for (j=0; j< FLOOR((smpl_t)s->length/2); j++) { | |||
ELEM_SWAP(s->data[j], s->data[s->length-1-j]); | |||
} | |||
} | |||
void fvec_weight(fvec_t *s, const fvec_t *weight) { | |||
uint_t length = MIN(s->length, weight->length); | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsMul(s->data, weight->data, s->data, (int)length); | |||
#elif defined(HAVE_ACCELERATE) | |||
aubio_vDSP_vmul( s->data, 1, weight->data, 1, s->data, 1, length ); | |||
#else | |||
uint_t j; | |||
for (j = 0; j < length; j++) { | |||
s->data[j] *= weight->data[j]; | |||
} | |||
#endif /* HAVE_ACCELERATE */ | |||
} | |||
void fvec_weighted_copy(const fvec_t *in, const fvec_t *weight, fvec_t *out) { | |||
uint_t length = MIN(in->length, MIN(out->length, weight->length)); | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsMul(in->data, weight->data, out->data, (int)length); | |||
#elif defined(HAVE_ACCELERATE) | |||
aubio_vDSP_vmul(in->data, 1, weight->data, 1, out->data, 1, length); | |||
#else | |||
uint_t j; | |||
for (j = 0; j < length; j++) { | |||
out->data[j] = in->data[j] * weight->data[j]; | |||
} | |||
#endif | |||
} | |||
void fvec_copy(const fvec_t *s, fvec_t *t) { | |||
if (s->length != t->length) { | |||
AUBIO_ERR("trying to copy %d elements to %d elements \n", | |||
s->length, t->length); | |||
return; | |||
} | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsCopy(s->data, t->data, (int)s->length); | |||
#elif defined(HAVE_BLAS) | |||
aubio_cblas_copy(s->length, s->data, 1, t->data, 1); | |||
#elif defined(HAVE_ACCELERATE) | |||
aubio_vDSP_mmov(s->data, t->data, 1, s->length, 1, 1); | |||
#elif defined(HAVE_MEMCPY_HACKS) | |||
memcpy(t->data, s->data, t->length * sizeof(smpl_t)); | |||
#else | |||
uint_t j; | |||
for (j = 0; j < t->length; j++) { | |||
t->data[j] = s->data[j]; | |||
} | |||
#endif | |||
} |
@@ -0,0 +1,178 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef AUBIO_FVEC_H | |||
#define AUBIO_FVEC_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** \file | |||
Vector of real-valued data | |||
This file specifies the ::fvec_t buffer type, which is used throughout aubio | |||
to store vector of real-valued ::smpl_t. | |||
\example test-fvec.c | |||
*/ | |||
/** Buffer for real data | |||
Vector of real-valued data | |||
::fvec_t is is the structure used to store vector of real-valued data, ::smpl_t . | |||
\code | |||
uint_t buffer_size = 1024; | |||
// create a vector of 512 values | |||
fvec_t * input = new_fvec (buffer_size); | |||
// set some values of the vector | |||
input->data[23] = 2.; | |||
// .. | |||
// compute the mean of the vector | |||
mean = fvec_mean(a_vector); | |||
// destroy the vector | |||
del_fvec(a_vector); | |||
\endcode | |||
See `examples/` and `tests/src` directories for more examples. | |||
*/ | |||
typedef struct { | |||
uint_t length; /**< length of buffer */ | |||
smpl_t *data; /**< data vector of length ::fvec_t.length */ | |||
} fvec_t; | |||
/** fvec_t buffer creation function | |||
\param length the length of the buffer to create | |||
*/ | |||
fvec_t * new_fvec(uint_t length); | |||
/** fvec_t buffer deletion function | |||
\param s buffer to delete as returned by new_fvec() | |||
*/ | |||
void del_fvec(fvec_t *s); | |||
/** read sample value in a buffer | |||
\param s vector to read from | |||
\param position sample position to read from | |||
*/ | |||
smpl_t fvec_get_sample(const fvec_t *s, uint_t position); | |||
/** write sample value in a buffer | |||
\param s vector to write to | |||
\param data value to write in s->data[position] | |||
\param position sample position to write to | |||
*/ | |||
void fvec_set_sample(fvec_t *s, smpl_t data, uint_t position); | |||
/** read data from a buffer | |||
\param s vector to read from | |||
*/ | |||
smpl_t * fvec_get_data(const fvec_t *s); | |||
/** print out fvec data | |||
\param s vector to print out | |||
*/ | |||
void fvec_print(const fvec_t *s); | |||
/** set all elements to a given value | |||
\param s vector to modify | |||
\param val value to set elements to | |||
*/ | |||
void fvec_set_all (fvec_t *s, smpl_t val); | |||
/** set all elements to zero | |||
\param s vector to modify | |||
*/ | |||
void fvec_zeros(fvec_t *s); | |||
/** set all elements to ones | |||
\param s vector to modify | |||
*/ | |||
void fvec_ones(fvec_t *s); | |||
/** revert order of vector elements | |||
\param s vector to revert | |||
*/ | |||
void fvec_rev(fvec_t *s); | |||
/** apply weight to vector | |||
If the weight vector is longer than s, only the first elements are used. If | |||
the weight vector is shorter than s, the last elements of s are not weighted. | |||
\param s vector to weight | |||
\param weight weighting coefficients | |||
*/ | |||
void fvec_weight(fvec_t *s, const fvec_t *weight); | |||
/** make a copy of a vector | |||
\param s source vector | |||
\param t vector to copy to | |||
*/ | |||
void fvec_copy(const fvec_t *s, fvec_t *t); | |||
/** make a copy of a vector, applying weights to each element | |||
\param in input vector | |||
\param weight weights vector | |||
\param out output vector | |||
*/ | |||
void fvec_weighted_copy(const fvec_t *in, const fvec_t *weight, fvec_t *out); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_FVEC_H */ |
@@ -0,0 +1,80 @@ | |||
/* | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "lvec.h" | |||
lvec_t * new_lvec(uint_t length) { | |||
lvec_t * s; | |||
if ((sint_t)length <= 0) { | |||
return NULL; | |||
} | |||
s = AUBIO_NEW(lvec_t); | |||
s->length = length; | |||
s->data = AUBIO_ARRAY(lsmp_t, s->length); | |||
return s; | |||
} | |||
void del_lvec(lvec_t *s) { | |||
AUBIO_FREE(s->data); | |||
AUBIO_FREE(s); | |||
} | |||
void lvec_set_sample(lvec_t *s, lsmp_t data, uint_t position) { | |||
s->data[position] = data; | |||
} | |||
lsmp_t lvec_get_sample(lvec_t *s, uint_t position) { | |||
return s->data[position]; | |||
} | |||
lsmp_t * lvec_get_data(const lvec_t *s) { | |||
return s->data; | |||
} | |||
/* helper functions */ | |||
void lvec_print(const lvec_t *s) { | |||
uint_t j; | |||
for (j=0; j< s->length; j++) { | |||
AUBIO_MSG(AUBIO_LSMP_FMT " ", s->data[j]); | |||
} | |||
AUBIO_MSG("\n"); | |||
} | |||
void lvec_set_all (lvec_t *s, smpl_t val) { | |||
uint_t j; | |||
for (j=0; j< s->length; j++) { | |||
s->data[j] = val; | |||
} | |||
} | |||
void lvec_zeros(lvec_t *s) { | |||
#if HAVE_MEMCPY_HACKS | |||
memset(s->data, 0, s->length * sizeof(lsmp_t)); | |||
#else | |||
lvec_set_all (s, 0.); | |||
#endif | |||
} | |||
void lvec_ones(lvec_t *s) { | |||
lvec_set_all (s, 1.); | |||
} | |||
@@ -0,0 +1,118 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef AUBIO_LVEC_H | |||
#define AUBIO_LVEC_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** \file | |||
Vector of real-valued data in double precision | |||
This file specifies the ::lvec_t buffer type, which is used in some places in | |||
aubio to store a vector of ::lsmp_t. | |||
Note: the lvec_t data type is required in some algorithms such as IIR filters | |||
(see temporal/filter.h). | |||
\example test-lvec.c | |||
*/ | |||
/** Buffer for real data in double precision */ | |||
typedef struct { | |||
uint_t length; /**< length of buffer */ | |||
lsmp_t *data; /**< data array of size [length] */ | |||
} lvec_t; | |||
/** lvec_t buffer creation function | |||
\param length the length of the buffer to create | |||
*/ | |||
lvec_t * new_lvec(uint_t length); | |||
/** lvec_t buffer deletion function | |||
\param s buffer to delete as returned by new_lvec() | |||
*/ | |||
void del_lvec(lvec_t *s); | |||
/** read sample value in a buffer | |||
\param s vector to read from | |||
\param position sample position to read from | |||
*/ | |||
lsmp_t lvec_get_sample(lvec_t *s, uint_t position); | |||
/** write sample value in a buffer | |||
\param s vector to write to | |||
\param data value to write in s->data[position] | |||
\param position sample position to write to | |||
*/ | |||
void lvec_set_sample(lvec_t *s, lsmp_t data, uint_t position); | |||
/** read data from a buffer | |||
\param s vector to read from | |||
*/ | |||
lsmp_t * lvec_get_data(const lvec_t *s); | |||
/** print out lvec data | |||
\param s vector to print out | |||
*/ | |||
void lvec_print(const lvec_t *s); | |||
/** set all elements to a given value | |||
\param s vector to modify | |||
\param val value to set elements to | |||
*/ | |||
void lvec_set_all(lvec_t *s, smpl_t val); | |||
/** set all elements to zero | |||
\param s vector to modify | |||
*/ | |||
void lvec_zeros(lvec_t *s); | |||
/** set all elements to ones | |||
\param s vector to modify | |||
*/ | |||
void lvec_ones(lvec_t *s); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_LVEC_H */ |
@@ -0,0 +1,681 @@ | |||
/* | |||
Copyright (C) 2003-2014 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/* see in mathutils.h for doc */ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "mathutils.h" | |||
#include "musicutils.h" | |||
/** Window types */ | |||
typedef enum | |||
{ | |||
aubio_win_ones, | |||
aubio_win_rectangle, | |||
aubio_win_hamming, | |||
aubio_win_hanning, | |||
aubio_win_hanningz, | |||
aubio_win_blackman, | |||
aubio_win_blackman_harris, | |||
aubio_win_gaussian, | |||
aubio_win_welch, | |||
aubio_win_parzen, | |||
aubio_win_default = aubio_win_hanningz, | |||
} aubio_window_type; | |||
fvec_t * | |||
new_aubio_window (char_t * window_type, uint_t length) | |||
{ | |||
fvec_t * win = new_fvec (length); | |||
uint_t err; | |||
if (win == NULL) { | |||
return NULL; | |||
} | |||
err = fvec_set_window (win, window_type); | |||
if (err != 0) { | |||
del_fvec(win); | |||
return NULL; | |||
} | |||
return win; | |||
} | |||
uint_t fvec_set_window (fvec_t *win, char_t *window_type) { | |||
smpl_t * w = win->data; | |||
uint_t i, size = win->length; | |||
aubio_window_type wintype; | |||
if (window_type == NULL) { | |||
AUBIO_ERR ("window type can not be null.\n"); | |||
return 1; | |||
} else if (strcmp (window_type, "ones") == 0) | |||
wintype = aubio_win_ones; | |||
else if (strcmp (window_type, "rectangle") == 0) | |||
wintype = aubio_win_rectangle; | |||
else if (strcmp (window_type, "hamming") == 0) | |||
wintype = aubio_win_hamming; | |||
else if (strcmp (window_type, "hanning") == 0) | |||
wintype = aubio_win_hanning; | |||
else if (strcmp (window_type, "hanningz") == 0) | |||
wintype = aubio_win_hanningz; | |||
else if (strcmp (window_type, "blackman") == 0) | |||
wintype = aubio_win_blackman; | |||
else if (strcmp (window_type, "blackman_harris") == 0) | |||
wintype = aubio_win_blackman_harris; | |||
else if (strcmp (window_type, "gaussian") == 0) | |||
wintype = aubio_win_gaussian; | |||
else if (strcmp (window_type, "welch") == 0) | |||
wintype = aubio_win_welch; | |||
else if (strcmp (window_type, "parzen") == 0) | |||
wintype = aubio_win_parzen; | |||
else if (strcmp (window_type, "default") == 0) | |||
wintype = aubio_win_default; | |||
else { | |||
AUBIO_ERR ("unknown window type `%s`.\n", window_type); | |||
return 1; | |||
} | |||
switch(wintype) { | |||
case aubio_win_ones: | |||
fvec_ones(win); | |||
break; | |||
case aubio_win_rectangle: | |||
fvec_set_all(win, .5); | |||
break; | |||
case aubio_win_hamming: | |||
for (i=0;i<size;i++) | |||
w[i] = 0.54 - 0.46 * COS(TWO_PI * i / (size)); | |||
break; | |||
case aubio_win_hanning: | |||
for (i=0;i<size;i++) | |||
w[i] = 0.5 - (0.5 * COS(TWO_PI * i / (size))); | |||
break; | |||
case aubio_win_hanningz: | |||
for (i=0;i<size;i++) | |||
w[i] = 0.5 * (1.0 - COS(TWO_PI * i / (size))); | |||
break; | |||
case aubio_win_blackman: | |||
for (i=0;i<size;i++) | |||
w[i] = 0.42 | |||
- 0.50 * COS( TWO_PI*i/(size-1.0)) | |||
+ 0.08 * COS(2.0*TWO_PI*i/(size-1.0)); | |||
break; | |||
case aubio_win_blackman_harris: | |||
for (i=0;i<size;i++) | |||
w[i] = 0.35875 | |||
- 0.48829 * COS( TWO_PI*i/(size-1.0)) | |||
+ 0.14128 * COS(2.0*TWO_PI*i/(size-1.0)) | |||
- 0.01168 * COS(3.0*TWO_PI*i/(size-1.0)); | |||
break; | |||
case aubio_win_gaussian: | |||
{ | |||
lsmp_t a, b, c = 0.5; | |||
uint_t n; | |||
for (n = 0; n < size; n++) | |||
{ | |||
a = (n-c*(size-1))/(SQR(c)*(size-1)); | |||
b = -c*SQR(a); | |||
w[n] = EXP(b); | |||
} | |||
} | |||
break; | |||
case aubio_win_welch: | |||
for (i=0;i<size;i++) | |||
w[i] = 1.0 - SQR((2.*i-size)/(size+1.0)); | |||
break; | |||
case aubio_win_parzen: | |||
for (i=0;i<size;i++) | |||
w[i] = 1.0 - ABS((2.f*i-size)/(size+1.0f)); | |||
break; | |||
default: | |||
break; | |||
} | |||
return 0; | |||
} | |||
smpl_t | |||
aubio_unwrap2pi (smpl_t phase) | |||
{ | |||
/* mod(phase+pi,-2pi)+pi */ | |||
return phase + TWO_PI * (1. + FLOOR (-(phase + PI) / TWO_PI)); | |||
} | |||
smpl_t | |||
fvec_mean (fvec_t * s) | |||
{ | |||
smpl_t tmp = 0.0; | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsMean(s->data, (int)s->length, &tmp); | |||
return tmp; | |||
#elif defined(HAVE_ACCELERATE) | |||
aubio_vDSP_meanv(s->data, 1, &tmp, s->length); | |||
return tmp; | |||
#else | |||
uint_t j; | |||
for (j = 0; j < s->length; j++) { | |||
tmp += s->data[j]; | |||
} | |||
return tmp / (smpl_t)(s->length); | |||
#endif | |||
} | |||
smpl_t | |||
fvec_sum (fvec_t * s) | |||
{ | |||
smpl_t tmp = 0.0; | |||
#if defined(HAVE_INTEL_IPP) | |||
aubio_ippsSum(s->data, (int)s->length, &tmp); | |||
#elif defined(HAVE_ACCELERATE) | |||
aubio_vDSP_sve(s->data, 1, &tmp, s->length); | |||
#else | |||
uint_t j; | |||
for (j = 0; j < s->length; j++) { | |||
tmp += s->data[j]; | |||
} | |||
#endif | |||
return tmp; | |||
} | |||
smpl_t | |||
fvec_max (fvec_t * s) | |||
{ | |||
#if defined(HAVE_INTEL_IPP) | |||
smpl_t tmp = 0.; | |||
aubio_ippsMax( s->data, (int)s->length, &tmp); | |||
#elif defined(HAVE_ACCELERATE) | |||
smpl_t tmp = 0.; | |||
aubio_vDSP_maxv( s->data, 1, &tmp, s->length ); | |||
#else | |||
uint_t j; | |||
smpl_t tmp = s->data[0]; | |||
for (j = 1; j < s->length; j++) { | |||
tmp = (tmp > s->data[j]) ? tmp : s->data[j]; | |||
} | |||
#endif | |||
return tmp; | |||
} | |||
smpl_t | |||
fvec_min (fvec_t * s) | |||
{ | |||
#if defined(HAVE_INTEL_IPP) | |||
smpl_t tmp = 0.; | |||
aubio_ippsMin(s->data, (int)s->length, &tmp); | |||
#elif defined(HAVE_ACCELERATE) | |||
smpl_t tmp = 0.; | |||
aubio_vDSP_minv(s->data, 1, &tmp, s->length); | |||
#else | |||
uint_t j; | |||
smpl_t tmp = s->data[0]; | |||
for (j = 1; j < s->length; j++) { | |||
tmp = (tmp < s->data[j]) ? tmp : s->data[j]; | |||
} | |||
#endif | |||
return tmp; | |||
} | |||
uint_t | |||
fvec_min_elem (fvec_t * s) | |||
{ | |||
#ifndef HAVE_ACCELERATE | |||
uint_t j, pos = 0.; | |||
smpl_t tmp = s->data[0]; | |||
for (j = 0; j < s->length; j++) { | |||
pos = (tmp < s->data[j]) ? pos : j; | |||
tmp = (tmp < s->data[j]) ? tmp : s->data[j]; | |||
} | |||
#else | |||
smpl_t tmp = 0.; | |||
vDSP_Length pos = 0; | |||
aubio_vDSP_minvi(s->data, 1, &tmp, &pos, s->length); | |||
#endif | |||
return (uint_t)pos; | |||
} | |||
uint_t | |||
fvec_max_elem (fvec_t * s) | |||
{ | |||
#ifndef HAVE_ACCELERATE | |||
uint_t j, pos = 0; | |||
smpl_t tmp = 0.0; | |||
for (j = 0; j < s->length; j++) { | |||
pos = (tmp > s->data[j]) ? pos : j; | |||
tmp = (tmp > s->data[j]) ? tmp : s->data[j]; | |||
} | |||
#else | |||
smpl_t tmp = 0.; | |||
vDSP_Length pos = 0; | |||
aubio_vDSP_maxvi(s->data, 1, &tmp, &pos, s->length); | |||
#endif | |||
return (uint_t)pos; | |||
} | |||
void | |||
fvec_shift (fvec_t * s) | |||
{ | |||
uint_t half = s->length / 2, start = half, j; | |||
// if length is odd, middle element is moved to the end | |||
if (2 * half < s->length) start ++; | |||
#ifndef HAVE_BLAS | |||
for (j = 0; j < half; j++) { | |||
ELEM_SWAP (s->data[j], s->data[j + start]); | |||
} | |||
#else | |||
aubio_cblas_swap(half, s->data, 1, s->data + start, 1); | |||
#endif | |||
if (start != half) { | |||
for (j = 0; j < half; j++) { | |||
ELEM_SWAP (s->data[j + start - 1], s->data[j + start]); | |||
} | |||
} | |||
} | |||
void | |||
fvec_ishift (fvec_t * s) | |||
{ | |||
uint_t half = s->length / 2, start = half, j; | |||
// if length is odd, middle element is moved to the beginning | |||
if (2 * half < s->length) start ++; | |||
#ifndef HAVE_BLAS | |||
for (j = 0; j < half; j++) { | |||
ELEM_SWAP (s->data[j], s->data[j + start]); | |||
} | |||
#else | |||
aubio_cblas_swap(half, s->data, 1, s->data + start, 1); | |||
#endif | |||
if (start != half) { | |||
for (j = 0; j < half; j++) { | |||
ELEM_SWAP (s->data[half], s->data[j]); | |||
} | |||
} | |||
} | |||
void fvec_push(fvec_t *in, smpl_t new_elem) { | |||
uint_t i; | |||
for (i = 0; i < in->length - 1; i++) { | |||
in->data[i] = in->data[i + 1]; | |||
} | |||
in->data[in->length - 1] = new_elem; | |||
} | |||
void fvec_clamp(fvec_t *in, smpl_t absmax) { | |||
uint_t i; | |||
for (i = 0; i < in->length; i++) { | |||
if (in->data[i] > 0 && in->data[i] > ABS(absmax)) { | |||
in->data[i] = absmax; | |||
} else if (in->data[i] < 0 && in->data[i] < -ABS(absmax)) { | |||
in->data[i] = -absmax; | |||
} | |||
} | |||
} | |||
smpl_t | |||
aubio_level_lin (const fvec_t * f) | |||
{ | |||
smpl_t energy = 0.; | |||
#ifndef HAVE_BLAS | |||
uint_t j; | |||
for (j = 0; j < f->length; j++) { | |||
energy += SQR (f->data[j]); | |||
} | |||
#else | |||
energy = aubio_cblas_dot(f->length, f->data, 1, f->data, 1); | |||
#endif | |||
return energy / f->length; | |||
} | |||
smpl_t | |||
fvec_local_hfc (fvec_t * v) | |||
{ | |||
smpl_t hfc = 0.; | |||
uint_t j; | |||
for (j = 0; j < v->length; j++) { | |||
hfc += (j + 1) * v->data[j]; | |||
} | |||
return hfc; | |||
} | |||
void | |||
fvec_min_removal (fvec_t * v) | |||
{ | |||
smpl_t v_min = fvec_min (v); | |||
fvec_add (v, - v_min ); | |||
} | |||
smpl_t | |||
fvec_alpha_norm (fvec_t * o, smpl_t alpha) | |||
{ | |||
uint_t j; | |||
smpl_t tmp = 0.; | |||
for (j = 0; j < o->length; j++) { | |||
tmp += POW (ABS (o->data[j]), alpha); | |||
} | |||
return POW (tmp / o->length, 1. / alpha); | |||
} | |||
void | |||
fvec_alpha_normalise (fvec_t * o, smpl_t alpha) | |||
{ | |||
uint_t j; | |||
smpl_t norm = fvec_alpha_norm (o, alpha); | |||
for (j = 0; j < o->length; j++) { | |||
o->data[j] /= norm; | |||
} | |||
} | |||
void | |||
fvec_add (fvec_t * o, smpl_t val) | |||
{ | |||
uint_t j; | |||
for (j = 0; j < o->length; j++) { | |||
o->data[j] += val; | |||
} | |||
} | |||
void | |||
fvec_mul (fvec_t *o, smpl_t val) | |||
{ | |||
uint_t j; | |||
for (j = 0; j < o->length; j++) { | |||
o->data[j] *= val; | |||
} | |||
} | |||
void fvec_adapt_thres(fvec_t * vec, fvec_t * tmp, | |||
uint_t post, uint_t pre) { | |||
uint_t length = vec->length, j; | |||
for (j=0;j<length;j++) { | |||
vec->data[j] -= fvec_moving_thres(vec, tmp, post, pre, j); | |||
} | |||
} | |||
smpl_t | |||
fvec_moving_thres (fvec_t * vec, fvec_t * tmpvec, | |||
uint_t post, uint_t pre, uint_t pos) | |||
{ | |||
uint_t k; | |||
smpl_t *medar = (smpl_t *) tmpvec->data; | |||
uint_t win_length = post + pre + 1; | |||
uint_t length = vec->length; | |||
/* post part of the buffer does not exist */ | |||
if (pos < post + 1) { | |||
for (k = 0; k < post + 1 - pos; k++) | |||
medar[k] = 0.; /* 0-padding at the beginning */ | |||
for (k = post + 1 - pos; k < win_length; k++) | |||
medar[k] = vec->data[k + pos - post]; | |||
/* the buffer is fully defined */ | |||
} else if (pos + pre < length) { | |||
for (k = 0; k < win_length; k++) | |||
medar[k] = vec->data[k + pos - post]; | |||
/* pre part of the buffer does not exist */ | |||
} else { | |||
for (k = 0; k < length - pos + post; k++) | |||
medar[k] = vec->data[k + pos - post]; | |||
for (k = length - pos + post; k < win_length; k++) | |||
medar[k] = 0.; /* 0-padding at the end */ | |||
} | |||
return fvec_median (tmpvec); | |||
} | |||
smpl_t fvec_median (fvec_t * input) { | |||
uint_t n = input->length; | |||
smpl_t * arr = (smpl_t *) input->data; | |||
uint_t low, high ; | |||
uint_t median; | |||
uint_t middle, ll, hh; | |||
low = 0 ; high = n-1 ; median = (low + high) / 2; | |||
for (;;) { | |||
if (high <= low) /* One element only */ | |||
return arr[median] ; | |||
if (high == low + 1) { /* Two elements only */ | |||
if (arr[low] > arr[high]) | |||
ELEM_SWAP(arr[low], arr[high]) ; | |||
return arr[median] ; | |||
} | |||
/* Find median of low, middle and high items; swap into position low */ | |||
middle = (low + high) / 2; | |||
if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]); | |||
if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]); | |||
if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; | |||
/* Swap low item (now in position middle) into position (low+1) */ | |||
ELEM_SWAP(arr[middle], arr[low+1]) ; | |||
/* Nibble from each end towards middle, swapping items when stuck */ | |||
ll = low + 1; | |||
hh = high; | |||
for (;;) { | |||
do ll++; while (arr[low] > arr[ll]) ; | |||
do hh--; while (arr[hh] > arr[low]) ; | |||
if (hh < ll) | |||
break; | |||
ELEM_SWAP(arr[ll], arr[hh]) ; | |||
} | |||
/* Swap middle item (in position low) back into correct position */ | |||
ELEM_SWAP(arr[low], arr[hh]) ; | |||
/* Re-set active partition */ | |||
if (hh <= median) | |||
low = ll; | |||
if (hh >= median) | |||
high = hh - 1; | |||
} | |||
} | |||
smpl_t fvec_quadratic_peak_pos (const fvec_t * x, uint_t pos) { | |||
smpl_t s0, s1, s2; uint_t x0, x2; | |||
smpl_t half = .5, two = 2.; | |||
if (pos == 0 || pos == x->length - 1) return pos; | |||
x0 = (pos < 1) ? pos : pos - 1; | |||
x2 = (pos + 1 < x->length) ? pos + 1 : pos; | |||
if (x0 == pos) return (x->data[pos] <= x->data[x2]) ? pos : x2; | |||
if (x2 == pos) return (x->data[pos] <= x->data[x0]) ? pos : x0; | |||
s0 = x->data[x0]; | |||
s1 = x->data[pos]; | |||
s2 = x->data[x2]; | |||
return pos + half * (s0 - s2 ) / (s0 - two * s1 + s2); | |||
} | |||
smpl_t fvec_quadratic_peak_mag (fvec_t *x, smpl_t pos) { | |||
smpl_t x0, x1, x2; | |||
uint_t index = (uint_t)(pos - .5) + 1; | |||
if (pos >= x->length || pos < 0.) return 0.; | |||
if ((smpl_t)index == pos) return x->data[index]; | |||
x0 = x->data[index - 1]; | |||
x1 = x->data[index]; | |||
x2 = x->data[index + 1]; | |||
return x1 - .25 * (x0 - x2) * (pos - index); | |||
} | |||
uint_t fvec_peakpick(const fvec_t * onset, uint_t pos) { | |||
uint_t tmp=0; | |||
tmp = (onset->data[pos] > onset->data[pos-1] | |||
&& onset->data[pos] > onset->data[pos+1] | |||
&& onset->data[pos] > 0.); | |||
return tmp; | |||
} | |||
smpl_t | |||
aubio_quadfrac (smpl_t s0, smpl_t s1, smpl_t s2, smpl_t pf) | |||
{ | |||
smpl_t tmp = | |||
s0 + (pf / 2.) * (pf * (s0 - 2. * s1 + s2) - 3. * s0 + 4. * s1 - s2); | |||
return tmp; | |||
} | |||
smpl_t | |||
aubio_freqtomidi (smpl_t freq) | |||
{ | |||
smpl_t midi; | |||
if (freq < 2. || freq > 100000.) return 0.; // avoid nans and infs | |||
/* log(freq/A-2)/log(2) */ | |||
midi = freq / 6.875; | |||
midi = LOG (midi) / 0.6931471805599453; | |||
midi *= 12; | |||
midi -= 3; | |||
return midi; | |||
} | |||
smpl_t | |||
aubio_miditofreq (smpl_t midi) | |||
{ | |||
smpl_t freq; | |||
if (midi > 140.) return 0.; // avoid infs | |||
freq = (midi + 3.) / 12.; | |||
freq = EXP (freq * 0.6931471805599453); | |||
freq *= 6.875; | |||
return freq; | |||
} | |||
smpl_t | |||
aubio_bintofreq (smpl_t bin, smpl_t samplerate, smpl_t fftsize) | |||
{ | |||
smpl_t freq = samplerate / fftsize; | |||
return freq * MAX(bin, 0); | |||
} | |||
smpl_t | |||
aubio_bintomidi (smpl_t bin, smpl_t samplerate, smpl_t fftsize) | |||
{ | |||
smpl_t midi = aubio_bintofreq (bin, samplerate, fftsize); | |||
return aubio_freqtomidi (midi); | |||
} | |||
smpl_t | |||
aubio_freqtobin (smpl_t freq, smpl_t samplerate, smpl_t fftsize) | |||
{ | |||
smpl_t bin = fftsize / samplerate; | |||
return MAX(freq, 0) * bin; | |||
} | |||
smpl_t | |||
aubio_miditobin (smpl_t midi, smpl_t samplerate, smpl_t fftsize) | |||
{ | |||
smpl_t freq = aubio_miditofreq (midi); | |||
return aubio_freqtobin (freq, samplerate, fftsize); | |||
} | |||
uint_t | |||
aubio_is_power_of_two (uint_t a) | |||
{ | |||
if ((a & (a - 1)) == 0) { | |||
return 1; | |||
} else { | |||
return 0; | |||
} | |||
} | |||
uint_t | |||
aubio_next_power_of_two (uint_t a) | |||
{ | |||
uint_t i = 1; | |||
while (i < a) i <<= 1; | |||
return i; | |||
} | |||
uint_t | |||
aubio_power_of_two_order (uint_t a) | |||
{ | |||
int order = 0; | |||
int temp = aubio_next_power_of_two(a); | |||
while (temp >>= 1) { | |||
++order; | |||
} | |||
return order; | |||
} | |||
smpl_t | |||
aubio_db_spl (const fvec_t * o) | |||
{ | |||
return 10. * LOG10 (aubio_level_lin (o)); | |||
} | |||
uint_t | |||
aubio_silence_detection (const fvec_t * o, smpl_t threshold) | |||
{ | |||
return (aubio_db_spl (o) < threshold); | |||
} | |||
smpl_t | |||
aubio_level_detection (const fvec_t * o, smpl_t threshold) | |||
{ | |||
smpl_t db_spl = aubio_db_spl (o); | |||
if (db_spl < threshold) { | |||
return 1.; | |||
} else { | |||
return db_spl; | |||
} | |||
} | |||
smpl_t | |||
aubio_zero_crossing_rate (fvec_t * input) | |||
{ | |||
uint_t j; | |||
uint_t zcr = 0; | |||
for (j = 1; j < input->length; j++) { | |||
// previous was strictly negative | |||
if (input->data[j - 1] < 0.) { | |||
// current is positive or null | |||
if (input->data[j] >= 0.) { | |||
zcr += 1; | |||
} | |||
// previous was positive or null | |||
} else { | |||
// current is strictly negative | |||
if (input->data[j] < 0.) { | |||
zcr += 1; | |||
} | |||
} | |||
} | |||
return zcr / (smpl_t) input->length; | |||
} | |||
void | |||
aubio_autocorr (const fvec_t * input, fvec_t * output) | |||
{ | |||
uint_t i, j, length = input->length; | |||
smpl_t *data, *acf; | |||
smpl_t tmp = 0; | |||
data = input->data; | |||
acf = output->data; | |||
for (i = 0; i < length; i++) { | |||
tmp = 0.; | |||
for (j = i; j < length; j++) { | |||
tmp += data[j - i] * data[j]; | |||
} | |||
acf[i] = tmp / (smpl_t) (length - i); | |||
} | |||
} | |||
void | |||
aubio_cleanup (void) | |||
{ | |||
#ifdef HAVE_FFTW3F | |||
fftwf_cleanup (); | |||
#else | |||
#ifdef HAVE_FFTW3 | |||
fftw_cleanup (); | |||
#endif | |||
#endif | |||
} |
@@ -0,0 +1,338 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** \file | |||
Various math functions | |||
\example test-mathutils.c | |||
\example test-mathutils-window.c | |||
*/ | |||
#ifndef AUBIO_MATHUTILS_H | |||
#define AUBIO_MATHUTILS_H | |||
#include "fvec.h" | |||
#include "musicutils.h" | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** compute the mean of a vector | |||
\param s vector to compute mean from | |||
\return the mean of `v` | |||
*/ | |||
smpl_t fvec_mean (fvec_t * s); | |||
/** find the max of a vector | |||
\param s vector to get the max from | |||
\return the value of the minimum of v | |||
*/ | |||
smpl_t fvec_max (fvec_t * s); | |||
/** find the min of a vector | |||
\param s vector to get the min from | |||
\return the value of the maximum of v | |||
*/ | |||
smpl_t fvec_min (fvec_t * s); | |||
/** find the index of the min of a vector | |||
\param s vector to get the index from | |||
\return the index of the minimum element of v | |||
*/ | |||
uint_t fvec_min_elem (fvec_t * s); | |||
/** find the index of the max of a vector | |||
\param s vector to get the index from | |||
\return the index of the maximum element of v | |||
*/ | |||
uint_t fvec_max_elem (fvec_t * s); | |||
/** swap the left and right halves of a vector | |||
This function swaps the left part of the signal with the right part of the | |||
signal. Therefore | |||
\f$ a[0], a[1], ..., a[\frac{N}{2}], a[\frac{N}{2}+1], ..., a[N-1], a[N] \f$ | |||
becomes | |||
\f$ a[\frac{N}{2}+1], ..., a[N-1], a[N], a[0], a[1], ..., a[\frac{N}{2}] \f$ | |||
This operation, known as 'fftshift' in the Matlab Signal Processing Toolbox, | |||
can be used before computing the FFT to simplify the phase relationship of the | |||
resulting spectrum. See Amalia de Götzen's paper referred to above. | |||
*/ | |||
void fvec_shift (fvec_t * v); | |||
/** swap the left and right halves of a vector | |||
This function swaps the left part of the signal with the right part of the | |||
signal. Therefore | |||
\f$ a[0], a[1], ..., a[\frac{N}{2}], a[\frac{N}{2}+1], ..., a[N-1], a[N] \f$ | |||
becomes | |||
\f$ a[\frac{N}{2}+1], ..., a[N-1], a[N], a[0], a[1], ..., a[\frac{N}{2}] \f$ | |||
This operation, known as 'ifftshift' in the Matlab Signal Processing Toolbox, | |||
can be used after computing the inverse FFT to simplify the phase relationship | |||
of the resulting spectrum. See Amalia de Götzen's paper referred to above. | |||
*/ | |||
void fvec_ishift (fvec_t * v); | |||
/** push a new element to the end of a vector, erasing the first element and | |||
* sliding all others | |||
\param in vector to push to | |||
\param new_elem new_element to add at the end of the vector | |||
In numpy words, this is equivalent to: in = np.concatenate([in, [new_elem]])[1:] | |||
*/ | |||
void fvec_push(fvec_t *in, smpl_t new_elem); | |||
/** compute the sum of all elements of a vector | |||
\param v vector to compute the sum of | |||
\return the sum of v | |||
*/ | |||
smpl_t fvec_sum (fvec_t * v); | |||
/** compute the High Frequency Content of a vector | |||
The High Frequency Content is defined as \f$ \sum_0^{N-1} (k+1) v[k] \f$. | |||
\param v vector to get the energy from | |||
\return the HFC of v | |||
*/ | |||
smpl_t fvec_local_hfc (fvec_t * v); | |||
/** computes the p-norm of a vector | |||
Computes the p-norm of a vector for \f$ p = \alpha \f$ | |||
\f$ L^p = ||x||_p = (|x_1|^p + |x_2|^p + ... + |x_n|^p ) ^ \frac{1}{p} \f$ | |||
If p = 1, the result is the Manhattan distance. | |||
If p = 2, the result is the Euclidean distance. | |||
As p tends towards large values, \f$ L^p \f$ tends towards the maximum of the | |||
input vector. | |||
References: | |||
- <a href="http://en.wikipedia.org/wiki/Lp_space">\f$L^p\f$ space</a> on | |||
Wikipedia | |||
\param v vector to compute norm from | |||
\param p order of the computed norm | |||
\return the p-norm of v | |||
*/ | |||
smpl_t fvec_alpha_norm (fvec_t * v, smpl_t p); | |||
/** alpha normalisation | |||
This function divides all elements of a vector by the p-norm as computed by | |||
fvec_alpha_norm(). | |||
\param v vector to compute norm from | |||
\param p order of the computed norm | |||
*/ | |||
void fvec_alpha_normalise (fvec_t * v, smpl_t p); | |||
/** add a constant to each elements of a vector | |||
\param v vector to add constant to | |||
\param c constant to add to v | |||
*/ | |||
void fvec_add (fvec_t * v, smpl_t c); | |||
/** multiply each elements of a vector by a scalar | |||
\param v vector to add constant to | |||
\param s constant to scale v with | |||
*/ | |||
void fvec_mul (fvec_t * v, smpl_t s); | |||
/** remove the minimum value of the vector to each elements | |||
\param v vector to remove minimum from | |||
*/ | |||
void fvec_min_removal (fvec_t * v); | |||
/** compute moving median threshold of a vector | |||
This function computes the moving median threshold value of at the given | |||
position of a vector, taking the median among post elements before and up to | |||
pre elements after pos. | |||
\param v input vector | |||
\param tmp temporary vector of length post+1+pre | |||
\param post length of causal part to take before pos | |||
\param pre length of anti-causal part to take after pos | |||
\param pos index to compute threshold for | |||
\return moving median threshold value | |||
*/ | |||
smpl_t fvec_moving_thres (fvec_t * v, fvec_t * tmp, uint_t post, uint_t pre, | |||
uint_t pos); | |||
/** apply adaptive threshold to a vector | |||
For each points at position p of an input vector, this function remove the | |||
moving median threshold computed at p. | |||
\param v input vector | |||
\param tmp temporary vector of length post+1+pre | |||
\param post length of causal part to take before pos | |||
\param pre length of anti-causal part to take after pos | |||
*/ | |||
void fvec_adapt_thres (fvec_t * v, fvec_t * tmp, uint_t post, uint_t pre); | |||
/** returns the median of a vector | |||
The QuickSelect routine is based on the algorithm described in "Numerical | |||
recipes in C", Second Edition, Cambridge University Press, 1992, Section 8.5, | |||
ISBN 0-521-43108-5 | |||
This implementation of the QuickSelect routine is based on Nicolas | |||
Devillard's implementation, available at http://ndevilla.free.fr/median/median/ | |||
and in the Public Domain. | |||
\param v vector to get median from | |||
\return the median of v | |||
*/ | |||
smpl_t fvec_median (fvec_t * v); | |||
/** finds exact peak index by quadratic interpolation | |||
See [Quadratic Interpolation of Spectral | |||
Peaks](https://ccrma.stanford.edu/~jos/sasp/Quadratic_Peak_Interpolation.html), | |||
by Julius O. Smith III | |||
\f$ p_{frac} = \frac{1}{2} \frac {x[p-1] - x[p+1]} {x[p-1] - 2 x[p] + x[p+1]} \in [ -.5, .5] \f$ | |||
\param x vector to get the interpolated peak position from | |||
\param p index of the peak in vector `x` | |||
\return \f$ p + p_{frac} \f$ exact peak position of interpolated maximum or minimum | |||
*/ | |||
smpl_t fvec_quadratic_peak_pos (const fvec_t * x, uint_t p); | |||
/** finds magnitude of peak by quadratic interpolation | |||
See [Quadratic Interpolation of Spectral | |||
Peaks](https://ccrma.stanford.edu/~jos/sasp/Quadratic_Peak_Interpolation.html), | |||
by Julius O. Smith III | |||
\param x vector to get the magnitude of the interpolated peak position from | |||
\param p index of the peak in vector `x` | |||
\return magnitude of interpolated peak | |||
*/ | |||
smpl_t fvec_quadratic_peak_mag (fvec_t * x, smpl_t p); | |||
/** Quadratic interpolation using Lagrange polynomial. | |||
Inspired from ``Comparison of interpolation algorithms in real-time sound | |||
processing'', Vladimir Arnost, | |||
\param s0,s1,s2 are 3 consecutive samples of a curve | |||
\param pf is the floating point index [0;2] | |||
\return \f$ s0 + (pf/2.)*((pf-3.)*s0-2.*(pf-2.)*s1+(pf-1.)*s2); \f$ | |||
*/ | |||
smpl_t aubio_quadfrac (smpl_t s0, smpl_t s1, smpl_t s2, smpl_t pf); | |||
/** return 1 if v[p] is a peak and positive, 0 otherwise | |||
This function returns 1 if a peak is found at index p in the vector v. The | |||
peak is defined as follows: | |||
- v[p] is positive | |||
- v[p-1] < v[p] | |||
- v[p] > v[p+1] | |||
\param v input vector | |||
\param p position of supposed for peak | |||
\return 1 if a peak is found, 0 otherwise | |||
*/ | |||
uint_t fvec_peakpick (const fvec_t * v, uint_t p); | |||
/** return 1 if a is a power of 2, 0 otherwise */ | |||
uint_t aubio_is_power_of_two(uint_t a); | |||
/** return the next power of power of 2 greater than a */ | |||
uint_t aubio_next_power_of_two(uint_t a); | |||
/** return the log2 factor of the given power of 2 value a */ | |||
uint_t aubio_power_of_two_order(uint_t a); | |||
/** compute normalised autocorrelation function | |||
\param input vector to compute autocorrelation from | |||
\param output vector to store autocorrelation function to | |||
*/ | |||
void aubio_autocorr (const fvec_t * input, fvec_t * output); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_MATHUTILS_H */ |
@@ -0,0 +1,270 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** @file | |||
* various functions useful in audio signal processing | |||
*/ | |||
#ifndef AUBIO_MUSICUTILS_H | |||
#define AUBIO_MUSICUTILS_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** create window | |||
\param window_type type of the window to create | |||
\param size length of the window to create (see fvec_set_window()) | |||
*/ | |||
fvec_t *new_aubio_window (char_t * window_type, uint_t size); | |||
/** set elements of a vector to window coefficients | |||
\param window exsting ::fvec_t to use | |||
\param window_type type of the window to create | |||
List of available window types: "rectangle", "hamming", "hanning", | |||
"hanningz", "blackman", "blackman_harris", "gaussian", "welch", "parzen", | |||
"default". | |||
"default" is equivalent to "hanningz". | |||
References: | |||
- <a href="http://en.wikipedia.org/wiki/Window_function">Window | |||
function</a> on Wikipedia | |||
- Amalia de Götzen, Nicolas Bernardini, and Daniel Arfib. Traditional (?) | |||
implementations of a phase vocoder: the tricks of the trade. In Proceedings of | |||
the International Conference on Digital Audio Effects (DAFx-00), pages 37–44, | |||
Uni- versity of Verona, Italy, 2000. | |||
(<a href="http://www.cs.princeton.edu/courses/archive/spr09/cos325/Bernardini.pdf"> | |||
pdf</a>) | |||
*/ | |||
uint_t fvec_set_window (fvec_t * window, char_t * window_type); | |||
/** compute the principal argument | |||
This function maps the input phase to its corresponding value wrapped in the | |||
range \f$ [-\pi, \pi] \f$. | |||
\param phase unwrapped phase to map to the unit circle | |||
\return equivalent phase wrapped to the unit circle | |||
*/ | |||
smpl_t aubio_unwrap2pi (smpl_t phase); | |||
/** convert frequency bin to midi value */ | |||
smpl_t aubio_bintomidi (smpl_t bin, smpl_t samplerate, smpl_t fftsize); | |||
/** convert midi value to frequency bin */ | |||
smpl_t aubio_miditobin (smpl_t midi, smpl_t samplerate, smpl_t fftsize); | |||
/** convert frequency bin to frequency (Hz) */ | |||
smpl_t aubio_bintofreq (smpl_t bin, smpl_t samplerate, smpl_t fftsize); | |||
/** convert frequency (Hz) to frequency bin */ | |||
smpl_t aubio_freqtobin (smpl_t freq, smpl_t samplerate, smpl_t fftsize); | |||
/** convert frequency (Hz) to mel | |||
\param freq input frequency, in Hz | |||
\return output mel | |||
Converts a scalar from the frequency domain to the mel scale using Slaney | |||
Auditory Toolbox's implementation: | |||
If \f$ f < 1000 \f$, \f$ m = 3 f / 200 \f$. | |||
If \f$ f >= 1000 \f$, \f$ m = 1000 + 27 \frac{{ln}(f) - ln(1000))} | |||
{{ln}(6400) - ln(1000)} | |||
\f$ | |||
See also | |||
-------- | |||
aubio_meltohz(), aubio_hztomel_htk(). | |||
*/ | |||
smpl_t aubio_hztomel (smpl_t freq); | |||
/** convert mel to frequency (Hz) | |||
\param mel input mel | |||
\return output frequency, in Hz | |||
Converts a scalar from the mel scale to the frequency domain using Slaney | |||
Auditory Toolbox's implementation: | |||
If \f$ f < 1000 \f$, \f$ f = 200 m/3 \f$. | |||
If \f$ f \geq 1000 \f$, \f$ f = 1000 + \left(\frac{6400}{1000}\right) | |||
^{\frac{m - 1000}{27}} \f$ | |||
See also | |||
-------- | |||
aubio_hztomel(), aubio_meltohz_htk(). | |||
References | |||
---------- | |||
Malcolm Slaney, *Auditory Toolbox Version 2, Technical Report #1998-010* | |||
https://engineering.purdue.edu/~malcolm/interval/1998-010/ | |||
*/ | |||
smpl_t aubio_meltohz (smpl_t mel); | |||
/** convert frequency (Hz) to mel | |||
\param freq input frequency, in Hz | |||
\return output mel | |||
Converts a scalar from the frequency domain to the mel scale, using the | |||
equation defined by O'Shaughnessy, as implemented in the HTK speech | |||
recognition toolkit: | |||
\f$ m = 1127 + ln(1 + \frac{f}{700}) \f$ | |||
See also | |||
-------- | |||
aubio_meltohz_htk(), aubio_hztomel(). | |||
References | |||
---------- | |||
Douglas O'Shaughnessy (1987). *Speech communication: human and machine*. | |||
Addison-Wesley. p. 150. ISBN 978-0-201-16520-3. | |||
HTK Speech Recognition Toolkit: http://htk.eng.cam.ac.uk/ | |||
*/ | |||
smpl_t aubio_hztomel_htk (smpl_t freq); | |||
/** convert mel to frequency (Hz) | |||
\param mel input mel | |||
\return output frequency, in Hz | |||
Converts a scalar from the mel scale to the frequency domain, using the | |||
equation defined by O'Shaughnessy, as implemented in the HTK speech | |||
recognition toolkit: | |||
\f$ f = 700 * {e}^\left(\frac{f}{1127} - 1\right) \f$ | |||
See also | |||
-------- | |||
aubio_hztomel_htk(), aubio_meltohz(). | |||
*/ | |||
smpl_t aubio_meltohz_htk (smpl_t mel); | |||
/** convert frequency (Hz) to midi value (0-128) */ | |||
smpl_t aubio_freqtomidi (smpl_t freq); | |||
/** convert midi value (0-128) to frequency (Hz) */ | |||
smpl_t aubio_miditofreq (smpl_t midi); | |||
/** clean up cached memory at the end of program | |||
This function should be used at the end of programs to purge all cached | |||
memory. So far it is only useful to clean FFTW's cache. | |||
*/ | |||
void aubio_cleanup (void); | |||
/** zero-crossing rate (ZCR) | |||
The zero-crossing rate is the number of times a signal changes sign, | |||
divided by the length of this signal. | |||
\param v vector to compute ZCR from | |||
\return zero-crossing rate of v | |||
*/ | |||
smpl_t aubio_zero_crossing_rate (fvec_t * v); | |||
/** compute sound level on a linear scale | |||
This gives the average of the square amplitudes. | |||
\param v vector to compute level from | |||
\return level of v | |||
*/ | |||
smpl_t aubio_level_lin (const fvec_t * v); | |||
/** compute sound pressure level (SPL) in dB | |||
This quantity is often wrongly called 'loudness'. | |||
This gives ten times the log10 of the average of the square amplitudes. | |||
\param v vector to compute dB SPL from | |||
\return level of v in dB SPL | |||
*/ | |||
smpl_t aubio_db_spl (const fvec_t * v); | |||
/** check if buffer level in dB SPL is under a given threshold | |||
\param v vector to get level from | |||
\param threshold threshold in dB SPL | |||
\return 1 if level is under the given threshold, 0 otherwise | |||
*/ | |||
uint_t aubio_silence_detection (const fvec_t * v, smpl_t threshold); | |||
/** get buffer level if level >= threshold, 1. otherwise | |||
\param v vector to get level from | |||
\param threshold threshold in dB SPL | |||
\return level in dB SPL if level >= threshold, 1. otherwise | |||
*/ | |||
smpl_t aubio_level_detection (const fvec_t * v, smpl_t threshold); | |||
/** clamp the values of a vector within the range [-abs(max), abs(max)] | |||
\param in vector to clamp | |||
\param absmax maximum value over which input vector elements should be clamped | |||
*/ | |||
void fvec_clamp(fvec_t *in, smpl_t absmax); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_MUSICUTILS_H */ |
@@ -0,0 +1,530 @@ | |||
/* | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "cvec.h" | |||
#include "lvec.h" | |||
#include "mathutils.h" | |||
#include "musicutils.h" | |||
#include "spectral/phasevoc.h" | |||
#include "temporal/filter.h" | |||
#include "temporal/c_weighting.h" | |||
#include "pitch/pitchmcomb.h" | |||
#include "pitch/pitchyin.h" | |||
#include "pitch/pitchfcomb.h" | |||
#include "pitch/pitchschmitt.h" | |||
#include "pitch/pitchyinfft.h" | |||
#include "pitch/pitchyinfast.h" | |||
#include "pitch/pitchspecacf.h" | |||
#include "pitch/pitch.h" | |||
#define DEFAULT_PITCH_SILENCE -50. | |||
/** pitch detection algorithms */ | |||
typedef enum | |||
{ | |||
aubio_pitcht_yin, /**< `yin`, YIN algorithm */ | |||
aubio_pitcht_mcomb, /**< `mcomb`, Multi-comb filter */ | |||
aubio_pitcht_schmitt, /**< `schmitt`, Schmitt trigger */ | |||
aubio_pitcht_fcomb, /**< `fcomb`, Fast comb filter */ | |||
aubio_pitcht_yinfft, /**< `yinfft`, Spectral YIN */ | |||
aubio_pitcht_yinfast, /**< `yinfast`, YIN fast */ | |||
aubio_pitcht_specacf, /**< `specacf`, Spectral autocorrelation */ | |||
aubio_pitcht_default | |||
= aubio_pitcht_yinfft, /**< `default` */ | |||
} aubio_pitch_type; | |||
/** pitch detection output modes */ | |||
typedef enum | |||
{ | |||
aubio_pitchm_freq, /**< Frequency (Hz) */ | |||
aubio_pitchm_midi, /**< MIDI note (0.,127) */ | |||
aubio_pitchm_cent, /**< Cent */ | |||
aubio_pitchm_bin, /**< Frequency bin (0,bufsize) */ | |||
aubio_pitchm_default = aubio_pitchm_freq, /**< the one used when "default" is asked */ | |||
} aubio_pitch_mode; | |||
/** callback to get pitch candidate, defined below */ | |||
typedef void (*aubio_pitch_detect_t) (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
/** callback to convert pitch from one unit to another, defined below */ | |||
typedef smpl_t(*aubio_pitch_convert_t) (smpl_t value, uint_t samplerate, uint_t bufsize); | |||
/** callback to fetch the confidence of the algorithm */ | |||
typedef smpl_t (*aubio_pitch_get_conf_t) (void * p); | |||
/** generic pitch detection structure */ | |||
struct _aubio_pitch_t | |||
{ | |||
aubio_pitch_type type; /**< pitch detection mode */ | |||
aubio_pitch_mode mode; /**< pitch detection output mode */ | |||
uint_t samplerate; /**< samplerate */ | |||
uint_t bufsize; /**< buffer size */ | |||
void *p_object; /**< pointer to pitch object */ | |||
aubio_filter_t *filter; /**< filter */ | |||
fvec_t *filtered; /**< filtered input */ | |||
aubio_pvoc_t *pv; /**< phase vocoder for mcomb */ | |||
cvec_t *fftgrain; /**< spectral frame for mcomb */ | |||
fvec_t *buf; /**< temporary buffer for yin */ | |||
aubio_pitch_detect_t detect_cb; /**< callback to get the pitch candidates */ | |||
aubio_pitch_convert_t conv_cb; /**< callback to convert it to the desired unit */ | |||
aubio_pitch_get_conf_t conf_cb; /**< pointer to the current confidence callback */ | |||
smpl_t silence; /**< silence threshold */ | |||
}; | |||
/* callback functions for pitch detection */ | |||
static void aubio_pitch_do_mcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
static void aubio_pitch_do_yin (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
static void aubio_pitch_do_schmitt (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
static void aubio_pitch_do_fcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
static void aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
static void aubio_pitch_do_yinfast (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
static void aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf); | |||
/* internal functions for frequency conversion */ | |||
static smpl_t freqconvbin (smpl_t f, uint_t samplerate, uint_t bufsize); | |||
static smpl_t freqconvmidi (smpl_t f, uint_t samplerate, uint_t bufsize); | |||
static smpl_t freqconvpass (smpl_t f, uint_t samplerate, uint_t bufsize); | |||
/* adapter to stack ibuf new samples at the end of buf, and trim `buf` to `bufsize` */ | |||
void aubio_pitch_slideblock (aubio_pitch_t * p, const fvec_t * ibuf); | |||
aubio_pitch_t * | |||
new_aubio_pitch (const char_t * pitch_mode, | |||
uint_t bufsize, uint_t hopsize, uint_t samplerate) | |||
{ | |||
aubio_pitch_t *p = AUBIO_NEW (aubio_pitch_t); | |||
aubio_pitch_type pitch_type; | |||
if (pitch_mode == NULL) { | |||
AUBIO_ERR ("pitch: can not use ‘NULL‘ for pitch detection method\n"); | |||
goto beach; | |||
} | |||
if (strcmp (pitch_mode, "mcomb") == 0) | |||
pitch_type = aubio_pitcht_mcomb; | |||
else if (strcmp (pitch_mode, "yinfast") == 0) | |||
pitch_type = aubio_pitcht_yinfast; | |||
else if (strcmp (pitch_mode, "yinfft") == 0) | |||
pitch_type = aubio_pitcht_yinfft; | |||
else if (strcmp (pitch_mode, "yin") == 0) | |||
pitch_type = aubio_pitcht_yin; | |||
else if (strcmp (pitch_mode, "schmitt") == 0) | |||
pitch_type = aubio_pitcht_schmitt; | |||
else if (strcmp (pitch_mode, "fcomb") == 0) | |||
pitch_type = aubio_pitcht_fcomb; | |||
else if (strcmp (pitch_mode, "specacf") == 0) | |||
pitch_type = aubio_pitcht_specacf; | |||
else if (strcmp (pitch_mode, "default") == 0) | |||
pitch_type = aubio_pitcht_default; | |||
else { | |||
AUBIO_ERR ("pitch: unknown pitch detection method ‘%s’\n", pitch_mode); | |||
goto beach; | |||
} | |||
// check parameters are valid | |||
if ((sint_t)hopsize < 1) { | |||
AUBIO_ERR("pitch: got hopsize %d, but can not be < 1\n", hopsize); | |||
goto beach; | |||
} else if ((sint_t)bufsize < 1) { | |||
AUBIO_ERR("pitch: got buffer_size %d, but can not be < 1\n", bufsize); | |||
goto beach; | |||
} else if (bufsize < hopsize) { | |||
AUBIO_ERR("pitch: hop size (%d) is larger than win size (%d)\n", hopsize, bufsize); | |||
goto beach; | |||
} else if ((sint_t)samplerate < 1) { | |||
AUBIO_ERR("pitch: samplerate (%d) can not be < 1\n", samplerate); | |||
goto beach; | |||
} | |||
p->samplerate = samplerate; | |||
p->type = pitch_type; | |||
aubio_pitch_set_unit (p, "default"); | |||
p->bufsize = bufsize; | |||
p->silence = DEFAULT_PITCH_SILENCE; | |||
p->conf_cb = NULL; | |||
switch (p->type) { | |||
case aubio_pitcht_yin: | |||
p->buf = new_fvec (bufsize); | |||
p->p_object = new_aubio_pitchyin (bufsize); | |||
if (!p->p_object) goto beach; | |||
p->detect_cb = aubio_pitch_do_yin; | |||
p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyin_get_confidence; | |||
aubio_pitchyin_set_tolerance (p->p_object, 0.15); | |||
break; | |||
case aubio_pitcht_mcomb: | |||
p->filtered = new_fvec (hopsize); | |||
p->pv = new_aubio_pvoc (bufsize, hopsize); | |||
if (!p->pv) goto beach; | |||
p->fftgrain = new_cvec (bufsize); | |||
p->p_object = new_aubio_pitchmcomb (bufsize, hopsize); | |||
p->filter = new_aubio_filter_c_weighting (samplerate); | |||
p->detect_cb = aubio_pitch_do_mcomb; | |||
break; | |||
case aubio_pitcht_fcomb: | |||
p->buf = new_fvec (bufsize); | |||
p->p_object = new_aubio_pitchfcomb (bufsize, hopsize); | |||
if (!p->p_object) goto beach; | |||
p->detect_cb = aubio_pitch_do_fcomb; | |||
break; | |||
case aubio_pitcht_schmitt: | |||
p->buf = new_fvec (bufsize); | |||
p->p_object = new_aubio_pitchschmitt (bufsize); | |||
p->detect_cb = aubio_pitch_do_schmitt; | |||
break; | |||
case aubio_pitcht_yinfft: | |||
p->buf = new_fvec (bufsize); | |||
p->p_object = new_aubio_pitchyinfft (samplerate, bufsize); | |||
if (!p->p_object) goto beach; | |||
p->detect_cb = aubio_pitch_do_yinfft; | |||
p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyinfft_get_confidence; | |||
aubio_pitchyinfft_set_tolerance (p->p_object, 0.85); | |||
break; | |||
case aubio_pitcht_yinfast: | |||
p->buf = new_fvec (bufsize); | |||
p->p_object = new_aubio_pitchyinfast (bufsize); | |||
if (!p->p_object) goto beach; | |||
p->detect_cb = aubio_pitch_do_yinfast; | |||
p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyinfast_get_confidence; | |||
aubio_pitchyinfast_set_tolerance (p->p_object, 0.15); | |||
break; | |||
case aubio_pitcht_specacf: | |||
p->buf = new_fvec (bufsize); | |||
p->p_object = new_aubio_pitchspecacf (bufsize); | |||
if (!p->p_object) goto beach; | |||
p->detect_cb = aubio_pitch_do_specacf; | |||
p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchspecacf_get_tolerance; | |||
aubio_pitchspecacf_set_tolerance (p->p_object, 0.85); | |||
break; | |||
default: | |||
break; | |||
} | |||
return p; | |||
beach: | |||
if (p->filtered) del_fvec(p->filtered); | |||
if (p->buf) del_fvec(p->buf); | |||
AUBIO_FREE(p); | |||
return NULL; | |||
} | |||
void | |||
del_aubio_pitch (aubio_pitch_t * p) | |||
{ | |||
switch (p->type) { | |||
case aubio_pitcht_yin: | |||
del_fvec (p->buf); | |||
del_aubio_pitchyin (p->p_object); | |||
break; | |||
case aubio_pitcht_mcomb: | |||
del_fvec (p->filtered); | |||
del_aubio_pvoc (p->pv); | |||
del_cvec (p->fftgrain); | |||
del_aubio_filter (p->filter); | |||
del_aubio_pitchmcomb (p->p_object); | |||
break; | |||
case aubio_pitcht_schmitt: | |||
del_fvec (p->buf); | |||
del_aubio_pitchschmitt (p->p_object); | |||
break; | |||
case aubio_pitcht_fcomb: | |||
del_fvec (p->buf); | |||
del_aubio_pitchfcomb (p->p_object); | |||
break; | |||
case aubio_pitcht_yinfft: | |||
del_fvec (p->buf); | |||
del_aubio_pitchyinfft (p->p_object); | |||
break; | |||
case aubio_pitcht_yinfast: | |||
del_fvec (p->buf); | |||
del_aubio_pitchyinfast (p->p_object); | |||
break; | |||
case aubio_pitcht_specacf: | |||
del_fvec (p->buf); | |||
del_aubio_pitchspecacf (p->p_object); | |||
break; | |||
default: | |||
break; | |||
} | |||
AUBIO_FREE (p); | |||
} | |||
void | |||
aubio_pitch_slideblock (aubio_pitch_t * p, const fvec_t * ibuf) | |||
{ | |||
uint_t overlap_size = p->buf->length - ibuf->length; | |||
#if 1 //!HAVE_MEMCPY_HACKS | |||
uint_t j; | |||
for (j = 0; j < overlap_size; j++) { | |||
p->buf->data[j] = p->buf->data[j + ibuf->length]; | |||
} | |||
for (j = 0; j < ibuf->length; j++) { | |||
p->buf->data[j + overlap_size] = ibuf->data[j]; | |||
} | |||
#else | |||
smpl_t *data = p->buf->data; | |||
smpl_t *newdata = ibuf->data; | |||
memmove(data, data + ibuf->length, overlap_size); | |||
memcpy(data + overlap_size, newdata, ibuf->length); | |||
#endif | |||
} | |||
uint_t | |||
aubio_pitch_set_unit (aubio_pitch_t * p, const char_t * pitch_unit) | |||
{ | |||
uint_t err = AUBIO_OK; | |||
aubio_pitch_mode pitch_mode; | |||
if (strcmp (pitch_unit, "freq") == 0) | |||
pitch_mode = aubio_pitchm_freq; | |||
else if (strcmp (pitch_unit, "hertz") == 0) | |||
pitch_mode = aubio_pitchm_freq; | |||
else if (strcmp (pitch_unit, "Hertz") == 0) | |||
pitch_mode = aubio_pitchm_freq; | |||
else if (strcmp (pitch_unit, "Hz") == 0) | |||
pitch_mode = aubio_pitchm_freq; | |||
else if (strcmp (pitch_unit, "f0") == 0) | |||
pitch_mode = aubio_pitchm_freq; | |||
else if (strcmp (pitch_unit, "midi") == 0) | |||
pitch_mode = aubio_pitchm_midi; | |||
else if (strcmp (pitch_unit, "cent") == 0) | |||
pitch_mode = aubio_pitchm_cent; | |||
else if (strcmp (pitch_unit, "bin") == 0) | |||
pitch_mode = aubio_pitchm_bin; | |||
else if (strcmp (pitch_unit, "default") == 0) | |||
pitch_mode = aubio_pitchm_default; | |||
else { | |||
AUBIO_WRN("pitch: unknown pitch detection unit ‘%s’, using default\n", | |||
pitch_unit); | |||
pitch_mode = aubio_pitchm_default; | |||
err = AUBIO_FAIL; | |||
} | |||
p->mode = pitch_mode; | |||
switch (p->mode) { | |||
case aubio_pitchm_freq: | |||
p->conv_cb = freqconvpass; | |||
break; | |||
case aubio_pitchm_midi: | |||
p->conv_cb = freqconvmidi; | |||
break; | |||
case aubio_pitchm_cent: | |||
/* bug: not implemented */ | |||
p->conv_cb = freqconvmidi; | |||
break; | |||
case aubio_pitchm_bin: | |||
p->conv_cb = freqconvbin; | |||
break; | |||
default: | |||
break; | |||
} | |||
return err; | |||
} | |||
uint_t | |||
aubio_pitch_set_tolerance (aubio_pitch_t * p, smpl_t tol) | |||
{ | |||
switch (p->type) { | |||
case aubio_pitcht_yin: | |||
aubio_pitchyin_set_tolerance (p->p_object, tol); | |||
break; | |||
case aubio_pitcht_yinfft: | |||
aubio_pitchyinfft_set_tolerance (p->p_object, tol); | |||
break; | |||
case aubio_pitcht_yinfast: | |||
aubio_pitchyinfast_set_tolerance (p->p_object, tol); | |||
break; | |||
default: | |||
break; | |||
} | |||
return AUBIO_OK; | |||
} | |||
smpl_t | |||
aubio_pitch_get_tolerance (aubio_pitch_t * p) | |||
{ | |||
smpl_t tolerance = 1.; | |||
switch (p->type) { | |||
case aubio_pitcht_yin: | |||
tolerance = aubio_pitchyin_get_tolerance (p->p_object); | |||
break; | |||
case aubio_pitcht_yinfft: | |||
tolerance = aubio_pitchyinfft_get_tolerance (p->p_object); | |||
break; | |||
case aubio_pitcht_yinfast: | |||
tolerance = aubio_pitchyinfast_get_tolerance (p->p_object); | |||
break; | |||
default: | |||
break; | |||
} | |||
return tolerance; | |||
} | |||
uint_t | |||
aubio_pitch_set_silence (aubio_pitch_t * p, smpl_t silence) | |||
{ | |||
if (silence <= 0 && silence >= -200) { | |||
p->silence = silence; | |||
return AUBIO_OK; | |||
} else { | |||
AUBIO_WRN("pitch: could not set silence to %.2f\n", silence); | |||
return AUBIO_FAIL; | |||
} | |||
} | |||
smpl_t | |||
aubio_pitch_get_silence (aubio_pitch_t * p) | |||
{ | |||
return p->silence; | |||
} | |||
/* do method, calling the detection callback, then the conversion callback */ | |||
void | |||
aubio_pitch_do (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf) | |||
{ | |||
p->detect_cb (p, ibuf, obuf); | |||
if (aubio_silence_detection(ibuf, p->silence) == 1) { | |||
obuf->data[0] = 0.; | |||
} | |||
obuf->data[0] = p->conv_cb (obuf->data[0], p->samplerate, p->bufsize); | |||
} | |||
/* do method for each algorithm */ | |||
void | |||
aubio_pitch_do_mcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf) | |||
{ | |||
aubio_filter_do_outplace (p->filter, ibuf, p->filtered); | |||
aubio_pvoc_do (p->pv, ibuf, p->fftgrain); | |||
aubio_pitchmcomb_do (p->p_object, p->fftgrain, obuf); | |||
obuf->data[0] = aubio_bintofreq (obuf->data[0], p->samplerate, p->bufsize); | |||
} | |||
void | |||
aubio_pitch_do_yin (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf) | |||
{ | |||
smpl_t pitch = 0.; | |||
aubio_pitch_slideblock (p, ibuf); | |||
aubio_pitchyin_do (p->p_object, p->buf, obuf); | |||
pitch = obuf->data[0]; | |||
if (pitch > 0) { | |||
pitch = p->samplerate / (pitch + 0.); | |||
} else { | |||
pitch = 0.; | |||
} | |||
obuf->data[0] = pitch; | |||
} | |||
void | |||
aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf) | |||
{ | |||
smpl_t pitch = 0.; | |||
aubio_pitch_slideblock (p, ibuf); | |||
aubio_pitchyinfft_do (p->p_object, p->buf, obuf); | |||
pitch = obuf->data[0]; | |||
if (pitch > 0) { | |||
pitch = p->samplerate / (pitch + 0.); | |||
} else { | |||
pitch = 0.; | |||
} | |||
obuf->data[0] = pitch; | |||
} | |||
void | |||
aubio_pitch_do_yinfast (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf) | |||
{ | |||
smpl_t pitch = 0.; | |||
aubio_pitch_slideblock (p, ibuf); | |||
aubio_pitchyinfast_do (p->p_object, p->buf, obuf); | |||
pitch = obuf->data[0]; | |||
if (pitch > 0) { | |||
pitch = p->samplerate / (pitch + 0.); | |||
} else { | |||
pitch = 0.; | |||
} | |||
obuf->data[0] = pitch; | |||
} | |||
void | |||
aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out) | |||
{ | |||
smpl_t pitch = 0., period; | |||
aubio_pitch_slideblock (p, ibuf); | |||
aubio_pitchspecacf_do (p->p_object, p->buf, out); | |||
//out->data[0] = aubio_bintofreq (out->data[0], p->samplerate, p->bufsize); | |||
period = out->data[0]; | |||
if (period > 0) { | |||
pitch = p->samplerate / period; | |||
} else { | |||
pitch = 0.; | |||
} | |||
out->data[0] = pitch; | |||
} | |||
void | |||
aubio_pitch_do_fcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out) | |||
{ | |||
aubio_pitch_slideblock (p, ibuf); | |||
aubio_pitchfcomb_do (p->p_object, p->buf, out); | |||
out->data[0] = aubio_bintofreq (out->data[0], p->samplerate, p->bufsize); | |||
} | |||
void | |||
aubio_pitch_do_schmitt (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out) | |||
{ | |||
smpl_t period, pitch = 0.; | |||
aubio_pitch_slideblock (p, ibuf); | |||
aubio_pitchschmitt_do (p->p_object, p->buf, out); | |||
period = out->data[0]; | |||
if (period > 0) { | |||
pitch = p->samplerate / period; | |||
} else { | |||
pitch = 0.; | |||
} | |||
out->data[0] = pitch; | |||
} | |||
/* conversion callbacks */ | |||
smpl_t | |||
freqconvbin(smpl_t f, uint_t samplerate, uint_t bufsize) | |||
{ | |||
return aubio_freqtobin(f, samplerate, bufsize); | |||
} | |||
smpl_t | |||
freqconvmidi (smpl_t f, uint_t samplerate UNUSED, uint_t bufsize UNUSED) | |||
{ | |||
return aubio_freqtomidi (f); | |||
} | |||
smpl_t | |||
freqconvpass (smpl_t f, uint_t samplerate UNUSED, uint_t bufsize UNUSED) | |||
{ | |||
return f; | |||
} | |||
/* confidence callbacks */ | |||
smpl_t | |||
aubio_pitch_get_confidence (aubio_pitch_t * p) | |||
{ | |||
if (p->conf_cb) { | |||
return p->conf_cb(p->p_object); | |||
} | |||
return 0.; | |||
} |
@@ -0,0 +1,197 @@ | |||
/* | |||
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef AUBIO_PITCH_H | |||
#define AUBIO_PITCH_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** \file | |||
Pitch detection object | |||
This file creates the objects required for the computation of the selected | |||
pitch detection algorithm and output the results, in midi note or Hz. | |||
\section pitch Pitch detection methods | |||
A list of the pitch detection methods currently available follows. | |||
\b \p default : use the default method | |||
Currently, the default method is set to \p yinfft . | |||
\b \p schmitt : Schmitt trigger | |||
This pitch extraction method implements a Schmitt trigger to estimate the | |||
period of a signal. | |||
This file was derived from the tuneit project, written by Mario Lang to | |||
detect the fundamental frequency of a sound. | |||
See http://delysid.org/tuneit.html | |||
\b \p fcomb : a fast harmonic comb filter | |||
This pitch extraction method implements a fast harmonic comb filter to | |||
determine the fundamental frequency of a harmonic sound. | |||
This file was derived from the tuneit project, written by Mario Lang to | |||
detect the fundamental frequency of a sound. | |||
See http://delysid.org/tuneit.html | |||
\b \p mcomb : multiple-comb filter | |||
This fundamental frequency estimation algorithm implements spectral | |||
flattening, multi-comb filtering and peak histogramming. | |||
This method was designed by Juan P. Bello and described in: | |||
Juan-Pablo Bello. ``Towards the Automated Analysis of Simple Polyphonic | |||
Music''. PhD thesis, Centre for Digital Music, Queen Mary University of | |||
London, London, UK, 2003. | |||
\b \p yin : YIN algorithm | |||
This algorithm was developed by A. de Cheveigne and H. Kawahara and | |||
published in: | |||
De Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency | |||
estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930. | |||
see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html | |||
\b \p yinfast : Yinfast algorithm | |||
This algorithm is equivalent to the YIN algorithm, but computed in the | |||
spectral domain for efficiency. See also `python/demos/demo_yin_compare.py`. | |||
\b \p yinfft : Yinfft algorithm | |||
This algorithm was derived from the YIN algorithm. In this implementation, a | |||
Fourier transform is used to compute a tapered square difference function, | |||
which allows spectral weighting. Because the difference function is tapered, | |||
the selection of the period is simplified. | |||
Paul Brossier, [Automatic annotation of musical audio for interactive | |||
systems](http://aubio.org/phd/), Chapter 3, Pitch Analysis, PhD thesis, | |||
Centre for Digital music, Queen Mary University of London, London, UK, 2006. | |||
\example pitch/test-pitch.c | |||
\example examples/aubiopitch.c | |||
*/ | |||
/** pitch detection object */ | |||
typedef struct _aubio_pitch_t aubio_pitch_t; | |||
/** execute pitch detection on an input signal frame | |||
\param o pitch detection object as returned by new_aubio_pitch() | |||
\param in input signal of size [hop_size] | |||
\param out output pitch candidates of size [1] | |||
*/ | |||
void aubio_pitch_do (aubio_pitch_t * o, const fvec_t * in, fvec_t * out); | |||
/** change yin or yinfft tolerance threshold | |||
\param o pitch detection object as returned by new_aubio_pitch() | |||
\param tol tolerance default is 0.15 for yin and 0.85 for yinfft | |||
*/ | |||
uint_t aubio_pitch_set_tolerance (aubio_pitch_t * o, smpl_t tol); | |||
/** get yin or yinfft tolerance threshold | |||
\param o pitch detection object as returned by new_aubio_pitch() | |||
\return tolerance (default is 0.15 for yin and 0.85 for yinfft) | |||
*/ | |||
smpl_t aubio_pitch_get_tolerance (aubio_pitch_t * o); | |||
/** deletion of the pitch detection object | |||
\param o pitch detection object as returned by new_aubio_pitch() | |||
*/ | |||
void del_aubio_pitch (aubio_pitch_t * o); | |||
/** creation of the pitch detection object | |||
\param method set pitch detection algorithm | |||
\param buf_size size of the input buffer to analyse | |||
\param hop_size step size between two consecutive analysis instant | |||
\param samplerate sampling rate of the signal | |||
\return newly created ::aubio_pitch_t | |||
*/ | |||
aubio_pitch_t *new_aubio_pitch (const char_t * method, | |||
uint_t buf_size, uint_t hop_size, uint_t samplerate); | |||
/** set the output unit of the pitch detection object | |||
\param o pitch detection object as returned by new_aubio_pitch() | |||
\param mode set pitch units for output | |||
mode can be one of "Hz", "midi", "cent", or "bin". Defaults to "Hz". | |||
\return 0 if successfull, non-zero otherwise | |||
*/ | |||
uint_t aubio_pitch_set_unit (aubio_pitch_t * o, const char_t * mode); | |||
/** set the silence threshold of the pitch detection object | |||
\param o pitch detection object as returned by new_aubio_pitch() | |||
\param silence level threshold under which pitch should be ignored, in dB | |||
\return 0 if successfull, non-zero otherwise | |||
*/ | |||
uint_t aubio_pitch_set_silence (aubio_pitch_t * o, smpl_t silence); | |||
/** set the silence threshold of the pitch detection object | |||
\param o pitch detection object as returned by ::new_aubio_pitch() | |||
\return level threshold under which pitch should be ignored, in dB | |||
*/ | |||
smpl_t aubio_pitch_get_silence (aubio_pitch_t * o); | |||
/** get the current confidence | |||
\param o pitch detection object as returned by new_aubio_pitch() | |||
\return the current confidence of the pitch algorithm | |||
*/ | |||
smpl_t aubio_pitch_get_confidence (aubio_pitch_t * o); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_PITCH_H */ |
@@ -0,0 +1,144 @@ | |||
/* | |||
Copyright (C) 2004, 2005 Mario Lang <mlang@delysid.org> | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "cvec.h" | |||
#include "mathutils.h" | |||
#include "musicutils.h" | |||
#include "spectral/fft.h" | |||
#include "pitch/pitchfcomb.h" | |||
#define MAX_PEAKS 8 | |||
typedef struct | |||
{ | |||
smpl_t bin; | |||
smpl_t db; | |||
} aubio_fpeak_t; | |||
struct _aubio_pitchfcomb_t | |||
{ | |||
uint_t fftSize; | |||
uint_t stepSize; | |||
uint_t rate; | |||
fvec_t *winput; | |||
fvec_t *win; | |||
cvec_t *fftOut; | |||
fvec_t *fftLastPhase; | |||
aubio_fft_t *fft; | |||
}; | |||
aubio_pitchfcomb_t * | |||
new_aubio_pitchfcomb (uint_t bufsize, uint_t hopsize) | |||
{ | |||
aubio_pitchfcomb_t *p = AUBIO_NEW (aubio_pitchfcomb_t); | |||
p->fftSize = bufsize; | |||
p->stepSize = hopsize; | |||
p->fft = new_aubio_fft (bufsize); | |||
if (!p->fft) goto beach; | |||
p->winput = new_fvec (bufsize); | |||
p->fftOut = new_cvec (bufsize); | |||
p->fftLastPhase = new_fvec (bufsize); | |||
p->win = new_aubio_window ("hanning", bufsize); | |||
return p; | |||
beach: | |||
AUBIO_FREE(p); | |||
return NULL; | |||
} | |||
/* input must be stepsize long */ | |||
void | |||
aubio_pitchfcomb_do (aubio_pitchfcomb_t * p, const fvec_t * input, fvec_t * output) | |||
{ | |||
uint_t k, l, maxharm = 0; | |||
smpl_t phaseDifference = TWO_PI * (smpl_t) p->stepSize / (smpl_t) p->fftSize; | |||
aubio_fpeak_t peaks[MAX_PEAKS]; | |||
for (k = 0; k < MAX_PEAKS; k++) { | |||
peaks[k].db = -200.; | |||
peaks[k].bin = 0.; | |||
} | |||
for (k = 0; k < input->length; k++) { | |||
p->winput->data[k] = p->win->data[k] * input->data[k]; | |||
} | |||
aubio_fft_do (p->fft, p->winput, p->fftOut); | |||
for (k = 0; k <= p->fftSize / 2; k++) { | |||
smpl_t | |||
magnitude = | |||
20. * LOG10 (2. * p->fftOut->norm[k] / (smpl_t) p->fftSize), | |||
phase = p->fftOut->phas[k], tmp, bin; | |||
/* compute phase difference */ | |||
tmp = phase - p->fftLastPhase->data[k]; | |||
p->fftLastPhase->data[k] = phase; | |||
/* subtract expected phase difference */ | |||
tmp -= (smpl_t) k *phaseDifference; | |||
/* map delta phase into +/- Pi interval */ | |||
tmp = aubio_unwrap2pi (tmp); | |||
/* get deviation from bin frequency from the +/- Pi interval */ | |||
tmp = p->fftSize / (smpl_t) p->stepSize * tmp / (TWO_PI); | |||
/* compute the k-th partials' true bin */ | |||
bin = (smpl_t) k + tmp; | |||
if (bin > 0.0 && magnitude > peaks[0].db) { // && magnitude < 0) { | |||
memmove (peaks + 1, peaks, sizeof (aubio_fpeak_t) * (MAX_PEAKS - 1)); | |||
peaks[0].bin = bin; | |||
peaks[0].db = magnitude; | |||
} | |||
} | |||
k = 0; | |||
for (l = 1; l < MAX_PEAKS && peaks[l].bin > 0.0; l++) { | |||
sint_t harmonic; | |||
for (harmonic = 5; harmonic > 1; harmonic--) { | |||
if (peaks[0].bin / peaks[l].bin < harmonic + .02 && | |||
peaks[0].bin / peaks[l].bin > harmonic - .02) { | |||
if (harmonic > (sint_t) maxharm && peaks[0].db < peaks[l].db / 2) { | |||
maxharm = harmonic; | |||
k = l; | |||
} | |||
} | |||
} | |||
} | |||
output->data[0] = peaks[k].bin; | |||
/* quick hack to clean output a bit */ | |||
if (peaks[k].bin > 5000.) | |||
output->data[0] = 0.; | |||
} | |||
void | |||
del_aubio_pitchfcomb (aubio_pitchfcomb_t * p) | |||
{ | |||
del_cvec (p->fftOut); | |||
del_fvec (p->fftLastPhase); | |||
del_fvec (p->win); | |||
del_fvec (p->winput); | |||
del_aubio_fft (p->fft); | |||
AUBIO_FREE (p); | |||
} |
@@ -0,0 +1,76 @@ | |||
/* | |||
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** \file | |||
Pitch detection using a fast harmonic comb filter | |||
This pitch extraction method implements a fast harmonic comb filter to | |||
determine the fundamental frequency of a harmonic sound. | |||
This file was derived from the tuneit project, written by Mario Lang to | |||
detect the fundamental frequency of a sound. | |||
See http://delysid.org/tuneit.html | |||
\example pitch/test-pitchfcomb.c | |||
*/ | |||
#ifndef AUBIO_PITCHFCOMB_H | |||
#define AUBIO_PITCHFCOMB_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** pitch detection object */ | |||
typedef struct _aubio_pitchfcomb_t aubio_pitchfcomb_t; | |||
/** execute pitch detection on an input buffer | |||
\param p pitch detection object as returned by new_aubio_pitchfcomb | |||
\param input input signal window (length as specified at creation time) | |||
\param output pitch candidates in bins | |||
*/ | |||
void aubio_pitchfcomb_do (aubio_pitchfcomb_t * p, const fvec_t * input, | |||
fvec_t * output); | |||
/** creation of the pitch detection object | |||
\param buf_size size of the input buffer to analyse | |||
\param hop_size step size between two consecutive analysis instant | |||
*/ | |||
aubio_pitchfcomb_t *new_aubio_pitchfcomb (uint_t buf_size, uint_t hop_size); | |||
/** deletion of the pitch detection object | |||
\param p pitch detection object as returned by new_aubio_pitchfcomb | |||
*/ | |||
void del_aubio_pitchfcomb (aubio_pitchfcomb_t * p); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_PITCHFCOMB_H */ |
@@ -0,0 +1,435 @@ | |||
/* | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "cvec.h" | |||
#include "mathutils.h" | |||
#include "pitch/pitchmcomb.h" | |||
#define CAND_SWAP(a,b) { register aubio_spectralcandidate_t *t=(a);(a)=(b);(b)=t; } | |||
typedef struct _aubio_spectralpeak_t aubio_spectralpeak_t; | |||
typedef struct _aubio_spectralcandidate_t aubio_spectralcandidate_t; | |||
uint_t aubio_pitchmcomb_get_root_peak (aubio_spectralpeak_t * peaks, | |||
uint_t length); | |||
uint_t aubio_pitchmcomb_quadpick (aubio_spectralpeak_t * spectral_peaks, | |||
const fvec_t * X); | |||
void aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, const fvec_t * oldmag); | |||
void aubio_pitchmcomb_combdet (aubio_pitchmcomb_t * p, const fvec_t * newmag); | |||
/* not used but useful : sort by amplitudes (or anything else) | |||
* sort_pitchpeak(peaks, length); | |||
*/ | |||
#if 0 | |||
/** spectral_peak comparison function (must return signed int) */ | |||
static sint_t aubio_pitchmcomb_sort_peak_comp (const void *x, const void *y); | |||
/** sort spectral_peak against their mag */ | |||
void aubio_pitchmcomb_sort_peak (aubio_spectralpeak_t * peaks, uint_t nbins); | |||
/** select the best candidates */ | |||
uint_t aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, | |||
smpl_t * cands); | |||
#endif | |||
/** sort spectral_candidate against their comb ene */ | |||
void aubio_pitchmcomb_sort_cand_ene (aubio_spectralcandidate_t ** candidates, | |||
uint_t nbins); | |||
#if 0 | |||
/** sort spectral_candidate against their frequency */ | |||
void aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates, | |||
uint_t nbins); | |||
#endif | |||
struct _aubio_pitchmcomb_t | |||
{ | |||
smpl_t threshold; /**< offset threshold [0.033 or 0.01] */ | |||
smpl_t alpha; /**< normalisation exponent [9] */ | |||
smpl_t cutoff; /**< low-pass filter cutoff [0.34, 1] */ | |||
smpl_t tol; /**< tolerance [0.05] */ | |||
// smpl_t tau; /**< frequency precision [44100/4096] */ | |||
uint_t win_post; /**< median filter window length */ | |||
uint_t win_pre; /**< median filter window */ | |||
uint_t ncand; /**< maximum number of candidates (combs) */ | |||
uint_t npartials; /**< maximum number of partials per combs */ | |||
uint_t count; /**< picked picks */ | |||
uint_t goodcandidate; /**< best candidate */ | |||
uint_t spec_partition; /**< spectrum partition to consider */ | |||
aubio_spectralpeak_t *peaks; /**< up to length win/spec_partition */ | |||
aubio_spectralcandidate_t **candidates; /** up to five candidates */ | |||
/* some scratch pads */ | |||
/** \bug (unnecessary copied from fftgrain?) */ | |||
fvec_t *newmag; /**< vec to store mag */ | |||
fvec_t *scratch; /**< vec to store modified mag */ | |||
fvec_t *scratch2; /**< vec to compute moving median */ | |||
fvec_t *theta; /**< vec to store phase */ | |||
smpl_t phasediff; | |||
smpl_t phasefreq; | |||
/** threshfn: name or handle of fn for computing adaptive threshold [median] */ | |||
/** aubio_thresholdfn_t thresholdfn; */ | |||
/** picker: name or handle of fn for picking event times [quadpick] */ | |||
/** aubio_pickerfn_t pickerfn; */ | |||
}; | |||
/** spectral peak object */ | |||
struct _aubio_spectralpeak_t | |||
{ | |||
uint_t bin; /**< bin [0-(length-1)] */ | |||
smpl_t ebin; /**< estimated bin */ | |||
smpl_t mag; /**< peak magnitude */ | |||
}; | |||
/** spectral candidates array object */ | |||
struct _aubio_spectralcandidate_t | |||
{ | |||
smpl_t ebin; /**< interpolated bin */ | |||
smpl_t *ecomb; /**< comb */ | |||
smpl_t ene; /**< candidate energy */ | |||
smpl_t len; /**< length */ | |||
}; | |||
void | |||
aubio_pitchmcomb_do (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, fvec_t * output) | |||
{ | |||
uint_t j; | |||
smpl_t instfreq; | |||
fvec_t *newmag = (fvec_t *) p->newmag; | |||
//smpl_t hfc; //fe=instfreq(theta1,theta,ops); //theta1=theta; | |||
/* copy incoming grain to newmag */ | |||
for (j = 0; j < newmag->length; j++) | |||
newmag->data[j] = fftgrain->norm[j]; | |||
/* detect only if local energy > 10. */ | |||
//if (aubio_level_lin (newmag) * newmag->length > 10.) { | |||
//hfc = fvec_local_hfc(newmag); //not used | |||
aubio_pitchmcomb_spectral_pp (p, newmag); | |||
aubio_pitchmcomb_combdet (p, newmag); | |||
//aubio_pitchmcomb_sort_cand_freq(p->candidates,p->ncand); | |||
//return p->candidates[p->goodcandidate]->ebin; | |||
j = (uint_t) FLOOR (p->candidates[p->goodcandidate]->ebin + .5); | |||
instfreq = aubio_unwrap2pi (fftgrain->phas[j] | |||
- p->theta->data[j] - j * p->phasediff); | |||
instfreq *= p->phasefreq; | |||
/* store phase for next run */ | |||
for (j = 0; j < p->theta->length; j++) { | |||
p->theta->data[j] = fftgrain->phas[j]; | |||
} | |||
//return p->candidates[p->goodcandidate]->ebin; | |||
output->data[0] = | |||
FLOOR (p->candidates[p->goodcandidate]->ebin + .5) + instfreq; | |||
/*} else { | |||
return -1.; | |||
} */ | |||
} | |||
#if 0 | |||
uint_t | |||
aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, smpl_t * cands) | |||
{ | |||
uint_t j; | |||
uint_t k; | |||
fvec_t *newmag = (fvec_t *) p->newmag; | |||
aubio_spectralcandidate_t **scands = | |||
(aubio_spectralcandidate_t **) (p->candidates); | |||
//smpl_t hfc; //fe=instfreq(theta1,theta,ops); //theta1=theta; | |||
/* copy incoming grain to newmag */ | |||
for (j = 0; j < newmag->length; j++) | |||
newmag->data[j] = fftgrain->norm[j]; | |||
/* detect only if local energy > 10. */ | |||
if (aubio_level_lin (newmag) * newmag->length > 10.) { | |||
/* hfc = fvec_local_hfc(newmag); do not use */ | |||
aubio_pitchmcomb_spectral_pp (p, newmag); | |||
aubio_pitchmcomb_combdet (p, newmag); | |||
aubio_pitchmcomb_sort_cand_freq (scands, p->ncand); | |||
/* store ncand comb energies in cands[1:ncand] */ | |||
for (k = 0; k < p->ncand; k++) | |||
cands[k] = p->candidates[k]->ene; | |||
/* store ncand[end] freq in cands[end] */ | |||
cands[p->ncand] = p->candidates[p->ncand - 1]->ebin; | |||
return 1; | |||
} else { | |||
for (k = 0; k < p->ncand; k++) | |||
cands[k] = 0; | |||
return 0; | |||
} | |||
} | |||
#endif | |||
void | |||
aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, const fvec_t * newmag) | |||
{ | |||
fvec_t *mag = (fvec_t *) p->scratch; | |||
fvec_t *tmp = (fvec_t *) p->scratch2; | |||
uint_t j; | |||
uint_t length = mag->length; | |||
/* copy newmag to mag (scracth) */ | |||
for (j = 0; j < length; j++) { | |||
mag->data[j] = newmag->data[j]; | |||
} | |||
fvec_min_removal (mag); /* min removal */ | |||
fvec_alpha_normalise (mag, p->alpha); /* alpha normalisation */ | |||
/* skipped *//* low pass filtering */ | |||
/** \bug fvec_moving_thres may write out of bounds */ | |||
fvec_adapt_thres (mag, tmp, p->win_post, p->win_pre); /* adaptative threshold */ | |||
fvec_add (mag, -p->threshold); /* fixed threshold */ | |||
{ | |||
aubio_spectralpeak_t *peaks = (aubio_spectralpeak_t *) p->peaks; | |||
uint_t count; | |||
/* return bin and ebin */ | |||
count = aubio_pitchmcomb_quadpick (peaks, mag); | |||
for (j = 0; j < count; j++) | |||
peaks[j].mag = newmag->data[peaks[j].bin]; | |||
/* reset non peaks */ | |||
for (j = count; j < length; j++) | |||
peaks[j].mag = 0.; | |||
p->peaks = peaks; | |||
p->count = count; | |||
} | |||
} | |||
void | |||
aubio_pitchmcomb_combdet (aubio_pitchmcomb_t * p, const fvec_t * newmag) | |||
{ | |||
aubio_spectralpeak_t *peaks = (aubio_spectralpeak_t *) p->peaks; | |||
aubio_spectralcandidate_t **candidate = | |||
(aubio_spectralcandidate_t **) p->candidates; | |||
/* parms */ | |||
uint_t N = p->npartials; /* maximum number of partials to be considered 10 */ | |||
uint_t M = p->ncand; /* maximum number of combs to be considered 5 */ | |||
uint_t length = newmag->length; | |||
uint_t count = p->count; | |||
uint_t k; | |||
uint_t l; | |||
uint_t d; | |||
uint_t curlen = 0; | |||
smpl_t delta2; | |||
smpl_t xx; | |||
uint_t position = 0; | |||
uint_t root_peak = 0; | |||
uint_t tmpl = 0; | |||
smpl_t tmpene = 0.; | |||
/* get the biggest peak in the spectrum */ | |||
root_peak = aubio_pitchmcomb_get_root_peak (peaks, count); | |||
/* not enough partials in highest notes, could be forced */ | |||
//if (peaks[root_peak].ebin >= aubio_miditofreq(85.)/p->tau) N=2; | |||
//if (peaks[root_peak].ebin >= aubio_miditofreq(90.)/p->tau) N=1; | |||
/* now calculate the energy of each of the 5 combs */ | |||
for (l = 0; l < M; l++) { | |||
smpl_t scaler = (1. / (l + 1.)); | |||
candidate[l]->ene = 0.; /* reset ene and len sums */ | |||
candidate[l]->len = 0.; | |||
candidate[l]->ebin = scaler * peaks[root_peak].ebin; | |||
/* if less than N peaks available, curlen < N */ | |||
if (candidate[l]->ebin != 0.) | |||
curlen = (uint_t) FLOOR (length / (candidate[l]->ebin)); | |||
curlen = (N < curlen) ? N : curlen; | |||
/* fill candidate[l]->ecomb[k] with (k+1)*candidate[l]->ebin */ | |||
for (k = 0; k < curlen; k++) | |||
candidate[l]->ecomb[k] = (candidate[l]->ebin) * (k + 1.); | |||
for (k = curlen; k < length; k++) | |||
candidate[l]->ecomb[k] = 0.; | |||
/* for each in candidate[l]->ecomb[k] */ | |||
for (k = 0; k < curlen; k++) { | |||
xx = 100000.; | |||
/** get the candidate->ecomb the closer to peaks.ebin | |||
* (to cope with the inharmonicity)*/ | |||
for (d = 0; d < count; d++) { | |||
delta2 = ABS (candidate[l]->ecomb[k] - peaks[d].ebin); | |||
if (delta2 <= xx) { | |||
position = d; | |||
xx = delta2; | |||
} | |||
} | |||
/* for a Q factor of 17, maintaining "constant Q filtering", | |||
* and sum energy and length over non null combs */ | |||
if (17. * xx < candidate[l]->ecomb[k]) { | |||
candidate[l]->ecomb[k] = peaks[position].ebin; | |||
candidate[l]->ene += /* ecomb rounded to nearest int */ | |||
POW (newmag->data[(uint_t) FLOOR (candidate[l]->ecomb[k] + .5)], | |||
0.25); | |||
candidate[l]->len += 1. / curlen; | |||
} else | |||
candidate[l]->ecomb[k] = 0.; | |||
} | |||
/* punishment */ | |||
/*if (candidate[l]->len<0.6) | |||
candidate[l]->ene=0.; */ | |||
/* remember best candidate energy (in polyphonic, could check for | |||
* tmpene*1.1 < candidate->ene to reduce jumps towards low frequencies) */ | |||
if (tmpene < candidate[l]->ene) { | |||
tmpl = l; | |||
tmpene = candidate[l]->ene; | |||
} | |||
} | |||
//p->candidates=candidate; | |||
//p->peaks=peaks; | |||
p->goodcandidate = tmpl; | |||
} | |||
/** T=quadpick(X): return indices of elements of X which are peaks and positive | |||
* exact peak positions are retrieved by quadratic interpolation | |||
* | |||
* \bug peak-picking too picky, sometimes counts too many peaks ? | |||
*/ | |||
uint_t | |||
aubio_pitchmcomb_quadpick (aubio_spectralpeak_t * spectral_peaks, const fvec_t * X) | |||
{ | |||
uint_t j, ispeak, count = 0; | |||
for (j = 1; j < X->length - 1; j++) { | |||
ispeak = fvec_peakpick (X, j); | |||
if (ispeak) { | |||
count += ispeak; | |||
spectral_peaks[count - 1].bin = j; | |||
spectral_peaks[count - 1].ebin = fvec_quadratic_peak_pos (X, j); | |||
} | |||
} | |||
return count; | |||
} | |||
/* get predominant partial */ | |||
uint_t | |||
aubio_pitchmcomb_get_root_peak (aubio_spectralpeak_t * peaks, uint_t length) | |||
{ | |||
uint_t i, pos = 0; | |||
smpl_t tmp = 0.; | |||
for (i = 0; i < length; i++) | |||
if (tmp <= peaks[i].mag) { | |||
pos = i; | |||
tmp = peaks[i].mag; | |||
} | |||
return pos; | |||
} | |||
#if 0 | |||
void | |||
aubio_pitchmcomb_sort_peak (aubio_spectralpeak_t * peaks, uint_t nbins) | |||
{ | |||
qsort (peaks, nbins, sizeof (aubio_spectralpeak_t), | |||
aubio_pitchmcomb_sort_peak_comp); | |||
} | |||
static sint_t | |||
aubio_pitchmcomb_sort_peak_comp (const void *x, const void *y) | |||
{ | |||
return (((aubio_spectralpeak_t *) y)->mag - | |||
((aubio_spectralpeak_t *) x)->mag); | |||
} | |||
void | |||
aubio_pitchmcomb_sort_cand_ene (aubio_spectralcandidate_t ** candidates, | |||
uint_t nbins) | |||
{ | |||
uint_t cur = 0; | |||
uint_t run = 0; | |||
for (cur = 0; cur < nbins; cur++) { | |||
for (run = cur + 1; run < nbins; run++) { | |||
if (candidates[run]->ene > candidates[cur]->ene) | |||
CAND_SWAP (candidates[run], candidates[cur]); | |||
} | |||
} | |||
} | |||
void | |||
aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates, | |||
uint_t nbins) | |||
{ | |||
uint_t cur = 0; | |||
uint_t run = 0; | |||
for (cur = 0; cur < nbins; cur++) { | |||
for (run = cur + 1; run < nbins; run++) { | |||
if (candidates[run]->ebin < candidates[cur]->ebin) | |||
CAND_SWAP (candidates[run], candidates[cur]); | |||
} | |||
} | |||
} | |||
#endif | |||
aubio_pitchmcomb_t * | |||
new_aubio_pitchmcomb (uint_t bufsize, uint_t hopsize) | |||
{ | |||
aubio_pitchmcomb_t *p = AUBIO_NEW (aubio_pitchmcomb_t); | |||
/* bug: should check if size / 8 > post+pre+1 */ | |||
uint_t i, j; | |||
uint_t spec_size; | |||
p->spec_partition = 2; | |||
p->ncand = 5; | |||
p->npartials = 5; | |||
p->cutoff = 1.; | |||
p->threshold = 0.01; | |||
p->win_post = 8; | |||
p->win_pre = 7; | |||
// p->tau = samplerate/bufsize; | |||
p->alpha = 9.; | |||
p->goodcandidate = 0; | |||
p->phasefreq = bufsize / hopsize / TWO_PI; | |||
p->phasediff = TWO_PI * hopsize / bufsize; | |||
spec_size = bufsize / p->spec_partition + 1; | |||
//p->pickerfn = quadpick; | |||
//p->biquad = new_biquad(0.1600,0.3200,0.1600, -0.5949, 0.2348); | |||
/* allocate temp memory */ | |||
p->newmag = new_fvec (spec_size); | |||
/* array for median */ | |||
p->scratch = new_fvec (spec_size); | |||
/* array for phase */ | |||
p->theta = new_fvec (spec_size); | |||
/* array for adaptative threshold */ | |||
p->scratch2 = new_fvec (p->win_post + p->win_pre + 1); | |||
/* array of spectral peaks */ | |||
p->peaks = AUBIO_ARRAY (aubio_spectralpeak_t, spec_size); | |||
for (i = 0; i < spec_size; i++) { | |||
p->peaks[i].bin = 0.; | |||
p->peaks[i].ebin = 0.; | |||
p->peaks[i].mag = 0.; | |||
} | |||
/* array of pointers to spectral candidates */ | |||
p->candidates = AUBIO_ARRAY (aubio_spectralcandidate_t *, p->ncand); | |||
for (i = 0; i < p->ncand; i++) { | |||
p->candidates[i] = AUBIO_NEW (aubio_spectralcandidate_t); | |||
p->candidates[i]->ecomb = AUBIO_ARRAY (smpl_t, spec_size); | |||
for (j = 0; j < spec_size; j++) { | |||
p->candidates[i]->ecomb[j] = 0.; | |||
} | |||
p->candidates[i]->ene = 0.; | |||
p->candidates[i]->ebin = 0.; | |||
p->candidates[i]->len = 0.; | |||
} | |||
return p; | |||
} | |||
void | |||
del_aubio_pitchmcomb (aubio_pitchmcomb_t * p) | |||
{ | |||
uint_t i; | |||
del_fvec (p->newmag); | |||
del_fvec (p->scratch); | |||
del_fvec (p->theta); | |||
del_fvec (p->scratch2); | |||
AUBIO_FREE (p->peaks); | |||
for (i = 0; i < p->ncand; i++) { | |||
AUBIO_FREE (p->candidates[i]->ecomb); | |||
AUBIO_FREE (p->candidates[i]); | |||
} | |||
AUBIO_FREE (p->candidates); | |||
AUBIO_FREE (p); | |||
} |
@@ -0,0 +1,77 @@ | |||
/* | |||
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** \file | |||
Pitch detection using multiple-comb filter | |||
This fundamental frequency estimation algorithm implements spectral | |||
flattening, multi-comb filtering and peak histogramming. | |||
This method was designed by Juan P. Bello and described in: | |||
Juan-Pablo Bello. ``Towards the Automated Analysis of Simple Polyphonic | |||
Music''. PhD thesis, Centre for Digital Music, Queen Mary University of | |||
London, London, UK, 2003. | |||
\example pitch/test-pitchmcomb.c | |||
*/ | |||
#ifndef AUBIO_PITCHMCOMB_H | |||
#define AUBIO_PITCHMCOMB_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** pitch detection object */ | |||
typedef struct _aubio_pitchmcomb_t aubio_pitchmcomb_t; | |||
/** execute pitch detection on an input spectral frame | |||
\param p pitch detection object as returned by new_aubio_pitchmcomb | |||
\param in_fftgrain input signal spectrum as computed by aubio_pvoc_do | |||
\param out_cands pitch candidate frequenciess, in bins | |||
*/ | |||
void aubio_pitchmcomb_do (aubio_pitchmcomb_t * p, const cvec_t * in_fftgrain, | |||
fvec_t * out_cands); | |||
/** creation of the pitch detection object | |||
\param buf_size size of the input buffer to analyse | |||
\param hop_size step size between two consecutive analysis instant | |||
*/ | |||
aubio_pitchmcomb_t *new_aubio_pitchmcomb (uint_t buf_size, uint_t hop_size); | |||
/** deletion of the pitch detection object | |||
\param p pitch detection object as returned by new_aubio_pitchfcomb | |||
*/ | |||
void del_aubio_pitchmcomb (aubio_pitchmcomb_t * p); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_PITCHMCOMB_H */ |
@@ -0,0 +1,119 @@ | |||
/* | |||
Copyright (C) 2004, 2005 Mario Lang <mlang@delysid.org> | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "pitch/pitchschmitt.h" | |||
smpl_t aubio_schmittS16LE (aubio_pitchschmitt_t * p, uint_t nframes, | |||
signed short int *indata); | |||
struct _aubio_pitchschmitt_t | |||
{ | |||
uint_t blockSize; | |||
uint_t rate; | |||
signed short int *schmittBuffer; | |||
signed short int *schmittPointer; | |||
signed short int *buf; | |||
}; | |||
aubio_pitchschmitt_t * | |||
new_aubio_pitchschmitt (uint_t size) | |||
{ | |||
aubio_pitchschmitt_t *p = AUBIO_NEW (aubio_pitchschmitt_t); | |||
p->blockSize = size; | |||
p->schmittBuffer = AUBIO_ARRAY (signed short int, p->blockSize); | |||
p->buf = AUBIO_ARRAY (signed short int, p->blockSize); | |||
p->schmittPointer = p->schmittBuffer; | |||
return p; | |||
} | |||
void | |||
aubio_pitchschmitt_do (aubio_pitchschmitt_t * p, const fvec_t * input, | |||
fvec_t * output) | |||
{ | |||
uint_t j; | |||
for (j = 0; j < input->length; j++) { | |||
p->buf[j] = input->data[j] * 32768.; | |||
} | |||
output->data[0] = aubio_schmittS16LE (p, input->length, p->buf); | |||
} | |||
smpl_t | |||
aubio_schmittS16LE (aubio_pitchschmitt_t * p, uint_t nframes, | |||
signed short int *indata) | |||
{ | |||
uint_t i, j; | |||
uint_t blockSize = p->blockSize; | |||
signed short int *schmittBuffer = p->schmittBuffer; | |||
signed short int *schmittPointer = p->schmittPointer; | |||
smpl_t period = 0., trigfact = 0.6; | |||
for (i = 0; i < nframes; i++) { | |||
*schmittPointer++ = indata[i]; | |||
if (schmittPointer - schmittBuffer >= (sint_t) blockSize) { | |||
sint_t endpoint, startpoint, t1, t2, A1, A2, tc, schmittTriggered; | |||
schmittPointer = schmittBuffer; | |||
for (j = 0, A1 = 0, A2 = 0; j < blockSize; j++) { | |||
if (schmittBuffer[j] > 0 && A1 < schmittBuffer[j]) | |||
A1 = schmittBuffer[j]; | |||
if (schmittBuffer[j] < 0 && A2 < -schmittBuffer[j]) | |||
A2 = -schmittBuffer[j]; | |||
} | |||
t1 = (sint_t) (A1 * trigfact + 0.5); | |||
t2 = -(sint_t) (A2 * trigfact + 0.5); | |||
startpoint = 0; | |||
for (j = 1; j < blockSize && schmittBuffer[j] <= t1; j++); | |||
for ( ; j < blockSize - 1 && !(schmittBuffer[j] >= t2 && | |||
schmittBuffer[j + 1] < t2); j++); | |||
startpoint = j; | |||
schmittTriggered = 0; | |||
endpoint = startpoint + 1; | |||
for (j = startpoint, tc = 0; j < blockSize; j++) { | |||
if (!schmittTriggered) { | |||
schmittTriggered = (schmittBuffer[j] >= t1); | |||
} else if (schmittBuffer[j] >= t2 && schmittBuffer[j + 1] < t2) { | |||
endpoint = j; | |||
tc++; | |||
schmittTriggered = 0; | |||
} | |||
} | |||
if ((endpoint > startpoint) && (tc > 0)) { | |||
period = (smpl_t) (endpoint - startpoint) / tc; | |||
} | |||
} | |||
} | |||
p->schmittBuffer = schmittBuffer; | |||
p->schmittPointer = schmittPointer; | |||
return period; | |||
} | |||
void | |||
del_aubio_pitchschmitt (aubio_pitchschmitt_t * p) | |||
{ | |||
AUBIO_FREE (p->schmittBuffer); | |||
AUBIO_FREE (p->buf); | |||
AUBIO_FREE (p); | |||
} |
@@ -0,0 +1,75 @@ | |||
/* | |||
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** \file | |||
Pitch detection using a Schmitt trigger | |||
This pitch extraction method implements a Schmitt trigger to estimate the | |||
period of a signal. | |||
This file was derived from the tuneit project, written by Mario Lang to | |||
detect the fundamental frequency of a sound. | |||
See http://delysid.org/tuneit.html | |||
\example pitch/test-pitchschmitt.c | |||
*/ | |||
#ifndef AUBIO_PITCHSCHMITT_H | |||
#define AUBIO_PITCHSCHMITT_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** pitch detection object */ | |||
typedef struct _aubio_pitchschmitt_t aubio_pitchschmitt_t; | |||
/** execute pitch detection on an input buffer | |||
\param p pitch detection object as returned by new_aubio_pitchschmitt | |||
\param samples_in input signal vector (length as specified at creation time) | |||
\param cands_out pitch period estimates, in samples | |||
*/ | |||
void aubio_pitchschmitt_do (aubio_pitchschmitt_t * p, const fvec_t * samples_in, | |||
fvec_t * cands_out); | |||
/** creation of the pitch detection object | |||
\param buf_size size of the input buffer to analyse | |||
*/ | |||
aubio_pitchschmitt_t *new_aubio_pitchschmitt (uint_t buf_size); | |||
/** deletion of the pitch detection object | |||
\param p pitch detection object as returned by new_aubio_pitchschmitt | |||
*/ | |||
void del_aubio_pitchschmitt (aubio_pitchschmitt_t * p); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_PITCHSCHMITT_H */ |
@@ -0,0 +1,116 @@ | |||
/* | |||
Copyright (C) 2013 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "cvec.h" | |||
#include "mathutils.h" | |||
#include "spectral/fft.h" | |||
#include "pitch/pitchspecacf.h" | |||
/** pitch specacf structure */ | |||
struct _aubio_pitchspecacf_t | |||
{ | |||
fvec_t *win; /**< temporal weighting window */ | |||
fvec_t *winput; /**< windowed spectrum */ | |||
aubio_fft_t *fft; /**< fft object to compute*/ | |||
fvec_t *fftout; /**< Fourier transform output */ | |||
fvec_t *sqrmag; /**< square magnitudes */ | |||
fvec_t *acf; /**< auto correlation function */ | |||
smpl_t tol; /**< tolerance */ | |||
smpl_t confidence; /**< confidence */ | |||
}; | |||
aubio_pitchspecacf_t * | |||
new_aubio_pitchspecacf (uint_t bufsize) | |||
{ | |||
aubio_pitchspecacf_t *p = AUBIO_NEW (aubio_pitchspecacf_t); | |||
p->fft = new_aubio_fft (bufsize); | |||
if (!p->fft) goto beach; | |||
p->win = new_aubio_window ("hanningz", bufsize); | |||
p->winput = new_fvec (bufsize); | |||
p->fftout = new_fvec (bufsize); | |||
p->sqrmag = new_fvec (bufsize); | |||
p->acf = new_fvec (bufsize / 2 + 1); | |||
p->tol = 1.; | |||
p->confidence = 0.; | |||
return p; | |||
beach: | |||
AUBIO_FREE(p); | |||
return NULL; | |||
} | |||
void | |||
aubio_pitchspecacf_do (aubio_pitchspecacf_t * p, const fvec_t * input, fvec_t * output) | |||
{ | |||
uint_t l, tau; | |||
fvec_t *fftout = p->fftout; | |||
// window the input | |||
for (l = 0; l < input->length; l++) { | |||
p->winput->data[l] = p->win->data[l] * input->data[l]; | |||
} | |||
// get the real / imag parts of its fft | |||
aubio_fft_do_complex (p->fft, p->winput, fftout); | |||
for (l = 0; l < input->length / 2 + 1; l++) { | |||
p->sqrmag->data[l] = SQR(fftout->data[l]); | |||
} | |||
// get the real / imag parts of the fft of the squared magnitude | |||
aubio_fft_do_complex (p->fft, p->sqrmag, fftout); | |||
// copy real part to acf | |||
for (l = 0; l < fftout->length / 2 + 1; l++) { | |||
p->acf->data[l] = fftout->data[l]; | |||
} | |||
// get the minimum | |||
tau = fvec_min_elem (p->acf); | |||
// get the interpolated minimum | |||
output->data[0] = fvec_quadratic_peak_pos (p->acf, tau) * 2.; | |||
} | |||
void | |||
del_aubio_pitchspecacf (aubio_pitchspecacf_t * p) | |||
{ | |||
del_fvec (p->win); | |||
del_fvec (p->winput); | |||
del_aubio_fft (p->fft); | |||
del_fvec (p->sqrmag); | |||
del_fvec (p->fftout); | |||
del_fvec (p->acf); | |||
AUBIO_FREE (p); | |||
} | |||
smpl_t | |||
aubio_pitchspecacf_get_confidence (const aubio_pitchspecacf_t * o) { | |||
// no confidence for now | |||
return o->confidence; | |||
} | |||
uint_t | |||
aubio_pitchspecacf_set_tolerance (aubio_pitchspecacf_t * p, smpl_t tol) | |||
{ | |||
p->tol = tol; | |||
return 0; | |||
} | |||
smpl_t | |||
aubio_pitchspecacf_get_tolerance (const aubio_pitchspecacf_t * p) | |||
{ | |||
return p->tol; | |||
} |
@@ -0,0 +1,103 @@ | |||
/* | |||
Copyright (C) 2013 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** \file | |||
Pitch detection using spectral auto correlation | |||
This algorithm implements pitch detection by computing the autocorrelation | |||
function as the cosine transform of the square spectral magnitudes. | |||
Anssi Klapuri. Qualitative and quantitative aspects in the design of | |||
periodicity esti- mation algorithms. In Proceedings of the European Signal | |||
Processing Conference (EUSIPCO), 2000. | |||
Paul Brossier, [Automatic annotation of musical audio for interactive | |||
systems](http://aubio.org/phd/), Chapter 3, Pitch Analysis, Autocorrelation, | |||
pp. 75-77, PhD thesis, Centre for Digital music, Queen Mary University of | |||
London, London, UK, 2006. | |||
\example pitch/test-pitchspecacf.c | |||
*/ | |||
#ifndef AUBIO_PITCHSPECACF_H | |||
#define AUBIO_PITCHSPECACF_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** pitch detection object */ | |||
typedef struct _aubio_pitchspecacf_t aubio_pitchspecacf_t; | |||
/** execute pitch detection on an input buffer | |||
\param o pitch detection object as returned by new_aubio_pitchspecacf | |||
\param samples_in input signal vector (length as specified at creation time) | |||
\param cands_out pitch period candidates, in samples | |||
*/ | |||
void aubio_pitchspecacf_do (aubio_pitchspecacf_t * o, const fvec_t * samples_in, fvec_t * cands_out); | |||
/** creation of the pitch detection object | |||
\param buf_size size of the input buffer to analyse | |||
*/ | |||
aubio_pitchspecacf_t *new_aubio_pitchspecacf (uint_t buf_size); | |||
/** deletion of the pitch detection object | |||
\param o pitch detection object as returned by new_aubio_pitchspecacf() | |||
*/ | |||
void del_aubio_pitchspecacf (aubio_pitchspecacf_t * o); | |||
/** get tolerance parameter for `specacf` pitch detection object | |||
\param o pitch detection object | |||
\return tolerance parameter for minima selection [default 1.] | |||
*/ | |||
smpl_t aubio_pitchspecacf_get_tolerance (const aubio_pitchspecacf_t * o); | |||
/** set tolerance parameter for `specacf` pitch detection object | |||
\param o pitch detection object | |||
\param tol tolerance parameter for minima selection [default 1.] | |||
\return `1` on error, `0` on success | |||
*/ | |||
uint_t aubio_pitchspecacf_set_tolerance (aubio_pitchspecacf_t * o, smpl_t tol); | |||
/** get currenct confidence for `specacf` pitch detection object | |||
\param o pitch detection object | |||
\return confidence parameter | |||
*/ | |||
smpl_t aubio_pitchspecacf_get_confidence (const aubio_pitchspecacf_t * o); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_PITCHSPECACF_H */ |
@@ -0,0 +1,189 @@ | |||
/* | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/* This algorithm was developed by A. de Cheveigné and H. Kawahara and | |||
* published in: | |||
* | |||
* de Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency | |||
* estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930. | |||
* | |||
* see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "mathutils.h" | |||
#include "pitch/pitchyin.h" | |||
struct _aubio_pitchyin_t | |||
{ | |||
fvec_t *yin; | |||
smpl_t tol; | |||
uint_t peak_pos; | |||
}; | |||
#if 0 | |||
/** compute difference function | |||
\param input input signal | |||
\param yinbuf output buffer to store difference function (half shorter than input) | |||
*/ | |||
void aubio_pitchyin_diff (fvec_t * input, fvec_t * yinbuf); | |||
/** in place computation of the YIN cumulative normalised function | |||
\param yinbuf input signal (a square difference function), also used to store function | |||
*/ | |||
void aubio_pitchyin_getcum (fvec_t * yinbuf); | |||
/** detect pitch in a YIN function | |||
\param yinbuf input buffer as computed by aubio_pitchyin_getcum | |||
*/ | |||
uint_t aubio_pitchyin_getpitch (const fvec_t * yinbuf); | |||
#endif | |||
aubio_pitchyin_t * | |||
new_aubio_pitchyin (uint_t bufsize) | |||
{ | |||
aubio_pitchyin_t *o = AUBIO_NEW (aubio_pitchyin_t); | |||
o->yin = new_fvec (bufsize / 2); | |||
o->tol = 0.15; | |||
o->peak_pos = 0; | |||
return o; | |||
} | |||
void | |||
del_aubio_pitchyin (aubio_pitchyin_t * o) | |||
{ | |||
del_fvec (o->yin); | |||
AUBIO_FREE (o); | |||
} | |||
#if 0 | |||
/* outputs the difference function */ | |||
void | |||
aubio_pitchyin_diff (fvec_t * input, fvec_t * yin) | |||
{ | |||
uint_t j, tau; | |||
smpl_t tmp; | |||
for (tau = 0; tau < yin->length; tau++) { | |||
yin->data[tau] = 0.; | |||
} | |||
for (tau = 1; tau < yin->length; tau++) { | |||
for (j = 0; j < yin->length; j++) { | |||
tmp = input->data[j] - input->data[j + tau]; | |||
yin->data[tau] += SQR (tmp); | |||
} | |||
} | |||
} | |||
/* cumulative mean normalized difference function */ | |||
void | |||
aubio_pitchyin_getcum (fvec_t * yin) | |||
{ | |||
uint_t tau; | |||
smpl_t tmp = 0.; | |||
yin->data[0] = 1.; | |||
//AUBIO_DBG("%f\t",yin->data[0]); | |||
for (tau = 1; tau < yin->length; tau++) { | |||
tmp += yin->data[tau]; | |||
yin->data[tau] *= tau / tmp; | |||
//AUBIO_DBG("%f\t",yin->data[tau]); | |||
} | |||
//AUBIO_DBG("\n"); | |||
} | |||
uint_t | |||
aubio_pitchyin_getpitch (const fvec_t * yin) | |||
{ | |||
uint_t tau = 1; | |||
do { | |||
if (yin->data[tau] < 0.1) { | |||
while (yin->data[tau + 1] < yin->data[tau]) { | |||
tau++; | |||
} | |||
return tau; | |||
} | |||
tau++; | |||
} while (tau < yin->length); | |||
//AUBIO_DBG("No pitch found"); | |||
return 0; | |||
} | |||
#endif | |||
/* all the above in one */ | |||
void | |||
aubio_pitchyin_do (aubio_pitchyin_t * o, const fvec_t * input, fvec_t * out) | |||
{ | |||
const smpl_t tol = o->tol; | |||
fvec_t* yin = o->yin; | |||
const smpl_t *input_data = input->data; | |||
const uint_t length = yin->length; | |||
smpl_t *yin_data = yin->data; | |||
uint_t j, tau; | |||
sint_t period; | |||
smpl_t tmp, tmp2 = 0.; | |||
yin_data[0] = 1.; | |||
for (tau = 1; tau < length; tau++) { | |||
yin_data[tau] = 0.; | |||
for (j = 0; j < length; j++) { | |||
tmp = input_data[j] - input_data[j + tau]; | |||
yin_data[tau] += SQR (tmp); | |||
} | |||
tmp2 += yin_data[tau]; | |||
if (tmp2 != 0) { | |||
yin->data[tau] *= tau / tmp2; | |||
} else { | |||
yin->data[tau] = 1.; | |||
} | |||
period = tau - 3; | |||
if (tau > 4 && (yin_data[period] < tol) && | |||
(yin_data[period] < yin_data[period + 1])) { | |||
o->peak_pos = (uint_t)period; | |||
out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos); | |||
return; | |||
} | |||
} | |||
o->peak_pos = (uint_t)fvec_min_elem (yin); | |||
out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos); | |||
} | |||
smpl_t | |||
aubio_pitchyin_get_confidence (aubio_pitchyin_t * o) { | |||
return 1. - o->yin->data[o->peak_pos]; | |||
} | |||
uint_t | |||
aubio_pitchyin_set_tolerance (aubio_pitchyin_t * o, smpl_t tol) | |||
{ | |||
o->tol = tol; | |||
return 0; | |||
} | |||
smpl_t | |||
aubio_pitchyin_get_tolerance (aubio_pitchyin_t * o) | |||
{ | |||
return o->tol; | |||
} |
@@ -0,0 +1,100 @@ | |||
/* | |||
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** \file | |||
Pitch detection using the YIN algorithm | |||
This algorithm was developed by A. de Cheveigne and H. Kawahara and | |||
published in: | |||
De Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency | |||
estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930. | |||
see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html | |||
http://recherche.ircam.fr/equipes/pcm/cheveign/ps/2002_JASA_YIN_proof.pdf | |||
\example pitch/test-pitchyin.c | |||
*/ | |||
#ifndef AUBIO_PITCHYIN_H | |||
#define AUBIO_PITCHYIN_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** pitch detection object */ | |||
typedef struct _aubio_pitchyin_t aubio_pitchyin_t; | |||
/** creation of the pitch detection object | |||
\param buf_size size of the input buffer to analyse | |||
*/ | |||
aubio_pitchyin_t *new_aubio_pitchyin (uint_t buf_size); | |||
/** deletion of the pitch detection object | |||
\param o pitch detection object as returned by new_aubio_pitchyin() | |||
*/ | |||
void del_aubio_pitchyin (aubio_pitchyin_t * o); | |||
/** execute pitch detection an input buffer | |||
\param o pitch detection object as returned by new_aubio_pitchyin() | |||
\param samples_in input signal vector (length as specified at creation time) | |||
\param cands_out pitch period candidates, in samples | |||
*/ | |||
void aubio_pitchyin_do (aubio_pitchyin_t * o, const fvec_t * samples_in, fvec_t * cands_out); | |||
/** set tolerance parameter for YIN algorithm | |||
\param o YIN pitch detection object | |||
\param tol tolerance parameter for minima selection [default 0.15] | |||
*/ | |||
uint_t aubio_pitchyin_set_tolerance (aubio_pitchyin_t * o, smpl_t tol); | |||
/** get tolerance parameter for YIN algorithm | |||
\param o YIN pitch detection object | |||
\return tolerance parameter for minima selection [default 0.15] | |||
*/ | |||
smpl_t aubio_pitchyin_get_tolerance (aubio_pitchyin_t * o); | |||
/** get current confidence of YIN algorithm | |||
\param o YIN pitch detection object | |||
\return confidence parameter | |||
*/ | |||
smpl_t aubio_pitchyin_get_confidence (aubio_pitchyin_t * o); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_PITCHYIN_H */ |
@@ -0,0 +1,201 @@ | |||
/* | |||
Copyright (C) 2003-2017 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/* This algorithm was developed by A. de Cheveigné and H. Kawahara and | |||
* published in: | |||
* | |||
* de Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency | |||
* estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930. | |||
* | |||
* see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "mathutils.h" | |||
#include "cvec.h" | |||
#include "spectral/fft.h" | |||
#include "pitch/pitchyinfast.h" | |||
struct _aubio_pitchyinfast_t | |||
{ | |||
fvec_t *yin; | |||
smpl_t tol; | |||
uint_t peak_pos; | |||
fvec_t *tmpdata; | |||
fvec_t *sqdiff; | |||
fvec_t *kernel; | |||
fvec_t *samples_fft; | |||
fvec_t *kernel_fft; | |||
aubio_fft_t *fft; | |||
}; | |||
aubio_pitchyinfast_t * | |||
new_aubio_pitchyinfast (uint_t bufsize) | |||
{ | |||
aubio_pitchyinfast_t *o = AUBIO_NEW (aubio_pitchyinfast_t); | |||
o->yin = new_fvec (bufsize / 2); | |||
o->tmpdata = new_fvec (bufsize); | |||
o->sqdiff = new_fvec (bufsize / 2); | |||
o->kernel = new_fvec (bufsize); | |||
o->samples_fft = new_fvec (bufsize); | |||
o->kernel_fft = new_fvec (bufsize); | |||
o->fft = new_aubio_fft (bufsize); | |||
if (!o->yin || !o->tmpdata || !o->tmpdata || !o->sqdiff | |||
|| !o->kernel || !o->samples_fft || !o->kernel || !o->fft) | |||
{ | |||
del_aubio_pitchyinfast(o); | |||
return NULL; | |||
} | |||
o->tol = 0.15; | |||
o->peak_pos = 0; | |||
return o; | |||
} | |||
void | |||
del_aubio_pitchyinfast (aubio_pitchyinfast_t * o) | |||
{ | |||
if (o->yin) | |||
del_fvec (o->yin); | |||
if (o->tmpdata) | |||
del_fvec (o->tmpdata); | |||
if (o->sqdiff) | |||
del_fvec (o->sqdiff); | |||
if (o->kernel) | |||
del_fvec (o->kernel); | |||
if (o->samples_fft) | |||
del_fvec (o->samples_fft); | |||
if (o->kernel_fft) | |||
del_fvec (o->kernel_fft); | |||
if (o->fft) | |||
del_aubio_fft (o->fft); | |||
AUBIO_FREE (o); | |||
} | |||
/* all the above in one */ | |||
void | |||
aubio_pitchyinfast_do (aubio_pitchyinfast_t * o, const fvec_t * input, fvec_t * out) | |||
{ | |||
const smpl_t tol = o->tol; | |||
fvec_t* yin = o->yin; | |||
const uint_t length = yin->length; | |||
uint_t B = o->tmpdata->length; | |||
uint_t W = o->yin->length; // B / 2 | |||
fvec_t tmp_slice, kernel_ptr; | |||
uint_t tau; | |||
sint_t period; | |||
smpl_t tmp2 = 0.; | |||
// compute r_t(0) + r_t+tau(0) | |||
{ | |||
fvec_t *squares = o->tmpdata; | |||
fvec_weighted_copy(input, input, squares); | |||
#if 0 | |||
for (tau = 0; tau < W; tau++) { | |||
tmp_slice.data = squares->data + tau; | |||
tmp_slice.length = W; | |||
o->sqdiff->data[tau] = fvec_sum(&tmp_slice); | |||
} | |||
#else | |||
tmp_slice.data = squares->data; | |||
tmp_slice.length = W; | |||
o->sqdiff->data[0] = fvec_sum(&tmp_slice); | |||
for (tau = 1; tau < W; tau++) { | |||
o->sqdiff->data[tau] = o->sqdiff->data[tau-1]; | |||
o->sqdiff->data[tau] -= squares->data[tau-1]; | |||
o->sqdiff->data[tau] += squares->data[W+tau-1]; | |||
} | |||
#endif | |||
fvec_add(o->sqdiff, o->sqdiff->data[0]); | |||
} | |||
// compute r_t(tau) = -2.*ifft(fft(samples)*fft(samples[W-1::-1])) | |||
{ | |||
fvec_t *compmul = o->tmpdata; | |||
fvec_t *rt_of_tau = o->samples_fft; | |||
aubio_fft_do_complex(o->fft, input, o->samples_fft); | |||
// build kernel, take a copy of first half of samples | |||
tmp_slice.data = input->data; | |||
tmp_slice.length = W; | |||
kernel_ptr.data = o->kernel->data + 1; | |||
kernel_ptr.length = W; | |||
fvec_copy(&tmp_slice, &kernel_ptr); | |||
// reverse them | |||
fvec_rev(&kernel_ptr); | |||
// compute fft(kernel) | |||
aubio_fft_do_complex(o->fft, o->kernel, o->kernel_fft); | |||
// compute complex product | |||
compmul->data[0] = o->kernel_fft->data[0] * o->samples_fft->data[0]; | |||
for (tau = 1; tau < W; tau++) { | |||
compmul->data[tau] = o->kernel_fft->data[tau] * o->samples_fft->data[tau]; | |||
compmul->data[tau] -= o->kernel_fft->data[B-tau] * o->samples_fft->data[B-tau]; | |||
} | |||
compmul->data[W] = o->kernel_fft->data[W] * o->samples_fft->data[W]; | |||
for (tau = 1; tau < W; tau++) { | |||
compmul->data[B-tau] = o->kernel_fft->data[B-tau] * o->samples_fft->data[tau]; | |||
compmul->data[B-tau] += o->kernel_fft->data[tau] * o->samples_fft->data[B-tau]; | |||
} | |||
// compute inverse fft | |||
aubio_fft_rdo_complex(o->fft, compmul, rt_of_tau); | |||
// compute square difference r_t(tau) = sqdiff - 2 * r_t_tau[W-1:-1] | |||
for (tau = 0; tau < W; tau++) { | |||
yin->data[tau] = o->sqdiff->data[tau] - 2. * rt_of_tau->data[tau+W]; | |||
} | |||
} | |||
// now build yin and look for first minimum | |||
fvec_zeros(out); | |||
yin->data[0] = 1.; | |||
for (tau = 1; tau < length; tau++) { | |||
tmp2 += yin->data[tau]; | |||
if (tmp2 != 0) { | |||
yin->data[tau] *= tau / tmp2; | |||
} else { | |||
yin->data[tau] = 1.; | |||
} | |||
period = tau - 3; | |||
if (tau > 4 && (yin->data[period] < tol) && | |||
(yin->data[period] < yin->data[period + 1])) { | |||
o->peak_pos = (uint_t)period; | |||
out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos); | |||
return; | |||
} | |||
} | |||
// use global minimum | |||
o->peak_pos = (uint_t)fvec_min_elem (yin); | |||
out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos); | |||
} | |||
smpl_t | |||
aubio_pitchyinfast_get_confidence (aubio_pitchyinfast_t * o) { | |||
return 1. - o->yin->data[o->peak_pos]; | |||
} | |||
uint_t | |||
aubio_pitchyinfast_set_tolerance (aubio_pitchyinfast_t * o, smpl_t tol) | |||
{ | |||
o->tol = tol; | |||
return 0; | |||
} | |||
smpl_t | |||
aubio_pitchyinfast_get_tolerance (aubio_pitchyinfast_t * o) | |||
{ | |||
return o->tol; | |||
} |
@@ -0,0 +1,102 @@ | |||
/* | |||
Copyright (C) 2003-2017 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** \file | |||
Pitch detection using YIN algorithm (fast implementation) | |||
This algorithm was developed by A. de Cheveigne and H. Kawahara and | |||
published in: | |||
De Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency | |||
estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930. | |||
This implementation compute the autocorrelation function using time domain | |||
convolution computed in the spectral domain. | |||
see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html | |||
http://recherche.ircam.fr/equipes/pcm/cheveign/ps/2002_JASA_YIN_proof.pdf | |||
*/ | |||
#ifndef AUBIO_PITCHYINFAST_H | |||
#define AUBIO_PITCHYINFAST_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** pitch detection object */ | |||
typedef struct _aubio_pitchyinfast_t aubio_pitchyinfast_t; | |||
/** creation of the pitch detection object | |||
\param buf_size size of the input buffer to analyse | |||
*/ | |||
aubio_pitchyinfast_t *new_aubio_pitchyinfast (uint_t buf_size); | |||
/** deletion of the pitch detection object | |||
\param o pitch detection object as returned by new_aubio_pitchyin() | |||
*/ | |||
void del_aubio_pitchyinfast (aubio_pitchyinfast_t * o); | |||
/** execute pitch detection an input buffer | |||
\param o pitch detection object as returned by new_aubio_pitchyin() | |||
\param samples_in input signal vector (length as specified at creation time) | |||
\param cands_out pitch period candidates, in samples | |||
*/ | |||
void aubio_pitchyinfast_do (aubio_pitchyinfast_t * o, const fvec_t * samples_in, fvec_t * cands_out); | |||
/** set tolerance parameter for YIN algorithm | |||
\param o YIN pitch detection object | |||
\param tol tolerance parameter for minima selection [default 0.15] | |||
*/ | |||
uint_t aubio_pitchyinfast_set_tolerance (aubio_pitchyinfast_t * o, smpl_t tol); | |||
/** get tolerance parameter for YIN algorithm | |||
\param o YIN pitch detection object | |||
\return tolerance parameter for minima selection [default 0.15] | |||
*/ | |||
smpl_t aubio_pitchyinfast_get_tolerance (aubio_pitchyinfast_t * o); | |||
/** get current confidence of YIN algorithm | |||
\param o YIN pitch detection object | |||
\return confidence parameter | |||
*/ | |||
smpl_t aubio_pitchyinfast_get_confidence (aubio_pitchyinfast_t * o); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_PITCHYINFAST_H */ | |||
@@ -0,0 +1,208 @@ | |||
/* | |||
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "cvec.h" | |||
#include "mathutils.h" | |||
#include "spectral/fft.h" | |||
#include "pitch/pitchyinfft.h" | |||
/** pitch yinfft structure */ | |||
struct _aubio_pitchyinfft_t | |||
{ | |||
fvec_t *win; /**< temporal weighting window */ | |||
fvec_t *winput; /**< windowed spectrum */ | |||
fvec_t *sqrmag; /**< square difference function */ | |||
fvec_t *weight; /**< spectral weighting window (psychoacoustic model) */ | |||
fvec_t *fftout; /**< Fourier transform output */ | |||
aubio_fft_t *fft; /**< fft object to compute square difference function */ | |||
fvec_t *yinfft; /**< Yin function */ | |||
smpl_t tol; /**< Yin tolerance */ | |||
uint_t peak_pos; /**< currently selected peak pos*/ | |||
uint_t short_period; /** shortest period under which to check for octave error */ | |||
}; | |||
static const smpl_t freqs[] = { | |||
0., 20., 25., 31.5, 40., 50., 63., 80., 100., 125., | |||
160., 200., 250., 315., 400., 500., 630., 800., 1000., 1250., | |||
1600., 2000., 2500., 3150., 4000., 5000., 6300., 8000., 9000., 10000., | |||
12500., 15000., 20000., 25100., -1. | |||
}; | |||
static const smpl_t weight[] = { | |||
-75.8, -70.1, -60.8, -52.1, -44.2, -37.5, -31.3, -25.6, -20.9, -16.5, | |||
-12.6, -9.60, -7.00, -4.70, -3.00, -1.80, -0.80, -0.20, -0.00, 0.50, | |||
1.60, 3.20, 5.40, 7.80, 8.10, 5.30, -2.40, -11.1, -12.8, -12.2, | |||
-7.40, -17.8, -17.8, -17.8 | |||
}; | |||
aubio_pitchyinfft_t * | |||
new_aubio_pitchyinfft (uint_t samplerate, uint_t bufsize) | |||
{ | |||
uint_t i = 0, j = 1; | |||
smpl_t freq = 0, a0 = 0, a1 = 0, f0 = 0, f1 = 0; | |||
aubio_pitchyinfft_t *p = AUBIO_NEW (aubio_pitchyinfft_t); | |||
p->winput = new_fvec (bufsize); | |||
p->fft = new_aubio_fft (bufsize); | |||
if (!p->fft) goto beach; | |||
p->fftout = new_fvec (bufsize); | |||
p->sqrmag = new_fvec (bufsize); | |||
p->yinfft = new_fvec (bufsize / 2 + 1); | |||
p->tol = 0.85; | |||
p->peak_pos = 0; | |||
p->win = new_aubio_window ("hanningz", bufsize); | |||
p->weight = new_fvec (bufsize / 2 + 1); | |||
for (i = 0; i < p->weight->length; i++) { | |||
freq = (smpl_t) i / (smpl_t) bufsize *(smpl_t) samplerate; | |||
while (freq > freqs[j] && freqs[j] > 0) { | |||
//AUBIO_DBG("freq %3.5f > %3.5f \tsamplerate %d (Hz) \t" | |||
// "(weight length %d, bufsize %d) %d %d\n", freq, freqs[j], | |||
// samplerate, p->weight->length, bufsize, i, j); | |||
j += 1; | |||
} | |||
a0 = weight[j - 1]; | |||
f0 = freqs[j - 1]; | |||
a1 = weight[j]; | |||
f1 = freqs[j]; | |||
if (f0 == f1) { // just in case | |||
p->weight->data[i] = a0; | |||
} else if (f0 == 0) { // y = ax+b | |||
p->weight->data[i] = (a1 - a0) / f1 * freq + a0; | |||
} else { | |||
p->weight->data[i] = (a1 - a0) / (f1 - f0) * freq + | |||
(a0 - (a1 - a0) / (f1 / f0 - 1.)); | |||
} | |||
while (freq > freqs[j]) { | |||
j += 1; | |||
} | |||
//AUBIO_DBG("%f\n",p->weight->data[i]); | |||
p->weight->data[i] = DB2LIN (p->weight->data[i]); | |||
//p->weight->data[i] = SQRT(DB2LIN(p->weight->data[i])); | |||
} | |||
// check for octave errors above 1300 Hz | |||
p->short_period = (uint_t)ROUND(samplerate / 1300.); | |||
return p; | |||
beach: | |||
if (p->winput) del_fvec(p->winput); | |||
AUBIO_FREE(p); | |||
return NULL; | |||
} | |||
void | |||
aubio_pitchyinfft_do (aubio_pitchyinfft_t * p, const fvec_t * input, fvec_t * output) | |||
{ | |||
uint_t tau, l; | |||
uint_t length = p->fftout->length; | |||
uint_t halfperiod; | |||
fvec_t *fftout = p->fftout; | |||
fvec_t *yin = p->yinfft; | |||
smpl_t tmp = 0., sum = 0.; | |||
// window the input | |||
fvec_weighted_copy(input, p->win, p->winput); | |||
// get the real / imag parts of its fft | |||
aubio_fft_do_complex (p->fft, p->winput, fftout); | |||
// get the squared magnitude spectrum, applying some weight | |||
p->sqrmag->data[0] = SQR(fftout->data[0]); | |||
p->sqrmag->data[0] *= p->weight->data[0]; | |||
for (l = 1; l < length / 2; l++) { | |||
p->sqrmag->data[l] = SQR(fftout->data[l]) + SQR(fftout->data[length - l]); | |||
p->sqrmag->data[l] *= p->weight->data[l]; | |||
p->sqrmag->data[length - l] = p->sqrmag->data[l]; | |||
} | |||
p->sqrmag->data[length / 2] = SQR(fftout->data[length / 2]); | |||
p->sqrmag->data[length / 2] *= p->weight->data[length / 2]; | |||
// get sum of weighted squared mags | |||
for (l = 0; l < length / 2 + 1; l++) { | |||
sum += p->sqrmag->data[l]; | |||
} | |||
sum *= 2.; | |||
// get the real / imag parts of the fft of the squared magnitude | |||
aubio_fft_do_complex (p->fft, p->sqrmag, fftout); | |||
yin->data[0] = 1.; | |||
for (tau = 1; tau < yin->length; tau++) { | |||
// compute the square differences | |||
yin->data[tau] = sum - fftout->data[tau]; | |||
// and the cumulative mean normalized difference function | |||
tmp += yin->data[tau]; | |||
if (tmp != 0) { | |||
yin->data[tau] *= tau / tmp; | |||
} else { | |||
yin->data[tau] = 1.; | |||
} | |||
} | |||
// find best candidates | |||
tau = fvec_min_elem (yin); | |||
if (yin->data[tau] < p->tol) { | |||
// no interpolation, directly return the period as an integer | |||
//output->data[0] = tau; | |||
//return; | |||
// 3 point quadratic interpolation | |||
//return fvec_quadratic_peak_pos (yin,tau,1); | |||
/* additional check for (unlikely) octave doubling in higher frequencies */ | |||
if (tau > p->short_period) { | |||
output->data[0] = fvec_quadratic_peak_pos (yin, tau); | |||
} else { | |||
/* should compare the minimum value of each interpolated peaks */ | |||
halfperiod = FLOOR (tau / 2 + .5); | |||
if (yin->data[halfperiod] < p->tol) | |||
p->peak_pos = halfperiod; | |||
else | |||
p->peak_pos = tau; | |||
output->data[0] = fvec_quadratic_peak_pos (yin, p->peak_pos); | |||
} | |||
} else { | |||
p->peak_pos = 0; | |||
output->data[0] = 0.; | |||
} | |||
} | |||
void | |||
del_aubio_pitchyinfft (aubio_pitchyinfft_t * p) | |||
{ | |||
del_fvec (p->win); | |||
del_aubio_fft (p->fft); | |||
del_fvec (p->yinfft); | |||
del_fvec (p->sqrmag); | |||
del_fvec (p->fftout); | |||
del_fvec (p->winput); | |||
del_fvec (p->weight); | |||
AUBIO_FREE (p); | |||
} | |||
smpl_t | |||
aubio_pitchyinfft_get_confidence (aubio_pitchyinfft_t * o) { | |||
return 1. - o->yinfft->data[o->peak_pos]; | |||
} | |||
uint_t | |||
aubio_pitchyinfft_set_tolerance (aubio_pitchyinfft_t * p, smpl_t tol) | |||
{ | |||
p->tol = tol; | |||
return 0; | |||
} | |||
smpl_t | |||
aubio_pitchyinfft_get_tolerance (aubio_pitchyinfft_t * p) | |||
{ | |||
return p->tol; | |||
} |
@@ -0,0 +1,99 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** \file | |||
Pitch detection using a spectral implementation of the YIN algorithm | |||
This algorithm was derived from the YIN algorithm. In this implementation, a | |||
Fourier transform is used to compute a tapered square difference function, | |||
which allows spectral weighting. Because the difference function is tapered, | |||
the selection of the period is simplified. | |||
Paul Brossier, [Automatic annotation of musical audio for interactive | |||
systems](http://aubio.org/phd/), Chapter 3, Pitch Analysis, PhD thesis, | |||
Centre for Digital music, Queen Mary University of London, London, UK, 2006. | |||
\example pitch/test-pitchyinfft.c | |||
*/ | |||
#ifndef AUBIO_PITCHYINFFT_H | |||
#define AUBIO_PITCHYINFFT_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** pitch detection object */ | |||
typedef struct _aubio_pitchyinfft_t aubio_pitchyinfft_t; | |||
/** execute pitch detection on an input buffer | |||
\param o pitch detection object as returned by new_aubio_pitchyinfft | |||
\param samples_in input signal vector (length as specified at creation time) | |||
\param cands_out pitch period candidates, in samples | |||
*/ | |||
void aubio_pitchyinfft_do (aubio_pitchyinfft_t * o, const fvec_t * samples_in, fvec_t * cands_out); | |||
/** creation of the pitch detection object | |||
\param samplerate samplerate of the input signal | |||
\param buf_size size of the input buffer to analyse | |||
*/ | |||
aubio_pitchyinfft_t *new_aubio_pitchyinfft (uint_t samplerate, uint_t buf_size); | |||
/** deletion of the pitch detection object | |||
\param o pitch detection object as returned by new_aubio_pitchyinfft() | |||
*/ | |||
void del_aubio_pitchyinfft (aubio_pitchyinfft_t * o); | |||
/** get tolerance parameter for YIN algorithm | |||
\param o YIN pitch detection object | |||
\return tolerance parameter for minima selection [default 0.15] | |||
*/ | |||
smpl_t aubio_pitchyinfft_get_tolerance (aubio_pitchyinfft_t * o); | |||
/** set tolerance parameter for YIN algorithm | |||
\param o YIN pitch detection object | |||
\param tol tolerance parameter for minima selection [default 0.15] | |||
*/ | |||
uint_t aubio_pitchyinfft_set_tolerance (aubio_pitchyinfft_t * o, smpl_t tol); | |||
/** get current confidence of YIN algorithm | |||
\param o YIN pitch detection object | |||
\return confidence parameter | |||
*/ | |||
smpl_t aubio_pitchyinfft_get_confidence (aubio_pitchyinfft_t * o); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_PITCHYINFFT_H */ |
@@ -0,0 +1,582 @@ | |||
/* | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "cvec.h" | |||
#include "mathutils.h" | |||
#include "spectral/fft.h" | |||
#ifdef HAVE_FFTW3 // using FFTW3 | |||
/* note that <complex.h> is not included here but only in aubio_priv.h, so that | |||
* c++ projects can still use their own complex definition. */ | |||
#include <fftw3.h> | |||
#include <pthread.h> | |||
#ifdef HAVE_COMPLEX_H | |||
#ifdef HAVE_FFTW3F | |||
/** fft data type with complex.h and fftw3f */ | |||
#define FFTW_TYPE fftwf_complex | |||
#else | |||
/** fft data type with complex.h and fftw3 */ | |||
#define FFTW_TYPE fftw_complex | |||
#endif | |||
#else | |||
#ifdef HAVE_FFTW3F | |||
/** fft data type without complex.h and with fftw3f */ | |||
#define FFTW_TYPE float | |||
#else | |||
/** fft data type without complex.h and with fftw */ | |||
#define FFTW_TYPE double | |||
#endif | |||
#endif | |||
/** fft data type */ | |||
typedef FFTW_TYPE fft_data_t; | |||
#ifdef HAVE_FFTW3F | |||
#define fftw_malloc fftwf_malloc | |||
#define fftw_free fftwf_free | |||
#define fftw_execute fftwf_execute | |||
#define fftw_plan_dft_r2c_1d fftwf_plan_dft_r2c_1d | |||
#define fftw_plan_dft_c2r_1d fftwf_plan_dft_c2r_1d | |||
#define fftw_plan_r2r_1d fftwf_plan_r2r_1d | |||
#define fftw_plan fftwf_plan | |||
#define fftw_destroy_plan fftwf_destroy_plan | |||
#endif | |||
#ifdef HAVE_FFTW3F | |||
#if HAVE_AUBIO_DOUBLE | |||
#error "Using aubio in double precision with fftw3 in single precision" | |||
#endif /* HAVE_AUBIO_DOUBLE */ | |||
#define real_t float | |||
#elif defined (HAVE_FFTW3) /* HAVE_FFTW3F */ | |||
#if !HAVE_AUBIO_DOUBLE | |||
#error "Using aubio in single precision with fftw3 in double precision" | |||
#endif /* HAVE_AUBIO_DOUBLE */ | |||
#define real_t double | |||
#endif /* HAVE_FFTW3F */ | |||
#ifndef __MOD_DEVICES__ | |||
// a global mutex for FFTW thread safety | |||
pthread_mutex_t aubio_fftw_mutex = PTHREAD_MUTEX_INITIALIZER; | |||
#endif | |||
#elif defined HAVE_ACCELERATE // using ACCELERATE | |||
// https://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/reference.html | |||
#include <Accelerate/Accelerate.h> | |||
#if !HAVE_AUBIO_DOUBLE | |||
#define aubio_vDSP_ctoz vDSP_ctoz | |||
#define aubio_vDSP_fft_zrip vDSP_fft_zrip | |||
#define aubio_vDSP_ztoc vDSP_ztoc | |||
#define aubio_vDSP_zvmags vDSP_zvmags | |||
#define aubio_vDSP_zvphas vDSP_zvphas | |||
#define aubio_vDSP_vsadd vDSP_vsadd | |||
#define aubio_vDSP_vsmul vDSP_vsmul | |||
#define aubio_DSPComplex DSPComplex | |||
#define aubio_DSPSplitComplex DSPSplitComplex | |||
#define aubio_vDSP_DFT_Setup vDSP_DFT_Setup | |||
#define aubio_vDSP_DFT_zrop_CreateSetup vDSP_DFT_zrop_CreateSetup | |||
#define aubio_vDSP_DFT_Execute vDSP_DFT_Execute | |||
#define aubio_vDSP_DFT_DestroySetup vDSP_DFT_DestroySetup | |||
#define aubio_vvsqrt vvsqrtf | |||
#else | |||
#define aubio_vDSP_ctoz vDSP_ctozD | |||
#define aubio_vDSP_fft_zrip vDSP_fft_zripD | |||
#define aubio_vDSP_ztoc vDSP_ztocD | |||
#define aubio_vDSP_zvmags vDSP_zvmagsD | |||
#define aubio_vDSP_zvphas vDSP_zvphasD | |||
#define aubio_vDSP_vsadd vDSP_vsaddD | |||
#define aubio_vDSP_vsmul vDSP_vsmulD | |||
#define aubio_DSPComplex DSPDoubleComplex | |||
#define aubio_DSPSplitComplex DSPDoubleSplitComplex | |||
#define aubio_vDSP_DFT_Setup vDSP_DFT_SetupD | |||
#define aubio_vDSP_DFT_zrop_CreateSetup vDSP_DFT_zrop_CreateSetupD | |||
#define aubio_vDSP_DFT_Execute vDSP_DFT_ExecuteD | |||
#define aubio_vDSP_DFT_DestroySetup vDSP_DFT_DestroySetupD | |||
#define aubio_vvsqrt vvsqrt | |||
#endif /* HAVE_AUBIO_DOUBLE */ | |||
#elif defined HAVE_INTEL_IPP // using INTEL IPP | |||
#if !HAVE_AUBIO_DOUBLE | |||
#define aubio_IppFloat Ipp32f | |||
#define aubio_IppComplex Ipp32fc | |||
#define aubio_FFTSpec FFTSpec_R_32f | |||
#define aubio_ippsMalloc_complex ippsMalloc_32fc | |||
#define aubio_ippsFFTInit_R ippsFFTInit_R_32f | |||
#define aubio_ippsFFTGetSize_R ippsFFTGetSize_R_32f | |||
#define aubio_ippsFFTInv_CCSToR ippsFFTInv_CCSToR_32f | |||
#define aubio_ippsFFTFwd_RToCCS ippsFFTFwd_RToCCS_32f | |||
#define aubio_ippsAtan2 ippsAtan2_32f_A21 | |||
#else /* HAVE_AUBIO_DOUBLE */ | |||
#define aubio_IppFloat Ipp64f | |||
#define aubio_IppComplex Ipp64fc | |||
#define aubio_FFTSpec FFTSpec_R_64f | |||
#define aubio_ippsMalloc_complex ippsMalloc_64fc | |||
#define aubio_ippsFFTInit_R ippsFFTInit_R_64f | |||
#define aubio_ippsFFTGetSize_R ippsFFTGetSize_R_64f | |||
#define aubio_ippsFFTInv_CCSToR ippsFFTInv_CCSToR_64f | |||
#define aubio_ippsFFTFwd_RToCCS ippsFFTFwd_RToCCS_64f | |||
#define aubio_ippsAtan2 ippsAtan2_64f_A50 | |||
#endif | |||
#else // using OOURA | |||
// let's use ooura instead | |||
extern void aubio_ooura_rdft(int, int, smpl_t *, int *, smpl_t *); | |||
#endif | |||
struct _aubio_fft_t { | |||
uint_t winsize; | |||
uint_t fft_size; | |||
#ifdef HAVE_FFTW3 // using FFTW3 | |||
real_t *in, *out; | |||
fftw_plan pfw, pbw; | |||
fft_data_t * specdata; /* complex spectral data */ | |||
#elif defined HAVE_ACCELERATE // using ACCELERATE | |||
aubio_vDSP_DFT_Setup fftSetupFwd; | |||
aubio_vDSP_DFT_Setup fftSetupBwd; | |||
aubio_DSPSplitComplex spec; | |||
smpl_t *in, *out; | |||
#elif defined HAVE_INTEL_IPP // using Intel IPP | |||
smpl_t *in, *out; | |||
Ipp8u* memSpec; | |||
Ipp8u* memInit; | |||
Ipp8u* memBuffer; | |||
struct aubio_FFTSpec* fftSpec; | |||
aubio_IppComplex* complexOut; | |||
#else // using OOURA | |||
smpl_t *in, *out; | |||
smpl_t *w; | |||
int *ip; | |||
#endif /* using OOURA */ | |||
fvec_t * compspec; | |||
}; | |||
aubio_fft_t * new_aubio_fft (uint_t winsize) { | |||
aubio_fft_t * s = AUBIO_NEW(aubio_fft_t); | |||
if ((sint_t)winsize < 2) { | |||
AUBIO_ERR("fft: got winsize %d, but can not be < 2\n", winsize); | |||
goto beach; | |||
} | |||
#ifdef HAVE_FFTW3 | |||
uint_t i; | |||
s->winsize = winsize; | |||
/* allocate memory */ | |||
s->in = AUBIO_ARRAY(real_t,winsize); | |||
s->out = AUBIO_ARRAY(real_t,winsize); | |||
s->compspec = new_fvec(winsize); | |||
/* create plans */ | |||
#ifndef __MOD_DEVICES__ | |||
pthread_mutex_lock(&aubio_fftw_mutex); | |||
#endif | |||
#ifdef HAVE_COMPLEX_H | |||
s->fft_size = winsize/2 + 1; | |||
s->specdata = (fft_data_t*)fftw_malloc(sizeof(fft_data_t)*s->fft_size); | |||
s->pfw = fftw_plan_dft_r2c_1d(winsize, s->in, s->specdata, FFTW_ESTIMATE); | |||
s->pbw = fftw_plan_dft_c2r_1d(winsize, s->specdata, s->out, FFTW_ESTIMATE); | |||
#else | |||
s->fft_size = winsize; | |||
s->specdata = (fft_data_t*)fftw_malloc(sizeof(fft_data_t)*s->fft_size); | |||
s->pfw = fftw_plan_r2r_1d(winsize, s->in, s->specdata, FFTW_R2HC, FFTW_ESTIMATE); | |||
s->pbw = fftw_plan_r2r_1d(winsize, s->specdata, s->out, FFTW_HC2R, FFTW_ESTIMATE); | |||
#endif | |||
#ifndef __MOD_DEVICES__ | |||
pthread_mutex_unlock(&aubio_fftw_mutex); | |||
#endif | |||
for (i = 0; i < s->winsize; i++) { | |||
s->in[i] = 0.; | |||
s->out[i] = 0.; | |||
} | |||
for (i = 0; i < s->fft_size; i++) { | |||
s->specdata[i] = 0.; | |||
} | |||
#elif defined HAVE_ACCELERATE // using ACCELERATE | |||
{ | |||
uint_t radix = winsize; | |||
uint_t order = 0; | |||
while ((radix / 2) * 2 == radix) { | |||
radix /= 2; | |||
order++; | |||
} | |||
if (order < 4 || (radix != 1 && radix != 3 && radix != 5 && radix != 15)) { | |||
AUBIO_ERR("fft: vDSP/Accelerate supports FFT with sizes = " | |||
"f * 2 ** n, where n > 4 and f in [1, 3, 5, 15], but requested %d. " | |||
"Use the closest power of two, or try recompiling aubio with " | |||
"--enable-fftw3.\n", winsize); | |||
goto beach; | |||
} | |||
} | |||
s->winsize = winsize; | |||
s->fft_size = winsize; | |||
s->compspec = new_fvec(winsize); | |||
s->in = AUBIO_ARRAY(smpl_t, s->fft_size); | |||
s->out = AUBIO_ARRAY(smpl_t, s->fft_size); | |||
s->spec.realp = AUBIO_ARRAY(smpl_t, s->fft_size/2); | |||
s->spec.imagp = AUBIO_ARRAY(smpl_t, s->fft_size/2); | |||
s->fftSetupFwd = aubio_vDSP_DFT_zrop_CreateSetup(NULL, | |||
s->fft_size, vDSP_DFT_FORWARD); | |||
s->fftSetupBwd = aubio_vDSP_DFT_zrop_CreateSetup(s->fftSetupFwd, | |||
s->fft_size, vDSP_DFT_INVERSE); | |||
#elif defined HAVE_INTEL_IPP // using Intel IPP | |||
const IppHintAlgorithm qualityHint = ippAlgHintAccurate; // OR ippAlgHintFast; | |||
const int flags = IPP_FFT_NODIV_BY_ANY; // we're scaling manually afterwards | |||
int order = aubio_power_of_two_order(winsize); | |||
int sizeSpec, sizeInit, sizeBuffer; | |||
IppStatus status; | |||
if (winsize <= 4 || aubio_is_power_of_two(winsize) != 1) | |||
{ | |||
AUBIO_ERR("intel IPP fft: can only create with sizes > 4 and power of two, requested %d," | |||
" try recompiling aubio with --enable-fftw3\n", winsize); | |||
goto beach; | |||
} | |||
status = aubio_ippsFFTGetSize_R(order, flags, qualityHint, | |||
&sizeSpec, &sizeInit, &sizeBuffer); | |||
if (status != ippStsNoErr) { | |||
AUBIO_ERR("fft: failed to initialize fft. IPP error: %d\n", status); | |||
goto beach; | |||
} | |||
s->fft_size = s->winsize = winsize; | |||
s->compspec = new_fvec(winsize); | |||
s->in = AUBIO_ARRAY(smpl_t, s->winsize); | |||
s->out = AUBIO_ARRAY(smpl_t, s->winsize); | |||
s->memSpec = ippsMalloc_8u(sizeSpec); | |||
s->memBuffer = ippsMalloc_8u(sizeBuffer); | |||
if (sizeInit > 0 ) { | |||
s->memInit = ippsMalloc_8u(sizeInit); | |||
} | |||
s->complexOut = aubio_ippsMalloc_complex(s->fft_size / 2 + 1); | |||
status = aubio_ippsFFTInit_R( | |||
&s->fftSpec, order, flags, qualityHint, s->memSpec, s->memInit); | |||
if (status != ippStsNoErr) { | |||
AUBIO_ERR("fft: failed to initialize. IPP error: %d\n", status); | |||
goto beach; | |||
} | |||
#else // using OOURA | |||
if (aubio_is_power_of_two(winsize) != 1) { | |||
AUBIO_ERR("fft: can only create with sizes power of two, requested %d," | |||
" try recompiling aubio with --enable-fftw3\n", winsize); | |||
goto beach; | |||
} | |||
s->winsize = winsize; | |||
s->fft_size = winsize / 2 + 1; | |||
s->compspec = new_fvec(winsize); | |||
s->in = AUBIO_ARRAY(smpl_t, s->winsize); | |||
s->out = AUBIO_ARRAY(smpl_t, s->winsize); | |||
s->ip = AUBIO_ARRAY(int , s->fft_size); | |||
s->w = AUBIO_ARRAY(smpl_t, s->fft_size); | |||
s->ip[0] = 0; | |||
#endif /* using OOURA */ | |||
return s; | |||
beach: | |||
AUBIO_FREE(s); | |||
return NULL; | |||
} | |||
void del_aubio_fft(aubio_fft_t * s) { | |||
/* destroy data */ | |||
#ifdef HAVE_FFTW3 // using FFTW3 | |||
#ifndef __MOD_DEVICES__ | |||
pthread_mutex_lock(&aubio_fftw_mutex); | |||
#endif | |||
fftw_destroy_plan(s->pfw); | |||
fftw_destroy_plan(s->pbw); | |||
fftw_free(s->specdata); | |||
#ifndef __MOD_DEVICES__ | |||
pthread_mutex_unlock(&aubio_fftw_mutex); | |||
#endif | |||
#elif defined HAVE_ACCELERATE // using ACCELERATE | |||
AUBIO_FREE(s->spec.realp); | |||
AUBIO_FREE(s->spec.imagp); | |||
aubio_vDSP_DFT_DestroySetup(s->fftSetupBwd); | |||
aubio_vDSP_DFT_DestroySetup(s->fftSetupFwd); | |||
#elif defined HAVE_INTEL_IPP // using Intel IPP | |||
ippFree(s->memSpec); | |||
ippFree(s->memInit); | |||
ippFree(s->memBuffer); | |||
ippFree(s->complexOut); | |||
#else // using OOURA | |||
AUBIO_FREE(s->w); | |||
AUBIO_FREE(s->ip); | |||
#endif | |||
del_fvec(s->compspec); | |||
AUBIO_FREE(s->in); | |||
AUBIO_FREE(s->out); | |||
AUBIO_FREE(s); | |||
} | |||
void aubio_fft_do(aubio_fft_t * s, const fvec_t * input, cvec_t * spectrum) { | |||
aubio_fft_do_complex(s, input, s->compspec); | |||
aubio_fft_get_spectrum(s->compspec, spectrum); | |||
} | |||
void aubio_fft_rdo(aubio_fft_t * s, const cvec_t * spectrum, fvec_t * output) { | |||
aubio_fft_get_realimag(spectrum, s->compspec); | |||
aubio_fft_rdo_complex(s, s->compspec, output); | |||
} | |||
void aubio_fft_do_complex(aubio_fft_t * s, const fvec_t * input, fvec_t * compspec) { | |||
uint_t i; | |||
#ifndef HAVE_MEMCPY_HACKS | |||
for (i=0; i < s->winsize; i++) { | |||
s->in[i] = input->data[i]; | |||
} | |||
#else | |||
memcpy(s->in, input->data, s->winsize * sizeof(smpl_t)); | |||
#endif /* HAVE_MEMCPY_HACKS */ | |||
#ifdef HAVE_FFTW3 // using FFTW3 | |||
fftw_execute(s->pfw); | |||
#ifdef HAVE_COMPLEX_H | |||
compspec->data[0] = REAL(s->specdata[0]); | |||
for (i = 1; i < s->fft_size -1 ; i++) { | |||
compspec->data[i] = REAL(s->specdata[i]); | |||
compspec->data[compspec->length - i] = IMAG(s->specdata[i]); | |||
} | |||
compspec->data[s->fft_size-1] = REAL(s->specdata[s->fft_size-1]); | |||
#else /* HAVE_COMPLEX_H */ | |||
for (i = 0; i < s->fft_size; i++) { | |||
compspec->data[i] = s->specdata[i]; | |||
} | |||
#endif /* HAVE_COMPLEX_H */ | |||
#elif defined HAVE_ACCELERATE // using ACCELERATE | |||
// convert real data to even/odd format used in vDSP | |||
aubio_vDSP_ctoz((aubio_DSPComplex*)s->in, 2, &s->spec, 1, s->fft_size/2); | |||
// compute the FFT | |||
aubio_vDSP_DFT_Execute(s->fftSetupFwd, s->spec.realp, s->spec.imagp, | |||
s->spec.realp, s->spec.imagp); | |||
// convert from vDSP complex split to [ r0, r1, ..., rN, iN-1, .., i2, i1] | |||
compspec->data[0] = s->spec.realp[0]; | |||
compspec->data[s->fft_size / 2] = s->spec.imagp[0]; | |||
for (i = 1; i < s->fft_size / 2; i++) { | |||
compspec->data[i] = s->spec.realp[i]; | |||
compspec->data[s->fft_size - i] = s->spec.imagp[i]; | |||
} | |||
// apply scaling | |||
smpl_t scale = 1./2.; | |||
aubio_vDSP_vsmul(compspec->data, 1, &scale, compspec->data, 1, s->fft_size); | |||
#elif defined HAVE_INTEL_IPP // using Intel IPP | |||
// apply fft | |||
aubio_ippsFFTFwd_RToCCS(s->in, (aubio_IppFloat*)s->complexOut, s->fftSpec, s->memBuffer); | |||
// convert complex buffer to [ r0, r1, ..., rN, iN-1, .., i2, i1] | |||
compspec->data[0] = s->complexOut[0].re; | |||
compspec->data[s->fft_size / 2] = s->complexOut[s->fft_size / 2].re; | |||
for (i = 1; i < s->fft_size / 2; i++) { | |||
compspec->data[i] = s->complexOut[i].re; | |||
compspec->data[s->fft_size - i] = s->complexOut[i].im; | |||
} | |||
#else // using OOURA | |||
aubio_ooura_rdft(s->winsize, 1, s->in, s->ip, s->w); | |||
compspec->data[0] = s->in[0]; | |||
compspec->data[s->winsize / 2] = s->in[1]; | |||
for (i = 1; i < s->fft_size - 1; i++) { | |||
compspec->data[i] = s->in[2 * i]; | |||
compspec->data[s->winsize - i] = - s->in[2 * i + 1]; | |||
} | |||
#endif /* using OOURA */ | |||
} | |||
void aubio_fft_rdo_complex(aubio_fft_t * s, const fvec_t * compspec, fvec_t * output) { | |||
uint_t i; | |||
#ifdef HAVE_FFTW3 | |||
const smpl_t renorm = 1./(smpl_t)s->winsize; | |||
#ifdef HAVE_COMPLEX_H | |||
s->specdata[0] = compspec->data[0]; | |||
for (i=1; i < s->fft_size - 1; i++) { | |||
s->specdata[i] = compspec->data[i] + | |||
I * compspec->data[compspec->length - i]; | |||
} | |||
s->specdata[s->fft_size - 1] = compspec->data[s->fft_size - 1]; | |||
#else | |||
for (i=0; i < s->fft_size; i++) { | |||
s->specdata[i] = compspec->data[i]; | |||
} | |||
#endif | |||
fftw_execute(s->pbw); | |||
for (i = 0; i < output->length; i++) { | |||
output->data[i] = s->out[i]*renorm; | |||
} | |||
#elif defined HAVE_ACCELERATE // using ACCELERATE | |||
// convert from real imag [ r0, r1, ..., rN, iN-1, .., i2, i1] | |||
// to vDSP packed format [ r0, rN, r1, i1, ..., rN-1, iN-1 ] | |||
s->out[0] = compspec->data[0]; | |||
s->out[1] = compspec->data[s->winsize / 2]; | |||
for (i = 1; i < s->fft_size / 2; i++) { | |||
s->out[2 * i] = compspec->data[i]; | |||
s->out[2 * i + 1] = compspec->data[s->winsize - i]; | |||
} | |||
// convert to split complex format used in vDSP | |||
aubio_vDSP_ctoz((aubio_DSPComplex*)s->out, 2, &s->spec, 1, s->fft_size/2); | |||
// compute the FFT | |||
aubio_vDSP_DFT_Execute(s->fftSetupBwd, s->spec.realp, s->spec.imagp, | |||
s->spec.realp, s->spec.imagp); | |||
// convert result to real output | |||
aubio_vDSP_ztoc(&s->spec, 1, (aubio_DSPComplex*)output->data, 2, s->fft_size/2); | |||
// apply scaling | |||
smpl_t scale = 1.0 / s->winsize; | |||
aubio_vDSP_vsmul(output->data, 1, &scale, output->data, 1, s->fft_size); | |||
#elif defined HAVE_INTEL_IPP // using Intel IPP | |||
// convert from real imag [ r0, 0, ..., rN, iN-1, .., i2, i1, iN-1] to complex format | |||
s->complexOut[0].re = compspec->data[0]; | |||
s->complexOut[0].im = 0; | |||
s->complexOut[s->fft_size / 2].re = compspec->data[s->fft_size / 2]; | |||
s->complexOut[s->fft_size / 2].im = 0.0; | |||
for (i = 1; i < s->fft_size / 2; i++) { | |||
s->complexOut[i].re = compspec->data[i]; | |||
s->complexOut[i].im = compspec->data[s->fft_size - i]; | |||
} | |||
// apply fft | |||
aubio_ippsFFTInv_CCSToR((const aubio_IppFloat *)s->complexOut, output->data, s->fftSpec, s->memBuffer); | |||
// apply scaling | |||
aubio_ippsMulC(output->data, 1.0 / s->winsize, output->data, s->fft_size); | |||
#else // using OOURA | |||
smpl_t scale = 2.0 / s->winsize; | |||
s->out[0] = compspec->data[0]; | |||
s->out[1] = compspec->data[s->winsize / 2]; | |||
for (i = 1; i < s->fft_size - 1; i++) { | |||
s->out[2 * i] = compspec->data[i]; | |||
s->out[2 * i + 1] = - compspec->data[s->winsize - i]; | |||
} | |||
aubio_ooura_rdft(s->winsize, -1, s->out, s->ip, s->w); | |||
for (i=0; i < s->winsize; i++) { | |||
output->data[i] = s->out[i] * scale; | |||
} | |||
#endif | |||
} | |||
void aubio_fft_get_spectrum(const fvec_t * compspec, cvec_t * spectrum) { | |||
aubio_fft_get_phas(compspec, spectrum); | |||
aubio_fft_get_norm(compspec, spectrum); | |||
} | |||
void aubio_fft_get_realimag(const cvec_t * spectrum, fvec_t * compspec) { | |||
aubio_fft_get_imag(spectrum, compspec); | |||
aubio_fft_get_real(spectrum, compspec); | |||
} | |||
void aubio_fft_get_phas(const fvec_t * compspec, cvec_t * spectrum) { | |||
uint_t i; | |||
if (compspec->data[0] < 0) { | |||
spectrum->phas[0] = PI; | |||
} else { | |||
spectrum->phas[0] = 0.; | |||
} | |||
#if defined(HAVE_INTEL_IPP) | |||
// convert from real imag [ r0, r1, ..., rN, iN-1, ..., i2, i1, i0] | |||
// to [ r0, r1, ..., rN, i0, i1, i2, ..., iN-1] | |||
for (i = 1; i < spectrum->length / 2; i++) { | |||
ELEM_SWAP(compspec->data[compspec->length - i], | |||
compspec->data[spectrum->length + i - 1]); | |||
} | |||
aubio_ippsAtan2(compspec->data + spectrum->length, | |||
compspec->data + 1, spectrum->phas + 1, spectrum->length - 1); | |||
// revert the imaginary part back again | |||
for (i = 1; i < spectrum->length / 2; i++) { | |||
ELEM_SWAP(compspec->data[spectrum->length + i - 1], | |||
compspec->data[compspec->length - i]); | |||
} | |||
#else | |||
for (i=1; i < spectrum->length - 1; i++) { | |||
spectrum->phas[i] = ATAN2(compspec->data[compspec->length-i], | |||
compspec->data[i]); | |||
} | |||
#endif | |||
#ifdef HAVE_FFTW3 | |||
// for even length only, make sure last element is 0 or PI | |||
if (2 * (compspec->length / 2) == compspec->length) { | |||
#endif | |||
if (compspec->data[compspec->length/2] < 0) { | |||
spectrum->phas[spectrum->length - 1] = PI; | |||
} else { | |||
spectrum->phas[spectrum->length - 1] = 0.; | |||
} | |||
#ifdef HAVE_FFTW3 | |||
} else { | |||
i = spectrum->length - 1; | |||
spectrum->phas[i] = ATAN2(compspec->data[compspec->length-i], | |||
compspec->data[i]); | |||
} | |||
#endif | |||
} | |||
void aubio_fft_get_norm(const fvec_t * compspec, cvec_t * spectrum) { | |||
uint_t i = 0; | |||
spectrum->norm[0] = ABS(compspec->data[0]); | |||
for (i=1; i < spectrum->length - 1; i++) { | |||
spectrum->norm[i] = SQRT(SQR(compspec->data[i]) | |||
+ SQR(compspec->data[compspec->length - i]) ); | |||
} | |||
#ifdef HAVE_FFTW3 | |||
// for even length, make sure last element is > 0 | |||
if (2 * (compspec->length / 2) == compspec->length) { | |||
#endif | |||
spectrum->norm[spectrum->length-1] = | |||
ABS(compspec->data[compspec->length/2]); | |||
#ifdef HAVE_FFTW3 | |||
} else { | |||
i = spectrum->length - 1; | |||
spectrum->norm[i] = SQRT(SQR(compspec->data[i]) | |||
+ SQR(compspec->data[compspec->length - i]) ); | |||
} | |||
#endif | |||
} | |||
void aubio_fft_get_imag(const cvec_t * spectrum, fvec_t * compspec) { | |||
uint_t i; | |||
for (i = 1; i < ( compspec->length + 1 ) / 2 /*- 1 + 1*/; i++) { | |||
compspec->data[compspec->length - i] = | |||
spectrum->norm[i]*SIN(spectrum->phas[i]); | |||
} | |||
} | |||
void aubio_fft_get_real(const cvec_t * spectrum, fvec_t * compspec) { | |||
uint_t i; | |||
for (i = 0; i < compspec->length / 2 + 1; i++) { | |||
compspec->data[i] = | |||
spectrum->norm[i]*COS(spectrum->phas[i]); | |||
} | |||
} |
@@ -0,0 +1,144 @@ | |||
/* | |||
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** \file | |||
Fast Fourier Transform | |||
Depending on how aubio was compiled, FFT are computed using one of: | |||
- [Ooura](http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) | |||
- [FFTW3](http://www.fftw.org) | |||
- [vDSP](https://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/reference.html) | |||
\example spectral/test-fft.c | |||
*/ | |||
#ifndef AUBIO_FFT_H | |||
#define AUBIO_FFT_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** FFT object | |||
This object computes forward and backward FFTs. | |||
*/ | |||
typedef struct _aubio_fft_t aubio_fft_t; | |||
/** create new FFT computation object | |||
\param size length of the FFT | |||
*/ | |||
aubio_fft_t * new_aubio_fft (uint_t size); | |||
/** delete FFT object | |||
\param s fft object as returned by new_aubio_fft | |||
*/ | |||
void del_aubio_fft(aubio_fft_t * s); | |||
/** compute forward FFT | |||
\param s fft object as returned by new_aubio_fft | |||
\param input input signal | |||
\param spectrum output spectrum | |||
*/ | |||
void aubio_fft_do (aubio_fft_t *s, const fvec_t * input, cvec_t * spectrum); | |||
/** compute backward (inverse) FFT | |||
\param s fft object as returned by new_aubio_fft | |||
\param spectrum input spectrum | |||
\param output output signal | |||
*/ | |||
void aubio_fft_rdo (aubio_fft_t *s, const cvec_t * spectrum, fvec_t * output); | |||
/** compute forward FFT | |||
\param s fft object as returned by new_aubio_fft | |||
\param input real input signal | |||
\param compspec complex output fft real/imag | |||
*/ | |||
void aubio_fft_do_complex (aubio_fft_t *s, const fvec_t * input, fvec_t * compspec); | |||
/** compute backward (inverse) FFT from real/imag | |||
\param s fft object as returned by new_aubio_fft | |||
\param compspec real/imag input fft array | |||
\param output real output array | |||
*/ | |||
void aubio_fft_rdo_complex (aubio_fft_t *s, const fvec_t * compspec, fvec_t * output); | |||
/** convert real/imag spectrum to norm/phas spectrum | |||
\param compspec real/imag input fft array | |||
\param spectrum cvec norm/phas output array | |||
*/ | |||
void aubio_fft_get_spectrum(const fvec_t * compspec, cvec_t * spectrum); | |||
/** convert real/imag spectrum to norm/phas spectrum | |||
\param compspec real/imag input fft array | |||
\param spectrum cvec norm/phas output array | |||
*/ | |||
void aubio_fft_get_realimag(const cvec_t * spectrum, fvec_t * compspec); | |||
/** compute phas spectrum from real/imag parts | |||
\param compspec real/imag input fft array | |||
\param spectrum cvec norm/phas output array | |||
*/ | |||
void aubio_fft_get_phas(const fvec_t * compspec, cvec_t * spectrum); | |||
/** compute imaginary part from the norm/phas cvec | |||
\param spectrum norm/phas input array | |||
\param compspec real/imag output fft array | |||
*/ | |||
void aubio_fft_get_imag(const cvec_t * spectrum, fvec_t * compspec); | |||
/** compute norm component from real/imag parts | |||
\param compspec real/imag input fft array | |||
\param spectrum cvec norm/phas output array | |||
*/ | |||
void aubio_fft_get_norm(const fvec_t * compspec, cvec_t * spectrum); | |||
/** compute real part from norm/phas components | |||
\param spectrum norm/phas input array | |||
\param compspec real/imag output fft array | |||
*/ | |||
void aubio_fft_get_real(const cvec_t * spectrum, fvec_t * compspec); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_FFT_H */ |
@@ -0,0 +1,224 @@ | |||
/* | |||
Copyright (C) 2003-2014 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "cvec.h" | |||
#include "mathutils.h" | |||
#include "spectral/fft.h" | |||
#include "spectral/phasevoc.h" | |||
/** phasevocoder internal object */ | |||
struct _aubio_pvoc_t { | |||
uint_t win_s; /** grain length */ | |||
uint_t hop_s; /** overlap step */ | |||
aubio_fft_t * fft; /** fft object */ | |||
fvec_t * data; /** current input grain, [win_s] frames */ | |||
fvec_t * dataold; /** memory of past grain, [win_s-hop_s] frames */ | |||
fvec_t * synth; /** current output grain, [win_s] frames */ | |||
fvec_t * synthold; /** memory of past grain, [win_s-hop_s] frames */ | |||
fvec_t * w; /** grain window [win_s] */ | |||
uint_t start; /** where to start additive synthesis */ | |||
uint_t end; /** where to end it */ | |||
smpl_t scale; /** scaling factor for synthesis */ | |||
uint_t end_datasize; /** size of memory to end */ | |||
uint_t hop_datasize; /** size of memory to hop_s */ | |||
}; | |||
/** returns data and dataold slided by hop_s */ | |||
static void aubio_pvoc_swapbuffers(aubio_pvoc_t *pv, const fvec_t *new); | |||
/** do additive synthesis from 'old' and 'cur' */ | |||
static void aubio_pvoc_addsynth(aubio_pvoc_t *pv, fvec_t * synthnew); | |||
void aubio_pvoc_do(aubio_pvoc_t *pv, const fvec_t * datanew, cvec_t *fftgrain) { | |||
/* slide */ | |||
aubio_pvoc_swapbuffers(pv, datanew); | |||
/* windowing */ | |||
fvec_weight(pv->data, pv->w); | |||
/* shift */ | |||
fvec_shift(pv->data); | |||
/* calculate fft */ | |||
aubio_fft_do (pv->fft,pv->data,fftgrain); | |||
} | |||
void aubio_pvoc_rdo(aubio_pvoc_t *pv,cvec_t * fftgrain, fvec_t * synthnew) { | |||
/* calculate rfft */ | |||
aubio_fft_rdo(pv->fft,fftgrain,pv->synth); | |||
/* unshift */ | |||
fvec_ishift(pv->synth); | |||
/* windowing */ | |||
// if overlap = 50%, do not apply window (identity) | |||
if (pv->hop_s * 2 < pv->win_s) { | |||
fvec_weight(pv->synth, pv->w); | |||
} | |||
/* additive synthesis */ | |||
aubio_pvoc_addsynth(pv, synthnew); | |||
} | |||
aubio_pvoc_t * new_aubio_pvoc (uint_t win_s, uint_t hop_s) { | |||
aubio_pvoc_t * pv = AUBIO_NEW(aubio_pvoc_t); | |||
/* if (win_s < 2*hop_s) { | |||
AUBIO_WRN("Hop size bigger than half the window size!\n"); | |||
} */ | |||
if ((sint_t)hop_s < 1) { | |||
AUBIO_ERR("pvoc: got hop_size %d, but can not be < 1\n", hop_s); | |||
goto beach; | |||
} else if ((sint_t)win_s < 2) { | |||
AUBIO_ERR("pvoc: got buffer_size %d, but can not be < 2\n", win_s); | |||
goto beach; | |||
} else if (win_s < hop_s) { | |||
AUBIO_ERR("pvoc: hop size (%d) is larger than win size (%d)\n", hop_s, win_s); | |||
goto beach; | |||
} | |||
pv->fft = new_aubio_fft (win_s); | |||
if (pv->fft == NULL) { | |||
goto beach; | |||
} | |||
/* remember old */ | |||
pv->data = new_fvec (win_s); | |||
pv->synth = new_fvec (win_s); | |||
/* new input output */ | |||
if (win_s > hop_s) { | |||
pv->dataold = new_fvec (win_s-hop_s); | |||
pv->synthold = new_fvec (win_s-hop_s); | |||
} else { | |||
pv->dataold = new_fvec (1); | |||
pv->synthold = new_fvec (1); | |||
} | |||
pv->w = new_aubio_window ("hanningz", win_s); | |||
pv->hop_s = hop_s; | |||
pv->win_s = win_s; | |||
/* more than 50% overlap, overlap anyway */ | |||
if (win_s < 2 * hop_s) pv->start = 0; | |||
/* less than 50% overlap, reset latest grain trail */ | |||
else pv->start = win_s - hop_s - hop_s; | |||
if (win_s > hop_s) pv->end = win_s - hop_s; | |||
else pv->end = 0; | |||
pv->end_datasize = pv->end * sizeof(smpl_t); | |||
pv->hop_datasize = pv->hop_s * sizeof(smpl_t); | |||
// for reconstruction with 75% overlap | |||
if (win_s == hop_s * 4) { | |||
pv->scale = 2./3.; | |||
} else if (win_s == hop_s * 8) { | |||
pv->scale = 1./3.; | |||
} else if (win_s == hop_s * 2) { | |||
pv->scale = 1.; | |||
} else { | |||
pv->scale = .5; | |||
} | |||
return pv; | |||
beach: | |||
AUBIO_FREE (pv); | |||
return NULL; | |||
} | |||
uint_t aubio_pvoc_set_window(aubio_pvoc_t *pv, const char_t *window) { | |||
return fvec_set_window(pv->w, (char_t*)window); | |||
} | |||
void del_aubio_pvoc(aubio_pvoc_t *pv) { | |||
del_fvec(pv->data); | |||
del_fvec(pv->synth); | |||
del_fvec(pv->dataold); | |||
del_fvec(pv->synthold); | |||
del_fvec(pv->w); | |||
del_aubio_fft(pv->fft); | |||
AUBIO_FREE(pv); | |||
} | |||
static void aubio_pvoc_swapbuffers(aubio_pvoc_t *pv, const fvec_t *new) | |||
{ | |||
/* some convenience pointers */ | |||
smpl_t * data = pv->data->data; | |||
smpl_t * dataold = pv->dataold->data; | |||
smpl_t * datanew = new->data; | |||
#ifndef HAVE_MEMCPY_HACKS | |||
uint_t i; | |||
for (i = 0; i < pv->end; i++) | |||
data[i] = dataold[i]; | |||
for (i = 0; i < pv->hop_s; i++) | |||
data[pv->end + i] = datanew[i]; | |||
for (i = 0; i < pv->end; i++) | |||
dataold[i] = data[i + pv->hop_s]; | |||
#else | |||
memcpy(data, dataold, pv->end_datasize); | |||
data += pv->end; | |||
memcpy(data, datanew, pv->hop_datasize); | |||
data -= pv->end; | |||
data += pv->hop_s; | |||
memcpy(dataold, data, pv->end_datasize); | |||
#endif | |||
} | |||
static void aubio_pvoc_addsynth(aubio_pvoc_t *pv, fvec_t *synth_new) | |||
{ | |||
uint_t i; | |||
/* some convenience pointers */ | |||
smpl_t * synth = pv->synth->data; | |||
smpl_t * synthold = pv->synthold->data; | |||
smpl_t * synthnew = synth_new->data; | |||
/* put new result in synthnew */ | |||
for (i = 0; i < pv->hop_s; i++) | |||
synthnew[i] = synth[i] * pv->scale; | |||
/* no overlap, nothing else to do */ | |||
if (pv->end == 0) return; | |||
/* add new synth to old one */ | |||
for (i = 0; i < pv->hop_s; i++) | |||
synthnew[i] += synthold[i]; | |||
/* shift synthold */ | |||
for (i = 0; i < pv->start; i++) | |||
synthold[i] = synthold[i + pv->hop_s]; | |||
/* erase last frame in synthold */ | |||
for (i = pv->start; i < pv->end; i++) | |||
synthold[i] = 0.; | |||
/* additive synth */ | |||
for (i = 0; i < pv->end; i++) | |||
synthold[i] += synth[i + pv->hop_s] * pv->scale; | |||
} | |||
uint_t aubio_pvoc_get_win(aubio_pvoc_t* pv) | |||
{ | |||
return pv->win_s; | |||
} | |||
uint_t aubio_pvoc_get_hop(aubio_pvoc_t* pv) | |||
{ | |||
return pv->hop_s; | |||
} |
@@ -0,0 +1,113 @@ | |||
/* | |||
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/** \file | |||
Phase vocoder object | |||
This object implements a phase vocoder. The spectral frames are computed | |||
using a HanningZ window and a swapped version of the signal to simplify the | |||
phase relationships across frames. The window sizes and overlap are specified | |||
at creation time. | |||
\example spectral/test-phasevoc.c | |||
*/ | |||
#ifndef AUBIO_PHASEVOC_H | |||
#define AUBIO_PHASEVOC_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** phasevocoder object */ | |||
typedef struct _aubio_pvoc_t aubio_pvoc_t; | |||
/** create phase vocoder object | |||
\param win_s size of analysis buffer (and length the FFT transform) | |||
\param hop_s step size between two consecutive analysis | |||
*/ | |||
aubio_pvoc_t * new_aubio_pvoc (uint_t win_s, uint_t hop_s); | |||
/** delete phase vocoder object | |||
\param pv phase vocoder object as returned by new_aubio_pvoc | |||
*/ | |||
void del_aubio_pvoc(aubio_pvoc_t *pv); | |||
/** compute spectral frame | |||
This function accepts an input vector of size [hop_s]. The | |||
analysis buffer is rotated and filled with the new data. After windowing of | |||
this signal window, the Fourier transform is computed and returned in | |||
fftgrain as two vectors, magnitude and phase. | |||
\param pv phase vocoder object as returned by new_aubio_pvoc | |||
\param in new input signal (hop_s long) | |||
\param fftgrain output spectral frame | |||
*/ | |||
void aubio_pvoc_do(aubio_pvoc_t *pv, const fvec_t *in, cvec_t * fftgrain); | |||
/** compute signal from spectral frame | |||
This function takes an input spectral frame fftgrain of size | |||
[buf_s] and computes its inverse Fourier transform. Overlap-add | |||
synthesis is then computed using the previously synthetised frames, and the | |||
output stored in out. | |||
\param pv phase vocoder object as returned by new_aubio_pvoc | |||
\param fftgrain input spectral frame | |||
\param out output signal (hop_s long) | |||
*/ | |||
void aubio_pvoc_rdo(aubio_pvoc_t *pv, cvec_t * fftgrain, fvec_t *out); | |||
/** get window size | |||
\param pv phase vocoder to get the window size from | |||
*/ | |||
uint_t aubio_pvoc_get_win(aubio_pvoc_t* pv); | |||
/** get hop size | |||
\param pv phase vocoder to get the hop size from | |||
*/ | |||
uint_t aubio_pvoc_get_hop(aubio_pvoc_t* pv); | |||
/** set window type | |||
\param pv phase vocoder to set the window type | |||
\param window_type a string representing a window | |||
\return 0 if successful, non-zero otherwise | |||
*/ | |||
uint_t aubio_pvoc_set_window(aubio_pvoc_t *pv, const char_t *window_type); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_PHASEVOC_H */ |
@@ -0,0 +1,262 @@ | |||
/* | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "types.h" | |||
#include "fvec.h" | |||
#include "lvec.h" | |||
#include "temporal/filter.h" | |||
#include "temporal/a_weighting.h" | |||
uint_t | |||
aubio_filter_set_a_weighting (aubio_filter_t * f, uint_t samplerate) | |||
{ | |||
uint_t order; lsmp_t *a, *b; lvec_t *as, *bs; | |||
if ((sint_t)samplerate <= 0) { | |||
AUBIO_ERROR("aubio_filter: failed setting A-weighting with samplerate %d\n", samplerate); | |||
return AUBIO_FAIL; | |||
} | |||
if (f == NULL) { | |||
AUBIO_ERROR("aubio_filter: failed setting A-weighting with filter NULL\n"); | |||
return AUBIO_FAIL; | |||
} | |||
order = aubio_filter_get_order (f); | |||
if (order != 7) { | |||
AUBIO_ERROR ("aubio_filter: order of A-weighting filter must be 7, not %d\n", order); | |||
return 1; | |||
} | |||
aubio_filter_set_samplerate (f, samplerate); | |||
bs = aubio_filter_get_feedforward (f); | |||
as = aubio_filter_get_feedback (f); | |||
b = bs->data, a = as->data; | |||
/* select coefficients according to sampling frequency */ | |||
switch (samplerate) { | |||
case 8000: | |||
b[0] = 6.306209468238731519207362907764036208391189575195312500e-01; | |||
b[1] = -1.261241893647746525886077506584115326404571533203125000e+00; | |||
b[2] = -6.306209468238730408984338282607495784759521484375000000e-01; | |||
b[3] = 2.522483787295493051772155013168230652809143066406250000e+00; | |||
b[4] = -6.306209468238730408984338282607495784759521484375000000e-01; | |||
b[5] = -1.261241893647746525886077506584115326404571533203125000e+00; | |||
b[6] = 6.306209468238731519207362907764036208391189575195312500e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -2.128467193009123015201566886389628052711486816406250000e+00; | |||
a[2] = 2.948668980101234460278192273108288645744323730468750000e-01; | |||
a[3] = 1.824183830735050637628091863007284700870513916015625000e+00; | |||
a[4] = -8.056628943119792385374466903158463537693023681640625000e-01; | |||
a[5] = -3.947497982842933517133587884018197655677795410156250000e-01; | |||
a[6] = 2.098548546080332977137317129745497368276119232177734375e-01; | |||
break; | |||
case 11025: | |||
b[0] = 6.014684165832374640459079273568931967020034790039062500e-01; | |||
b[1] = -1.202936833166475150136420779745094478130340576171875000e+00; | |||
b[2] = -6.014684165832373530236054648412391543388366699218750000e-01; | |||
b[3] = 2.405873666332950300272841559490188956260681152343750000e+00; | |||
b[4] = -6.014684165832373530236054648412391543388366699218750000e-01; | |||
b[5] = -1.202936833166475150136420779745094478130340576171875000e+00; | |||
b[6] = 6.014684165832374640459079273568931967020034790039062500e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -2.463578747722854345170162559952586889266967773437500000e+00; | |||
a[2] = 1.096799662705210121060872552334330976009368896484375000e+00; | |||
a[3] = 1.381222210556041218865175324026495218276977539062500000e+00; | |||
a[4] = -1.013875696476876031582037285261321812868118286132812500e+00; | |||
a[5] = -1.839132734476921215982514468123554252088069915771484375e-01; | |||
a[6] = 1.833526393172056623281918064094497822225093841552734375e-01; | |||
break; | |||
case 16000: | |||
b[0] = 5.314898298235570806014038680586963891983032226562500000e-01; | |||
b[1] = -1.062979659647114161202807736117392778396606445312500000e+00; | |||
b[2] = -5.314898298235570806014038680586963891983032226562500000e-01; | |||
b[3] = 2.125959319294228322405615472234785556793212890625000000e+00; | |||
b[4] = -5.314898298235570806014038680586963891983032226562500000e-01; | |||
b[5] = -1.062979659647114161202807736117392778396606445312500000e+00; | |||
b[6] = 5.314898298235570806014038680586963891983032226562500000e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -2.867832572992162987191022693878039717674255371093750000e+00; | |||
a[2] = 2.221144410202312347024644623161293566226959228515625000e+00; | |||
a[3] = 4.552683347886614662058946123579517006874084472656250000e-01; | |||
a[4] = -9.833868636162828025248927588108927011489868164062500000e-01; | |||
a[5] = 5.592994142413361402521587706360151059925556182861328125e-02; | |||
a[6] = 1.188781038285612462468421313133148942142724990844726562e-01; | |||
break; | |||
case 22050: | |||
b[0] = 4.492998504299193784916610638902056962251663208007812500e-01; | |||
b[1] = -8.985997008598388680056245902960654348134994506835937500e-01; | |||
b[2] = -4.492998504299192674693586013745516538619995117187500000e-01; | |||
b[3] = 1.797199401719677958055854105623438954353332519531250000e+00; | |||
b[4] = -4.492998504299192674693586013745516538619995117187500000e-01; | |||
b[5] = -8.985997008598388680056245902960654348134994506835937500e-01; | |||
b[6] = 4.492998504299193784916610638902056962251663208007812500e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -3.229078805225074955131958631682209670543670654296875000e+00; | |||
a[2] = 3.354494881236033787530459449044428765773773193359375000e+00; | |||
a[3] = -7.317843680657351024265722116979304701089859008789062500e-01; | |||
a[4] = -6.271627581807257545420952737913466989994049072265625000e-01; | |||
a[5] = 1.772142005020879151899748649157118052244186401367187500e-01; | |||
a[6] = 5.631716697383508385410522123493137769401073455810546875e-02; | |||
break; | |||
case 24000: | |||
b[0] = 4.256263892891054001488271296693710610270500183105468750e-01; | |||
b[1] = -8.512527785782106892753517968230880796909332275390625000e-01; | |||
b[2] = -4.256263892891054556599783609271980822086334228515625000e-01; | |||
b[3] = 1.702505557156421378550703593646176159381866455078125000e+00; | |||
b[4] = -4.256263892891054556599783609271980822086334228515625000e-01; | |||
b[5] = -8.512527785782106892753517968230880796909332275390625000e-01; | |||
b[6] = 4.256263892891054001488271296693710610270500183105468750e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -3.325996004241962733516402295208536088466644287109375000e+00; | |||
a[2] = 3.677161079286316969216841243905946612358093261718750000e+00; | |||
a[3] = -1.106476076828482035807610373012721538543701171875000000e+00; | |||
a[4] = -4.726706734908718843257702246773988008499145507812500000e-01; | |||
a[5] = 1.861941760230954034938122276798821985721588134765625000e-01; | |||
a[6] = 4.178771337829546850262119050967157818377017974853515625e-02; | |||
break; | |||
case 32000: | |||
b[0] = 3.434583386824304196416335344110848382115364074707031250e-01; | |||
b[1] = -6.869166773648609503055695313378237187862396240234375000e-01; | |||
b[2] = -3.434583386824303641304823031532578170299530029296875000e-01; | |||
b[3] = 1.373833354729721900611139062675647437572479248046875000e+00; | |||
b[4] = -3.434583386824303641304823031532578170299530029296875000e-01; | |||
b[5] = -6.869166773648609503055695313378237187862396240234375000e-01; | |||
b[6] = 3.434583386824304196416335344110848382115364074707031250e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -3.656446043233668063976438133977353572845458984375000000e+00; | |||
a[2] = 4.831468450652579349480220116674900054931640625000000000e+00; | |||
a[3] = -2.557597496581567764195597192156128585338592529296875000e+00; | |||
a[4] = 2.533680394205302666144064005493419244885444641113281250e-01; | |||
a[5] = 1.224430322452567110325105659285327419638633728027343750e-01; | |||
a[6] = 6.764072168342137418572956875095769646577537059783935547e-03; | |||
break; | |||
case 44100: | |||
b[0] = 2.557411252042575133813784304948057979345321655273437500e-01; | |||
b[1] = -5.114822504085150267627568609896115958690643310546875000e-01; | |||
b[2] = -2.557411252042575133813784304948057979345321655273437500e-01; | |||
b[3] = 1.022964500817030053525513721979223191738128662109375000e+00; | |||
b[4] = -2.557411252042575133813784304948057979345321655273437500e-01; | |||
b[5] = -5.114822504085150267627568609896115958690643310546875000e-01; | |||
b[6] = 2.557411252042575133813784304948057979345321655273437500e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -4.019576181115832369528106937650591135025024414062500000e+00; | |||
a[2] = 6.189406442920693862674852425698190927505493164062500000e+00; | |||
a[3] = -4.453198903544116404873420833609998226165771484375000000e+00; | |||
a[4] = 1.420842949621876627475103305187076330184936523437500000e+00; | |||
a[5] = -1.418254738303044160119270600262098014354705810546875000e-01; | |||
a[6] = 4.351177233495117681327801761881346465088427066802978516e-03; | |||
break; | |||
case 48000: | |||
b[0] = 2.343017922995132285013397677175817079842090606689453125e-01; | |||
b[1] = -4.686035845990265125138307666929904371500015258789062500e-01; | |||
b[2] = -2.343017922995132007457641520886681973934173583984375000e-01; | |||
b[3] = 9.372071691980530250276615333859808743000030517578125000e-01; | |||
b[4] = -2.343017922995132007457641520886681973934173583984375000e-01; | |||
b[5] = -4.686035845990265125138307666929904371500015258789062500e-01; | |||
b[6] = 2.343017922995132285013397677175817079842090606689453125e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -4.113043408775872045168853219365701079368591308593750000e+00; | |||
a[2] = 6.553121752655050258340452273841947317123413085937500000e+00; | |||
a[3] = -4.990849294163385074796224216697737574577331542968750000e+00; | |||
a[4] = 1.785737302937575599059982778271660208702087402343750000e+00; | |||
a[5] = -2.461905953194876706113802811159985139966011047363281250e-01; | |||
a[6] = 1.122425003323123879339640041052916785702109336853027344e-02; | |||
break; | |||
case 88200: | |||
b[0] = 1.118876366882113199130444058937428053468465805053710938e-01; | |||
b[1] = -2.237752733764226120705131961585721001029014587402343750e-01; | |||
b[2] = -1.118876366882113337908322137081995606422424316406250000e-01; | |||
b[3] = 4.475505467528452241410263923171442002058029174804687500e-01; | |||
b[4] = -1.118876366882113337908322137081995606422424316406250000e-01; | |||
b[5] = -2.237752733764226120705131961585721001029014587402343750e-01; | |||
b[6] = 1.118876366882113199130444058937428053468465805053710938e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -4.726938565651158441482948546763509511947631835937500000e+00; | |||
a[2] = 9.076897983832765248735086061060428619384765625000000000e+00; | |||
a[3] = -9.014855113464800950850985827855765819549560546875000000e+00; | |||
a[4] = 4.852772261031594425162438710685819387435913085937500000e+00; | |||
a[5] = -1.333877820398965186043938047077972441911697387695312500e+00; | |||
a[6] = 1.460012549591642450064199465487035922706127166748046875e-01; | |||
break; | |||
case 96000: | |||
b[0] = 9.951898975972744976203898659150581806898117065429687500e-02; | |||
b[1] = -1.990379795194548995240779731830116361379623413085937500e-01; | |||
b[2] = -9.951898975972744976203898659150581806898117065429687500e-02; | |||
b[3] = 3.980759590389097990481559463660232722759246826171875000e-01; | |||
b[4] = -9.951898975972744976203898659150581806898117065429687500e-02; | |||
b[5] = -1.990379795194548995240779731830116361379623413085937500e-01; | |||
b[6] = 9.951898975972744976203898659150581806898117065429687500e-02; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -4.802203044225376693532325589330866932868957519531250000e+00; | |||
a[2] = 9.401807218627226347962277941405773162841796875000000000e+00; | |||
a[3] = -9.566143943569164420637207513209432363510131835937500000e+00; | |||
a[4] = 5.309775930392619081032989925006404519081115722656250000e+00; | |||
a[5] = -1.517333360452622237346531619550660252571105957031250000e+00; | |||
a[6] = 1.740971994228911745583587844521389342844486236572265625e-01; | |||
break; | |||
case 192000: | |||
b[0] = 3.433213424548713782469278044118254911154508590698242188e-02; | |||
b[1] = -6.866426849097426177159775306790834292769432067871093750e-02; | |||
b[2] = -3.433213424548714476358668434841092675924301147460937500e-02; | |||
b[3] = 1.373285369819485235431955061358166858553886413574218750e-01; | |||
b[4] = -3.433213424548714476358668434841092675924301147460937500e-02; | |||
b[5] = -6.866426849097426177159775306790834292769432067871093750e-02; | |||
b[6] = 3.433213424548713782469278044118254911154508590698242188e-02; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -5.305923689674640009172890131594613194465637207031250000e+00; | |||
a[2] = 1.165952437466175695135461864992976188659667968750000000e+01; | |||
a[3] = -1.357560092700591525272102444432675838470458984375000000e+01; | |||
a[4] = 8.828906932824192921316353022120893001556396484375000000e+00; | |||
a[5] = -3.039490120988216581565666274400427937507629394531250000e+00; | |||
a[6] = 4.325834301870381537469256727490574121475219726562500000e-01; | |||
break; | |||
default: | |||
AUBIO_ERROR ("sampling rate of A-weighting filter is %d, should be one of\ | |||
8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, 192000.\n", samplerate); | |||
return 1; | |||
} | |||
return 0; | |||
} | |||
aubio_filter_t * | |||
new_aubio_filter_a_weighting (uint_t samplerate) | |||
{ | |||
aubio_filter_t *f = new_aubio_filter (7); | |||
if (aubio_filter_set_a_weighting(f,samplerate) != AUBIO_OK) { | |||
del_aubio_filter(f); | |||
return NULL; | |||
} | |||
return f; | |||
} |
@@ -0,0 +1,88 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef AUBIO_FILTER_A_DESIGN_H | |||
#define AUBIO_FILTER_A_DESIGN_H | |||
/** \file | |||
A-weighting filter coefficients | |||
This file creates an A-weighting digital filter, which reduces low and high | |||
frequencies and enhance the middle ones to reflect the ability of the human | |||
hearing. | |||
The implementation is based on the following standard: | |||
- IEC/CD 1672: Electroacoustics-Sound Level Meters, IEC, Geneva, Nov. 1996, | |||
for A- and C-weighting filters. | |||
See also: | |||
- <a href="http://en.wikipedia.org/wiki/A-weighting">A-Weighting on | |||
Wikipedia</a> | |||
- <a href="http://en.wikipedia.org/wiki/Weighting_filter">Weighting filter on | |||
Wikipedia</a> | |||
- <a href="http://www.mathworks.com/matlabcentral/fileexchange/69">Christophe | |||
Couvreur's 'octave' toolbox</a> | |||
The coefficients in this file have been computed using Christophe Couvreur's | |||
scripts in octave 3.0 (debian package 1:3.0.5-6+b2 with octave-signal | |||
1.0.9-1+b1 on i386), with <pre> [b, a] = adsign(1/Fs) </pre> for various | |||
sampling frequencies (8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, | |||
88200, 96000, and 192000 Hz). | |||
The sampling frequency should normally be higher than 20kHz, but most common | |||
file sampling rates have been included for completeness. | |||
\example temporal/test-a_weighting.c | |||
*/ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** create new A-design filter | |||
\param samplerate sampling frequency of the signal to filter. Should be one of | |||
8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, and | |||
192000 Hz | |||
\return a new filter object | |||
*/ | |||
aubio_filter_t *new_aubio_filter_a_weighting (uint_t samplerate); | |||
/** set feedback and feedforward coefficients of a A-weighting filter | |||
\param f filter object to get coefficients from | |||
\param samplerate sampling frequency of the signal to filter. Should be one of | |||
8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, and | |||
192000 Hz | |||
*/ | |||
uint_t aubio_filter_set_a_weighting (aubio_filter_t * f, uint_t samplerate); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_FILTER_A_DESIGN_H */ |
@@ -0,0 +1,54 @@ | |||
/* | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "lvec.h" | |||
#include "temporal/filter.h" | |||
#include "temporal/biquad.h" | |||
uint_t | |||
aubio_filter_set_biquad (aubio_filter_t * f, lsmp_t b0, lsmp_t b1, lsmp_t b2, | |||
lsmp_t a1, lsmp_t a2) | |||
{ | |||
uint_t order = aubio_filter_get_order (f); | |||
lvec_t *bs = aubio_filter_get_feedforward (f); | |||
lvec_t *as = aubio_filter_get_feedback (f); | |||
if (order != 3) { | |||
AUBIO_ERROR ("order of biquad filter must be 3, not %d\n", order); | |||
return AUBIO_FAIL; | |||
} | |||
bs->data[0] = b0; | |||
bs->data[1] = b1; | |||
bs->data[2] = b2; | |||
as->data[0] = 1.; | |||
as->data[1] = a1; | |||
as->data[2] = a2; | |||
return AUBIO_OK; | |||
} | |||
aubio_filter_t * | |||
new_aubio_filter_biquad (lsmp_t b0, lsmp_t b1, lsmp_t b2, lsmp_t a1, lsmp_t a2) | |||
{ | |||
aubio_filter_t *f = new_aubio_filter (3); | |||
aubio_filter_set_biquad (f, b0, b1, b2, a1, a2); | |||
return f; | |||
} |
@@ -0,0 +1,75 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef AUBIO_FILTER_BIQUAD_H | |||
#define AUBIO_FILTER_BIQUAD_H | |||
/** \file | |||
Second order Infinite Impulse Response filter | |||
This file implements a normalised biquad filter (second order IIR): | |||
\f$ y[n] = b_0 x[n] + b_1 x[n-1] + b_2 x[n-2] - a_1 y[n-1] - a_2 y[n-2] \f$ | |||
The filtfilt version runs the filter twice, forward and backward, to | |||
compensate the phase shifting of the forward operation. | |||
See also <a href="http://en.wikipedia.org/wiki/Digital_biquad_filter">Digital | |||
biquad filter</a> on wikipedia. | |||
\example temporal/test-biquad.c | |||
*/ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** set coefficients of a biquad filter | |||
\param f filter object as returned by new_aubio_filter() | |||
\param b0 forward filter coefficient | |||
\param b1 forward filter coefficient | |||
\param b2 forward filter coefficient | |||
\param a1 feedback filter coefficient | |||
\param a2 feedback filter coefficient | |||
*/ | |||
uint_t aubio_filter_set_biquad (aubio_filter_t * f, lsmp_t b0, lsmp_t b1, | |||
lsmp_t b2, lsmp_t a1, lsmp_t a2); | |||
/** create biquad filter with `b0`, `b1`, `b2`, `a1`, `a2` coeffs | |||
\param b0 forward filter coefficient | |||
\param b1 forward filter coefficient | |||
\param b2 forward filter coefficient | |||
\param a1 feedback filter coefficient | |||
\param a2 feedback filter coefficient | |||
*/ | |||
aubio_filter_t *new_aubio_filter_biquad (lsmp_t b0, lsmp_t b1, lsmp_t b2, | |||
lsmp_t a1, lsmp_t a2); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_FILTER_BIQUAD_H */ |
@@ -0,0 +1,217 @@ | |||
/* | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "types.h" | |||
#include "fvec.h" | |||
#include "lvec.h" | |||
#include "temporal/filter.h" | |||
#include "temporal/c_weighting.h" | |||
uint_t | |||
aubio_filter_set_c_weighting (aubio_filter_t * f, uint_t samplerate) | |||
{ | |||
uint_t order; lsmp_t *a, *b; lvec_t *as, *bs; | |||
if ((sint_t)samplerate <= 0) { | |||
AUBIO_ERROR("aubio_filter: failed setting C-weighting with samplerate %d\n", samplerate); | |||
return AUBIO_FAIL; | |||
} | |||
if (f == NULL) { | |||
AUBIO_ERROR("aubio_filter: failed setting C-weighting with filter NULL\n"); | |||
return AUBIO_FAIL; | |||
} | |||
order = aubio_filter_get_order (f); | |||
if ( order != 5 ) { | |||
AUBIO_ERROR ("aubio_filter: order of C-weighting filter must be 5, not %d\n", order); | |||
return 1; | |||
} | |||
aubio_filter_set_samplerate (f, samplerate); | |||
bs = aubio_filter_get_feedforward (f); | |||
as = aubio_filter_get_feedback (f); | |||
b = bs->data, a = as->data; | |||
/* select coefficients according to sampling frequency */ | |||
switch (samplerate) { | |||
case 8000: | |||
b[0] = 6.782173932405135552414776611840352416038513183593750000e-01; | |||
b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[2] = -1.356434786481027110482955322368070483207702636718750000e+00; | |||
b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[4] = 6.782173932405135552414776611840352416038513183593750000e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -6.589092811505605773447769024642184376716613769531250000e-01; | |||
a[2] = -1.179445664897062595599663836765103042125701904296875000e+00; | |||
a[3] = 4.243329729632123736848825501510873436927795410156250000e-01; | |||
a[4] = 4.147270002091348328754349950031610205769538879394531250e-01; | |||
break; | |||
case 11025: | |||
b[0] = 6.002357155402652244546857218665536493062973022460937500e-01; | |||
b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[2] = -1.200471431080530448909371443733107298612594604492187500e+00; | |||
b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[4] = 6.002357155402652244546857218665536493062973022460937500e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -8.705602141280316397242700077185872942209243774414062500e-01; | |||
a[2] = -9.037199507150940336330791069485712796449661254882812500e-01; | |||
a[3] = 4.758433040929530011275971901341108605265617370605468750e-01; | |||
a[4] = 2.987653956523212417373258631414500996470451354980468750e-01; | |||
break; | |||
case 16000: | |||
b[0] = 4.971057193673903418229542694461997598409652709960937500e-01; | |||
b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[2] = -9.942114387347806836459085388923995196819305419921875000e-01; | |||
b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[4] = 4.971057193673903418229542694461997598409652709960937500e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -1.162322939286873690889478893950581550598144531250000000e+00; | |||
a[2] = -4.771961355734982701548574368644040077924728393554687500e-01; | |||
a[3] = 4.736145114694704227886745684372726827859878540039062500e-01; | |||
a[4] = 1.660337524309875301131711466950946487486362457275390625e-01; | |||
break; | |||
case 22050: | |||
b[0] = 4.033381299002754549754001800465630367398262023925781250e-01; | |||
b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[2] = -8.066762598005509099508003600931260734796524047851562500e-01; | |||
b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[4] = 4.033381299002754549754001800465630367398262023925781250e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -1.449545371157945350404361306573264300823211669921875000e+00; | |||
a[2] = -1.030104190885922088583015465701464563608169555664062500e-02; | |||
a[3] = 3.881857047554073680828423675848171114921569824218750000e-01; | |||
a[4] = 7.171589940116777917022972133054281584918498992919921875e-02; | |||
break; | |||
case 24000: | |||
b[0] = 3.786678621924967069745093795063439756631851196289062500e-01; | |||
b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[2] = -7.573357243849934139490187590126879513263702392578125000e-01; | |||
b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[4] = 3.786678621924967069745093795063439756631851196289062500e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -1.529945307555420797029910318087786436080932617187500000e+00; | |||
a[2] = 1.283553182116208835061854642844991758465766906738281250e-01; | |||
a[3] = 3.494608072385725350272878131363540887832641601562500000e-01; | |||
a[4] = 5.217291949300089520802359288609295617789030075073242188e-02; | |||
break; | |||
case 32000: | |||
b[0] = 2.977986488230693340462096330156782642006874084472656250e-01; | |||
b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[2] = -5.955972976461386680924192660313565284013748168945312500e-01; | |||
b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[4] = 2.977986488230693340462096330156782642006874084472656250e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -1.812455387128179218336754274787381291389465332031250000e+00; | |||
a[2] = 6.425013281155662614452239722595550119876861572265625000e-01; | |||
a[3] = 1.619857574578579817448087396769551560282707214355468750e-01; | |||
a[4] = 7.987649713547682189807019881300220731645822525024414062e-03; | |||
break; | |||
case 44100: | |||
b[0] = 2.170085619492190254220531642204150557518005371093750000e-01; | |||
b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[2] = -4.340171238984380508441063284408301115036010742187500000e-01; | |||
b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[4] = 2.170085619492190254220531642204150557518005371093750000e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -2.134674963687040794013682898366823792457580566406250000e+00; | |||
a[2] = 1.279333533236062692139967111870646476745605468750000000e+00; | |||
a[3] = -1.495598460893957093453821016737492755055427551269531250e-01; | |||
a[4] = 4.908700174624683852664386307651511742733418941497802734e-03; | |||
break; | |||
case 48000: | |||
b[0] = 1.978871200263932761398422144338837824761867523193359375e-01; | |||
b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[2] = -3.957742400527865522796844288677675649523735046386718750e-01; | |||
b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[4] = 1.978871200263932761398422144338837824761867523193359375e-01; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -2.219172914052801814932536217384040355682373046875000000e+00; | |||
a[2] = 1.455135878947171557129536267893854528665542602539062500e+00; | |||
a[3] = -2.484960738877830532800317087094299495220184326171875000e-01; | |||
a[4] = 1.253882314727246607977129144728678511455655097961425781e-02; | |||
break; | |||
case 88200: | |||
b[0] = 9.221909851156021020734954163344809785485267639160156250e-02; | |||
b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[2] = -1.844381970231204204146990832668961957097053527832031250e-01; | |||
b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[4] = 9.221909851156021020734954163344809785485267639160156250e-02; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -2.785795902923448696952846148633398115634918212890625000e+00; | |||
a[2] = 2.727736758747444145711824603495188057422637939453125000e+00; | |||
a[3] = -1.097007502819661528548067508381791412830352783203125000e+00; | |||
a[4] = 1.550674356752141103132913713125162757933139801025390625e-01; | |||
break; | |||
case 96000: | |||
b[0] = 8.182864044979756834585771230194950476288795471191406250e-02; | |||
b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[2] = -1.636572808995951366917154246038990095257759094238281250e-01; | |||
b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[4] = 8.182864044979756834585771230194950476288795471191406250e-02; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -2.856378516857566829401093855267390608787536621093750000e+00; | |||
a[2] = 2.897640237559524045707348705036565661430358886718750000e+00; | |||
a[3] = -1.225265958339703198376469117647502571344375610351562500e+00; | |||
a[4] = 1.840048283551226071530493300087982788681983947753906250e-01; | |||
break; | |||
case 192000: | |||
b[0] = 2.784755468532278815940728122768632601946592330932617188e-02; | |||
b[1] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[2] = -5.569510937064557631881456245537265203893184661865234375e-02; | |||
b[3] = 0.000000000000000000000000000000000000000000000000000000e+00; | |||
b[4] = 2.784755468532278815940728122768632601946592330932617188e-02; | |||
a[0] = 1.000000000000000000000000000000000000000000000000000000e+00; | |||
a[1] = -3.333298856144166322224009491037577390670776367187500000e+00; | |||
a[2] = 4.111467536240339448738723149290308356285095214843750000e+00; | |||
a[3] = -2.222889041651291641699117462849244475364685058593750000e+00; | |||
a[4] = 4.447204118126878991112960193277103826403617858886718750e-01; | |||
break; | |||
default: | |||
AUBIO_ERROR ( "sampling rate of C-weighting filter is %d, should be one of\ | |||
8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, 192000.\n", | |||
samplerate ); | |||
return 1; | |||
} | |||
return 0; | |||
} | |||
aubio_filter_t * new_aubio_filter_c_weighting (uint_t samplerate) { | |||
aubio_filter_t * f = new_aubio_filter(5); | |||
if (aubio_filter_set_c_weighting(f,samplerate) != AUBIO_OK) { | |||
del_aubio_filter(f); | |||
return NULL; | |||
} | |||
return f; | |||
} |
@@ -0,0 +1,88 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef AUBIO_FILTER_C_DESIGN_H | |||
#define AUBIO_FILTER_C_DESIGN_H | |||
/** \file | |||
C-weighting filter coefficients | |||
This file creates a C-weighting digital filter, which reduces low and high | |||
frequencies and enhance the middle ones to reflect the ability of the human | |||
hearing. | |||
The implementation is based on the following standard: | |||
- IEC/CD 1672: Electroacoustics-Sound Level Meters, IEC, Geneva, Nov. 1996, | |||
for A- and C-weighting filters. | |||
See also: | |||
- <a href="http://en.wikipedia.org/wiki/A-weighting">A-Weighting on | |||
Wikipedia</a> | |||
- <a href="http://en.wikipedia.org/wiki/Weighting_filter">Weighting filter on | |||
Wikipedia</a> | |||
- <a href="http://www.mathworks.com/matlabcentral/fileexchange/69">Christophe | |||
Couvreur's 'octave' toolbox</a> | |||
The coefficients in this file have been computed using Christophe Couvreur's | |||
scripts in octave 3.0 (debian package 1:3.0.5-6+b2 with octave-signal | |||
1.0.9-1+b1 on i386), with <pre> [b, a] = cdsign(1/Fs) </pre> for various | |||
sampling frequencies (8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, | |||
88200, 96000, and 192000 Hz). | |||
The sampling frequency should normally be higher than 20kHz, but most common | |||
file sampling rates have been included for completeness. | |||
\example temporal/test-c_weighting.c | |||
*/ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** create new C-design filter | |||
\param samplerate sampling frequency of the signal to filter. Should be one of | |||
8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, and | |||
192000 Hz | |||
\return a new filter object | |||
*/ | |||
aubio_filter_t *new_aubio_filter_c_weighting (uint_t samplerate); | |||
/** set feedback and feedforward coefficients of a C-weighting filter | |||
\param f filter object to get coefficients from | |||
\param samplerate sampling frequency of the signal to filter. Should be one of | |||
8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000, and | |||
192000 Hz | |||
*/ | |||
uint_t aubio_filter_set_c_weighting (aubio_filter_t * f, uint_t samplerate); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_FILTER_C_DESIGN_H */ |
@@ -0,0 +1,163 @@ | |||
/* | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/* Requires lsmp_t to be long or double. float will NOT give reliable | |||
* results */ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "lvec.h" | |||
#include "mathutils.h" | |||
#include "temporal/filter.h" | |||
struct _aubio_filter_t | |||
{ | |||
uint_t order; | |||
uint_t samplerate; | |||
lvec_t *a; | |||
lvec_t *b; | |||
lvec_t *y; | |||
lvec_t *x; | |||
}; | |||
void | |||
aubio_filter_do_outplace (aubio_filter_t * f, const fvec_t * in, fvec_t * out) | |||
{ | |||
fvec_copy (in, out); | |||
aubio_filter_do (f, out); | |||
} | |||
void | |||
aubio_filter_do (aubio_filter_t * f, fvec_t * in) | |||
{ | |||
uint_t j, l, order = f->order; | |||
lsmp_t *x = f->x->data; | |||
lsmp_t *y = f->y->data; | |||
lsmp_t *a = f->a->data; | |||
lsmp_t *b = f->b->data; | |||
for (j = 0; j < in->length; j++) { | |||
/* new input */ | |||
x[0] = KILL_DENORMAL (in->data[j]); | |||
y[0] = b[0] * x[0]; | |||
for (l = 1; l < order; l++) { | |||
y[0] += b[l] * x[l]; | |||
y[0] -= a[l] * y[l]; | |||
} | |||
/* new output */ | |||
in->data[j] = y[0]; | |||
/* store for next sample */ | |||
for (l = order - 1; l > 0; l--) { | |||
x[l] = x[l - 1]; | |||
y[l] = y[l - 1]; | |||
} | |||
} | |||
} | |||
/* The rough way: reset memory of filter between each run to avoid end effects. */ | |||
void | |||
aubio_filter_do_filtfilt (aubio_filter_t * f, fvec_t * in, fvec_t * tmp) | |||
{ | |||
uint_t j; | |||
uint_t length = in->length; | |||
/* apply filtering */ | |||
aubio_filter_do (f, in); | |||
aubio_filter_do_reset (f); | |||
/* mirror */ | |||
for (j = 0; j < length; j++) | |||
tmp->data[length - j - 1] = in->data[j]; | |||
/* apply filtering on mirrored */ | |||
aubio_filter_do (f, tmp); | |||
aubio_filter_do_reset (f); | |||
/* invert back */ | |||
for (j = 0; j < length; j++) | |||
in->data[j] = tmp->data[length - j - 1]; | |||
} | |||
lvec_t * | |||
aubio_filter_get_feedback (const aubio_filter_t * f) | |||
{ | |||
return f->a; | |||
} | |||
lvec_t * | |||
aubio_filter_get_feedforward (const aubio_filter_t * f) | |||
{ | |||
return f->b; | |||
} | |||
uint_t | |||
aubio_filter_get_order (const aubio_filter_t * f) | |||
{ | |||
return f->order; | |||
} | |||
uint_t | |||
aubio_filter_get_samplerate (const aubio_filter_t * f) | |||
{ | |||
return f->samplerate; | |||
} | |||
uint_t | |||
aubio_filter_set_samplerate (aubio_filter_t * f, uint_t samplerate) | |||
{ | |||
f->samplerate = samplerate; | |||
return AUBIO_OK; | |||
} | |||
void | |||
aubio_filter_do_reset (aubio_filter_t * f) | |||
{ | |||
lvec_zeros (f->x); | |||
lvec_zeros (f->y); | |||
} | |||
aubio_filter_t * | |||
new_aubio_filter (uint_t order) | |||
{ | |||
aubio_filter_t *f = AUBIO_NEW (aubio_filter_t); | |||
if ((sint_t)order < 1) { | |||
AUBIO_FREE(f); | |||
return NULL; | |||
} | |||
f->x = new_lvec (order); | |||
f->y = new_lvec (order); | |||
f->a = new_lvec (order); | |||
f->b = new_lvec (order); | |||
/* by default, samplerate is not set */ | |||
f->samplerate = 0; | |||
f->order = order; | |||
/* set default to identity */ | |||
f->a->data[0] = 1.; | |||
f->b->data[0] = 1.; | |||
return f; | |||
} | |||
void | |||
del_aubio_filter (aubio_filter_t * f) | |||
{ | |||
del_lvec (f->a); | |||
del_lvec (f->b); | |||
del_lvec (f->x); | |||
del_lvec (f->y); | |||
AUBIO_FREE (f); | |||
return; | |||
} |
@@ -0,0 +1,176 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef AUBIO_FILTER_H | |||
#define AUBIO_FILTER_H | |||
/** \file | |||
Digital filter | |||
This object stores a digital filter of order \f$n\f$. | |||
It contains the following data: | |||
- \f$ n*1 b_i \f$ feedforward coefficients | |||
- \f$ n*1 a_i \f$ feedback coefficients | |||
- \f$ n*c x_i \f$ input signal | |||
- \f$ n*c y_i \f$ output signal | |||
For convenience, the samplerate of the input signal is also stored in the | |||
object. | |||
Feedforward and feedback parameters can be modified using | |||
aubio_filter_get_feedback() and aubio_filter_get_feedforward(). | |||
The function aubio_filter_do_outplace() computes the following output signal | |||
\f$ y[n] \f$ from the input signal \f$ x[n] \f$: | |||
\f{eqnarray*}{ | |||
y[n] = b_0 x[n] & + & b_1 x[n-1] + b_2 x[n-2] + ... + b_P x[n-P] \\ | |||
& - & a_1 y[n-1] - a_2 y[n-2] - ... - a_P y[n-P] \\ | |||
\f} | |||
The function aubio_filter_do() executes the same computation but modifies | |||
directly the input signal (in-place). | |||
The function aubio_filter_do_filtfilt() version runs the filter twice, first | |||
forward then backward, to compensate with the phase shifting of the forward | |||
operation. | |||
Some convenience functions are provided: | |||
- new_aubio_filter_a_weighting() and aubio_filter_set_a_weighting(), | |||
- new_aubio_filter_c_weighting() and aubio_filter_set_c_weighting(). | |||
- new_aubio_filter_biquad() and aubio_filter_set_biquad(). | |||
\example temporal/test-filter.c | |||
*/ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** Digital filter | |||
*/ | |||
typedef struct _aubio_filter_t aubio_filter_t; | |||
/** filter input vector (in-place) | |||
\param f filter object as returned by new_aubio_filter() | |||
\param in input vector to filter | |||
*/ | |||
void aubio_filter_do (aubio_filter_t * f, fvec_t * in); | |||
/** filter input vector (out-of-place) | |||
\param f filter object as returned by new_aubio_filter() | |||
\param in input vector to filter | |||
\param out output vector to store filtered input | |||
*/ | |||
void aubio_filter_do_outplace (aubio_filter_t * f, const fvec_t * in, fvec_t * out); | |||
/** filter input vector forward and backward | |||
\param f ::aubio_filter_t object as returned by new_aubio_filter() | |||
\param in ::fvec_t input vector to filter | |||
\param tmp memory space to use for computation | |||
*/ | |||
void aubio_filter_do_filtfilt (aubio_filter_t * f, fvec_t * in, fvec_t * tmp); | |||
/** returns a pointer to feedback coefficients \f$ a_i \f$ | |||
\param f filter object to get parameters from | |||
\return a pointer to the \f$ a_0 ... a_i ... a_P \f$ coefficients | |||
*/ | |||
lvec_t *aubio_filter_get_feedback (const aubio_filter_t * f); | |||
/** returns a pointer to feedforward coefficients \f$ b_i \f$ | |||
\param f filter object to get coefficients from | |||
\return a pointer to the \f$ b_0 ... b_i ... b_P \f$ coefficients | |||
*/ | |||
lvec_t *aubio_filter_get_feedforward (const aubio_filter_t * f); | |||
/** get order of the filter | |||
\param f filter to get order from | |||
\return the order of the filter | |||
*/ | |||
uint_t aubio_filter_get_order (const aubio_filter_t * f); | |||
/** get sampling rate of the filter | |||
\param f filter to get sampling rate from | |||
\return the sampling rate of the filter, in Hz | |||
*/ | |||
uint_t aubio_filter_get_samplerate (const aubio_filter_t * f); | |||
/** get sampling rate of the filter | |||
\param f filter to get sampling rate from | |||
\param samplerate sample rate to set the filter to | |||
\return the sampling rate of the filter, in Hz | |||
*/ | |||
uint_t aubio_filter_set_samplerate (aubio_filter_t * f, uint_t samplerate); | |||
/** reset filter memory | |||
\param f filter object as returned by new_aubio_filter() | |||
*/ | |||
void aubio_filter_do_reset (aubio_filter_t * f); | |||
/** create new filter object | |||
This function creates a new ::aubio_filter_t object, given the order of the | |||
filter. | |||
\param order order of the filter (number of coefficients) | |||
\return the newly created filter object | |||
*/ | |||
aubio_filter_t *new_aubio_filter (uint_t order); | |||
/** delete a filter object | |||
\param f filter object to delete | |||
*/ | |||
void del_aubio_filter (aubio_filter_t * f); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_FILTER_H */ |
@@ -0,0 +1,100 @@ | |||
/* | |||
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "fvec.h" | |||
#include "temporal/resampler.h" | |||
#ifdef HAVE_SAMPLERATE | |||
#if HAVE_AUBIO_DOUBLE | |||
#error "Should not use libsamplerate with aubio in double precision" | |||
#endif | |||
#include <samplerate.h> /* from libsamplerate */ | |||
struct _aubio_resampler_t | |||
{ | |||
SRC_DATA *proc; | |||
SRC_STATE *stat; | |||
smpl_t ratio; | |||
uint_t type; | |||
}; | |||
aubio_resampler_t * | |||
new_aubio_resampler (smpl_t ratio, uint_t type) | |||
{ | |||
aubio_resampler_t *s = AUBIO_NEW (aubio_resampler_t); | |||
int error = 0; | |||
s->stat = src_new (type, 1, &error); /* only one channel */ | |||
if (error) { | |||
AUBIO_ERR ("Failed creating resampler: %s\n", src_strerror (error)); | |||
del_aubio_resampler(s); | |||
return NULL; | |||
} | |||
s->proc = AUBIO_NEW (SRC_DATA); | |||
s->ratio = ratio; | |||
return s; | |||
} | |||
void | |||
del_aubio_resampler (aubio_resampler_t * s) | |||
{ | |||
if (s->stat) src_delete (s->stat); | |||
AUBIO_FREE (s->proc); | |||
AUBIO_FREE (s); | |||
} | |||
void | |||
aubio_resampler_do (aubio_resampler_t * s, const fvec_t * input, fvec_t * output) | |||
{ | |||
s->proc->input_frames = input->length; | |||
s->proc->output_frames = output->length; | |||
s->proc->src_ratio = (double) s->ratio; | |||
/* make SRC_PROC data point to input outputs */ | |||
s->proc->data_in = (float *) input->data; | |||
s->proc->data_out = (float *) output->data; | |||
/* do resampling */ | |||
src_process (s->stat, s->proc); | |||
} | |||
#else | |||
struct _aubio_resampler_t | |||
{ | |||
void *dummy; | |||
}; | |||
aubio_resampler_t * | |||
new_aubio_resampler (smpl_t ratio UNUSED, uint_t type UNUSED) | |||
{ | |||
AUBIO_ERR ("aubio was not compiled with libsamplerate\n"); | |||
return NULL; | |||
} | |||
void | |||
del_aubio_resampler (aubio_resampler_t * s UNUSED) | |||
{ | |||
} | |||
void | |||
aubio_resampler_do (aubio_resampler_t * s UNUSED, const fvec_t * input UNUSED, fvec_t * output UNUSED) | |||
{ | |||
} | |||
#endif /* HAVE_SAMPLERATE */ |
@@ -0,0 +1,65 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef AUBIO_RESAMPLER_H | |||
#define AUBIO_RESAMPLER_H | |||
/** \file | |||
Resampling object | |||
This object resamples an input vector into an output vector using | |||
libsamplerate. See http://www.mega-nerd.com/SRC/ | |||
*/ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** resampler object */ | |||
typedef struct _aubio_resampler_t aubio_resampler_t; | |||
/** create resampler object | |||
\param ratio output_sample_rate / input_sample_rate | |||
\param type libsamplerate resampling type, see http://www.mega-nerd.com/SRC/api_misc.html#Converters | |||
*/ | |||
aubio_resampler_t *new_aubio_resampler (smpl_t ratio, uint_t type); | |||
/** delete resampler object */ | |||
void del_aubio_resampler (aubio_resampler_t * s); | |||
/** resample input in output | |||
\param s resampler object | |||
\param input input buffer of size N | |||
\param output output buffer of size N*ratio | |||
*/ | |||
void aubio_resampler_do (aubio_resampler_t * s, const fvec_t * input, | |||
fvec_t * output); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_RESAMPLER_H */ |
@@ -0,0 +1,70 @@ | |||
/* | |||
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef AUBIO_TYPES_H | |||
#define AUBIO_TYPES_H | |||
/** \file | |||
Definition of data types used in aubio | |||
*/ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
#ifndef HAVE_AUBIO_DOUBLE | |||
/** defined to 1 if aubio is compiled in double precision */ | |||
#define HAVE_AUBIO_DOUBLE 0 | |||
#endif | |||
/** short sample format (32 or 64 bits) */ | |||
#if !HAVE_AUBIO_DOUBLE | |||
typedef float smpl_t; | |||
/** print format for sample in single precision */ | |||
#define AUBIO_SMPL_FMT "%f" | |||
#else | |||
typedef double smpl_t; | |||
/** print format for double in single precision */ | |||
#define AUBIO_SMPL_FMT "%lf" | |||
#endif | |||
/** long sample format (64 bits or more) */ | |||
#if !HAVE_AUBIO_DOUBLE | |||
typedef double lsmp_t; | |||
/** print format for sample in double precision */ | |||
#define AUBIO_LSMP_FMT "%lf" | |||
#else | |||
typedef long double lsmp_t; | |||
/** print format for double in double precision */ | |||
#define AUBIO_LSMP_FMT "%Lf" | |||
#endif | |||
/** unsigned integer */ | |||
typedef unsigned int uint_t; | |||
/** signed integer */ | |||
typedef int sint_t; | |||
/** character */ | |||
typedef char char_t; | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_TYPES_H */ |
@@ -0,0 +1,92 @@ | |||
/* | |||
Copyright (C) 2016 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "aubio_priv.h" | |||
#include "log.h" | |||
/** array of pointers to logging functions, one per level */ | |||
static aubio_log_function_t aubio_log_function[AUBIO_LOG_LAST_LEVEL]; | |||
/** array of pointers to closure passed to logging functions, one per level */ | |||
static void* aubio_log_user_data[AUBIO_LOG_LAST_LEVEL]; | |||
/** buffer for logging messages */ | |||
static char aubio_log_buffer[512]; | |||
/** private function used by default by logging functions */ | |||
void | |||
aubio_default_log(sint_t level, const char_t *message, void * data UNUSED) | |||
{ | |||
FILE *out; | |||
out = stdout; | |||
if (level == AUBIO_LOG_ERR || level == AUBIO_LOG_DBG || level == AUBIO_LOG_WRN) { | |||
out = stderr; | |||
} | |||
fprintf(out, "%s", message); | |||
//fflush(out); | |||
} | |||
uint_t | |||
aubio_log(sint_t level, const char_t *fmt, ...) | |||
{ | |||
aubio_log_function_t fun = NULL; | |||
va_list args; | |||
va_start(args, fmt); | |||
vsnprintf(aubio_log_buffer, sizeof(aubio_log_buffer), fmt, args); | |||
va_end(args); | |||
if ((level >= 0) && (level < AUBIO_LOG_LAST_LEVEL)) { | |||
fun = aubio_log_function[level]; | |||
if (fun != NULL) { | |||
(*fun)(level, aubio_log_buffer, aubio_log_user_data[level]); | |||
} else { | |||
aubio_default_log(level, aubio_log_buffer, NULL); | |||
} | |||
} | |||
return AUBIO_FAIL; | |||
} | |||
void | |||
aubio_log_reset(void) | |||
{ | |||
uint_t i = 0; | |||
for (i = 0; i < AUBIO_LOG_LAST_LEVEL; i++) { | |||
aubio_log_set_level_function(i, aubio_default_log, NULL); | |||
} | |||
} | |||
aubio_log_function_t | |||
aubio_log_set_level_function(sint_t level, aubio_log_function_t fun, void * data) | |||
{ | |||
aubio_log_function_t old = NULL; | |||
if ((level >= 0) && (level < AUBIO_LOG_LAST_LEVEL)) { | |||
old = aubio_log_function[level]; | |||
aubio_log_function[level] = fun; | |||
aubio_log_user_data[level] = data; | |||
} | |||
return old; | |||
} | |||
void | |||
aubio_log_set_function(aubio_log_function_t fun, void * data) { | |||
uint_t i = 0; | |||
for (i = 0; i < AUBIO_LOG_LAST_LEVEL; i++) { | |||
aubio_log_set_level_function(i, fun, data); | |||
} | |||
} |
@@ -0,0 +1,99 @@ | |||
/* | |||
Copyright (C) 2016 Paul Brossier <piem@aubio.org> | |||
This file is part of aubio. | |||
aubio is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
aubio is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with aubio. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef AUBIO_LOG_H | |||
#define AUBIO_LOG_H | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** \file | |||
Logging features | |||
This file specifies ::aubio_log_set_function and | |||
::aubio_log_set_level_function, which let you define one or several custom | |||
logging functions to redirect warnings and errors from aubio to your | |||
application. The custom function should have the prototype defined in | |||
::aubio_log_function_t. | |||
After a call to ::aubio_log_set_level_function, ::aubio_log_reset can be used | |||
to reset each logging functions to the default ones. | |||
\example utils/test-log.c | |||
*/ | |||
/** list of logging levels */ | |||
enum aubio_log_level { | |||
AUBIO_LOG_ERR, /**< critical errors */ | |||
AUBIO_LOG_INF, /**< infos */ | |||
AUBIO_LOG_MSG, /**< general messages */ | |||
AUBIO_LOG_DBG, /**< debug messages */ | |||
AUBIO_LOG_WRN, /**< warnings */ | |||
AUBIO_LOG_LAST_LEVEL, /**< number of valid levels */ | |||
}; | |||
/** Logging function prototype, to be passed to ::aubio_log_set_function | |||
\param level log level | |||
\param message text to log | |||
\param data optional closure used by the callback | |||
See @ref utils/test-log.c for an example of logging function. | |||
*/ | |||
typedef void (*aubio_log_function_t)(sint_t level, const char_t *message, void | |||
*data); | |||
/** Set logging function for all levels | |||
\param fun the function to be used to log, of type ::aubio_log_function_t | |||
\param data optional closure to be passed to the function (can be NULL if | |||
nothing to pass) | |||
*/ | |||
void aubio_log_set_function(aubio_log_function_t fun, void* data); | |||
/** Set logging function for a given level | |||
\param level the level for which to set the logging function | |||
\param fun the function to be used to log, of type ::aubio_log_function_t | |||
\param data optional closure to be passed to the function (can be NULL if | |||
nothing to pass) | |||
*/ | |||
aubio_log_function_t aubio_log_set_level_function(sint_t level, | |||
aubio_log_function_t fun, void* data); | |||
/** Reset all logging functions to the default one | |||
After calling this function, the default logging function will be used to | |||
print error, warning, normal, and debug messages to `stdout` or `stderr`. | |||
*/ | |||
void aubio_log_reset(void); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* AUBIO_LOG_H */ |
@@ -120,7 +120,7 @@ struct AudioToCVPitch : Module { | |||
if (detectedPitchInHz > 0.f && pitchConfidence >= params[PARAM_CONFIDENCETHRESHOLD].getValue() * 0.01f) | |||
{ | |||
const float linearPitch = 12.f * (log2f(detectedPitchInHz / 440.f) + octave - 1) + 69.f; | |||
const float linearPitch = 12.f * (log2f(detectedPitchInHz / 440.f) + octave - 5) + 69.f; | |||
cvPitch = std::max(-10.f, std::min(10.f, linearPitch * (1.f/12.f))); | |||
lastKnownPitchInHz = detectedPitchInHz; | |||
cvSignal = 10.f; | |||