Mercurial > hg > vamp-onsetsds-plugin
changeset 0:635e8745ccc9
* First commit of plugin using Dan Stowell's OnsetsDS library code
author | cannam |
---|---|
date | Thu, 19 Jun 2008 12:30:15 +0000 |
parents | |
children | 3d1928670329 |
files | AUTHORS COPYING Makefile onsetsds/AUTHORS onsetsds/COPYING onsetsds/ChangeLog onsetsds/README onsetsds/doc/Doxyfile onsetsds/doc/footer.html onsetsds/doc/mainpage.dox onsetsds/onsetsds.c onsetsds/onsetsds.h onsetsds/onsetsdshelpers.c onsetsds/onsetsdshelpers.h onsetsdsplugin.cpp onsetsdsplugin.h vamp-onsetsds.cat |
diffstat | 17 files changed, 2623 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AUTHORS Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,5 @@ + +Dan Stowell, dan.stowell@elec.qmul.ac.uk + +Vamp-plugin-ified by Chris Cannam, cannam@all-day-breakfast.com +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/COPYING Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,13 @@ + +CXXFLAGS := -I../vamp-plugin-sdk -O3 -Wall +#CXXFLAGS := -I../vamp-plugin-sdk -g -Wall -march=pentium4 -msse -msse2 -ffast-math +#CXXFLAGS := -I../vamp-plugin-sdk -O3 -Wall -march=pentium4 -msse -msse2 -fomit-frame-pointer -ffast-math + +vamp-onsetsds.so: onsetsdsplugin.o onsetsds/onsetsds.o + g++ -shared $^ -o $@ -L../vamp-plugin-sdk/vamp-sdk -Wl,-Bstatic -lvamp-sdk -Wl,-Bdynamic -lpthread + +clean: + rm -f *.o */*.o + +onsetsdsplugin.o: onsetsdsplugin.h onsetsds/onsetsds.h +onsetsds/onsetsds.o: onsetsds/onsetsds.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsds/AUTHORS Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,2 @@ + +Dan Stowell, dan.stowell@elec.qmul.ac.uk \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsds/COPYING Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsds/ChangeLog Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,3 @@ +2007-11 Dan Stowell + * Significant refactoring from v0.1, which was a set of SuperCollider UGens. + * VERSION: 0.2.0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsds/README Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,29 @@ + + ---------------------------------------------------------- + OnsetsDS + + Musical onset detection library + (c) 2007 Dan Stowell + Made available under the GPL v2 - see COPYING for details. + ---------------------------------------------------------- + + + +USAGE + +If your system can provide frequency-domain data (e.g. by performing FFT on the +input audio), then to perform onset detection you only need onsetsds.h and +onsetsds.c. These need no additional libraries beyond the standard C libraries. + +If you aren't already doing the FFT then you can also use onsetsdshelpers.c +and onsetsdshelpers.h, which can process raw audio, from a buffer or from a +file. These require two additional libraries: + + * libsndfile - I used version 1.0.17 + http://www.meganerd.com/libsndfile + + * FFTW 3 (floating-point version) - I used version 3.1.2 + http://www.fftw.org + +See the HTML documentation for a worked example. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsds/doc/Doxyfile Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,267 @@ +# Doxyfile 1.5.3 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = OnsetsDS +PROJECT_NUMBER = v0.2 +OUTPUT_DIRECTORY = . +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class " \ + "The $name widget " \ + "The $name file " \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = /Applications/ +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = NO +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = NO +GENERATE_TESTLIST = NO +GENERATE_BUGLIST = NO +GENERATE_DEPRECATEDLIST= NO +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = NO +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text " +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = .. +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = */.svn* */doc/html* +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = footer.html +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +HTML_DYNAMIC_SECTIONS = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO +MSCGEN_PATH = /Applications/Doxygen.app/Contents/Resources/ +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = /Applications/Doxygen.app/Contents/Resources/ +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsds/doc/footer.html Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,1 @@ +</body></html> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsds/doc/mainpage.dox Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,93 @@ +/** \mainpage OnsetsDS - real time musical onset detection C/C++ library + +<small>Copyright (c) 2007 Dan Stowell (Published under the GNU Public License v2). +http://onsetsds.sourceforge.net/</small> + +<h2>Introduction</h2> + +The purpose of %OnsetsDS is to provide capabilities for FFT-based onset +detection that works very efficiently in real-time, and can detect onsets +pretty well in a broad variety of musical signals, with a fast reaction +time. + +It is not specialised for any particular type of signal. Nor is it +particularly tailored towards non-real-time use (if we were working in +non-real-time there are extra things we could do to improve the precision). +Its efficiency and fast reaction are designed with general real-time musical +applications in mind. + +<h2>Download</h2> + +<ul> + <li><a href="http://sourceforge.net/">Download the sourcecode bundle</a></li> + <li>Or access the current development version using subversion [<small><a href="http://sourceforge.net/svn/?group_id=54622" title="What is subversion, and how to use it">info</a></small>]: <br /> + <tt>svn co %https://onsetsds.svn.sourceforge.net/svnroot/onsetsds onsetsds</tt></li> +</ul> + +<h2>Typical usage</h2> + +\code + +// This example uses the recommended settings of an FFT size of 512 (@44.1kHz), +// and a median span of 11. It also uses the "rectified complex deviation" +// onset detection function - your choice of function may be down to taste, +// or to performance on the particular type of sound you're using. + +#include "onsetsds.h" + +// An instance of the OnsetsDS struct, declared/allocated somewhere in your code, +// however you want to do it. +OnsetsDS ods; + + +///////// (1) INITIALISATION: ///////// + +// Allocate contiguous memory using malloc or whatever is reasonable. +float* odsdata = (float*) malloc( onsetsds_memneeded(odftype, 512, 11) ); + +// There are various types of onset detector available, we must choose one +odftype = ODS_ODF_RCOMPLEX; + +// Now initialise the OnsetsDS struct and its associated memory +onsetsds_init(ods, odsdata, ODS_FFT_FFTW3_HC, odftype, 512, 11); + + +///////// (2) EXECUTION: ///////// + +bool onset; +while(running){ + // Grab your 512-point, 50%-overlap, nicely-windowed FFT data, into "fftdata" + + // Then detect. "onset" will be true when there's an onset, false otherwise + onset = onsetsds_process(ods, fftdata); +} + + +///////// (3) TIDYING UP: ///////// + +free(ods->data); // Or free(odsdata), they point to the same thing in this case + +\endcode + +<h2>Research background</h2> + +%OnsetsDS is based on research into musical onset detection +carried out by Dan Stowell, with Dr Mark Plumbley, at +Queen Mary University of London's +<a href="http://www.elec.qmul.ac.uk/digitalmusic/">Centre for Digital Music</a>. + +Relevant publications: + +\li D. Stowell and M. D. Plumbley. +<a href="http://www.elec.qmul.ac.uk/digitalmusic/papers/2007/StowellPlumbley07-icmc.pdf"> +Adaptive whitening for improved real-time audio onset detection.</a> +To appear in: +Proceedings of the International Computer Music Conference (ICMC'07), +Copenhagen, Denmark, August 2007. + +The research stands on the shoulders of other onset detection research, and uses +some concepts from that research - see the ICMC'07 paper and its bibliography +for more details. + + +*/ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsds/onsetsds.c Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,547 @@ +/* + OnsetsDS - real time musical onset detection library. + Copyright (c) 2007 Dan Stowell. All rights reserved. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "onsetsds.h" + + +#define ODS_DEBUG_POST_CSV 0 + +// Inline +inline float onsetsds_phase_rewrap(float phase); +inline float onsetsds_phase_rewrap(float phase){ + return (phase>MINUSPI && phase<PI) ? phase : phase + TWOPI * (1.f + floorf((MINUSPI - phase) * INV_TWOPI)); +} + + +size_t onsetsds_memneeded (int odftype, size_t fftsize, unsigned int medspan){ + + /* + Need memory for: + - median calculation (2 * medspan floats) + - storing old values (whether as OdsPolarBuf or as weirder float lists) + - storing the OdsPolarBuf (size is NOT sizeof(OdsPolarBuf) but is fftsize) + - storing the PSP (numbins + 2 values) + All these are floats. + */ + + int numbins = (fftsize >> 1) - 1; // No of bins, not counting DC/nyq + + switch(odftype){ + case ODS_ODF_POWER: + case ODS_ODF_MAGSUM: + + // No old FFT frames needed, easy: + return (medspan+medspan + fftsize + numbins + 2) * sizeof(float); + + case ODS_ODF_COMPLEX: + case ODS_ODF_RCOMPLEX: + + return (medspan+medspan + fftsize + numbins + 2 + // For each bin (NOT dc/nyq) we store mag, phase and d_phase + + numbins + numbins + numbins + ) * sizeof(float); + + case ODS_ODF_PHASE: + case ODS_ODF_WPHASE: + + return (medspan+medspan + fftsize + numbins + 2 + // For each bin (NOT dc/nyq) we store phase and d_phase + + numbins + numbins + ) * sizeof(float); + + case ODS_ODF_MKL: + + return (medspan+medspan + fftsize + numbins + 2 + // For each bin (NOT dc/nyq) we store mag + + numbins + ) * sizeof(float); + + + break; + + } + return -1; //bleh +} + + +void onsetsds_init(OnsetsDS *ods, float *odsdata, int fftformat, + int odftype, size_t fftsize, unsigned int medspan, float srate){ + + // The main pointer to the processing area - other pointers will indicate areas within this + ods->data = odsdata; + // Set all vals in processing area to zero + memset(odsdata, 0, onsetsds_memneeded(odftype, fftsize, medspan)); + + ods->srate = srate; + + int numbins = (fftsize >> 1) - 1; // No of bins, not counting DC/nyq + int realnumbins = numbins + 2; + + // Also point the other pointers to the right places + ods->curr = (OdsPolarBuf*) odsdata; + ods->psp = odsdata + fftsize; + ods->odfvals = odsdata + fftsize + realnumbins; + ods->sortbuf = odsdata + fftsize + realnumbins + medspan; + ods->other = odsdata + fftsize + realnumbins + medspan + medspan; + + // Default settings for Adaptive Whitening, user can set own values after init + onsetsds_setrelax(ods, 1.f, fftsize>>1); + ods->floor = 0.1; + + switch(odftype){ + case ODS_ODF_POWER: + ods->odfparam = 0.01; // "powthresh" in SC code + ods->normfactor = 2560.f / (realnumbins * fftsize); + break; + case ODS_ODF_MAGSUM: + ods->odfparam = 0.01; // "powthresh" in SC code + ods->normfactor = 113.137085f / (realnumbins * sqrt(fftsize)); + break; + case ODS_ODF_COMPLEX: + ods->odfparam = 0.01; // "powthresh" in SC code + ods->normfactor = 231.70475f / pow(fftsize, 1.5);// / fftsize; + break; + case ODS_ODF_RCOMPLEX: + ods->odfparam = 0.01; // "powthresh" in SC code + ods->normfactor = 231.70475f / pow(fftsize, 1.5);// / fftsize; + break; + case ODS_ODF_PHASE: + ods->odfparam = 0.01; // "powthresh" in SC code + ods->normfactor = 5.12f / fftsize;// / fftsize; + break; + case ODS_ODF_WPHASE: + ods->odfparam = 0.0001; // "powthresh" in SC code. For WPHASE it's kind of superfluous. + ods->normfactor = 115.852375f / pow(fftsize, 1.5);// / fftsize; + break; + case ODS_ODF_MKL: + ods->odfparam = 0.01; // EPSILON parameter. Brossier recommends 1e-6 but I (ICMC 2007) found larger vals (e.g 0.01) to work better + ods->normfactor = 7.68f * 0.25f / fftsize; + break; + default: + printf("onsetsds_init ERROR: \"odftype\" is not a recognised value\n"); + } + + ods->odfvalpost = 0.f; + ods->odfvalpostprev = 0.f; + ods->thresh = 0.5f; + ods->logmags = false; + + ods->odftype = odftype; + ods->whtype = ODS_WH_ADAPT_MAX1; + ods->fftformat = fftformat; + + ods->whiten = (odftype != ODS_ODF_MKL); // Deactivate whitening for MKL by default + ods->detected = false; + ods->med_odd = (medspan & 1) != 0; + + ods->medspan = medspan; + + ods->mingap = 0; + ods->gapleft = 0; + + ods->fftsize = fftsize; + ods->numbins = numbins; + + //printf("End of _init: normfactor is %g\n", ods->normfactor); + +} + +bool onsetsds_process(OnsetsDS* ods, float* fftbuf){ + onsetsds_loadframe(ods, fftbuf); + + onsetsds_whiten(ods); + onsetsds_odf(ods); + onsetsds_detect(ods); + + return ods->detected; +} + + +void onsetsds_setrelax(OnsetsDS* ods, float time, size_t hopsize){ + ods->relaxtime = time; + ods->relaxcoef = (time == 0.0f) ? 0.0f : exp((ods_log1 * hopsize)/(time * ods->srate)); +} + + + +void onsetsds_loadframe(OnsetsDS* ods, float* fftbuf){ + + float *pos, *pos2, imag, real; + int i; + + switch(ods->fftformat){ + case ODS_FFT_SC3_POLAR: + // The format is the same! dc, nyq, mag[1], phase[1], ... + memcpy(ods->curr, fftbuf, ods->fftsize * sizeof(float)); + break; + + case ODS_FFT_SC3_COMPLEX: + + ods->curr->dc = fftbuf[0]; + ods->curr->nyq = fftbuf[1]; + + // Then convert cartesian to polar: + pos = fftbuf + 2; + for(i=0; i< (ods->numbins << 1); i += 2){ + real = pos[i]; + imag = pos[i+1]; // Plus 1 rather than increment; seems to avoid LSU reject on my PPC + ods->curr->bin[i].mag = hypotf(imag, real); + ods->curr->bin[i].phase = atan2f(imag, real); + } + break; + + case ODS_FFT_FFTW3_HC: + + ods->curr->dc = fftbuf[0]; + ods->curr->nyq = fftbuf[ods->fftsize>>1]; + + // Then convert cartesian to polar: + // (Starting positions: real and imag for bin 1) + pos = fftbuf + 1; + pos2 = fftbuf + ods->fftsize - 1; + for(i=0; i<ods->numbins; i++){ + real = *(pos++); + imag = *(pos2--); + ods->curr->bin[i].mag = hypotf(imag, real); + ods->curr->bin[i].phase = atan2f(imag, real); + } + break; + + case ODS_FFT_FFTW3_R2C: + + ods->curr->dc = fftbuf[0]; + ods->curr->nyq = fftbuf[ods->fftsize]; + + // Then convert cartesian to polar: + pos = fftbuf + 2; + for(i=0; i<ods->numbins; i++){ + real = *(pos++); + imag = *(pos++); + ods->curr->bin[i].mag = hypotf(imag, real); + ods->curr->bin[i].phase = atan2f(imag, real); + } + break; + + } + + // Conversion to log-domain magnitudes, including re-scaling to aim back at the zero-to-one range. + // Not well tested yet. + if(ods->logmags){ + for(i=0; i<ods->numbins; i++){ + ods->curr->bin[i].mag = + (log(ods_max(ods->curr->bin[i].mag, ODS_LOG_LOWER_LIMIT)) - ODS_LOGOF_LOG_LOWER_LIMIT) * ODS_ABSINVOF_LOGOF_LOG_LOWER_LIMIT; + } + ods->curr->dc = + (log(ods_max(ods_abs(ods->curr->dc ), ODS_LOG_LOWER_LIMIT)) - ODS_LOGOF_LOG_LOWER_LIMIT) * ODS_ABSINVOF_LOGOF_LOG_LOWER_LIMIT; + ods->curr->nyq = + (log(ods_max(ods_abs(ods->curr->nyq), ODS_LOG_LOWER_LIMIT)) - ODS_LOGOF_LOG_LOWER_LIMIT) * ODS_ABSINVOF_LOGOF_LOG_LOWER_LIMIT; + } + +} + +void onsetsds_whiten(OnsetsDS* ods){ + + if(ods->whtype == ODS_WH_NONE){ + //printf("onsetsds_whiten(): ODS_WH_NONE, skipping\n"); + return; + } + + // NB: Apart from the above, ods->whtype is currently IGNORED and only one mode is used. + + + float val,oldval, relaxcoef, floor; + int numbins, i; + OdsPolarBuf *curr; + float *psp; + float *pspp1; // Offset by 1, avoids quite a lot of "+1"s in the following code + + relaxcoef = ods->relaxcoef; + numbins = ods->numbins; + curr = ods->curr; + psp = ods->psp; + pspp1 = psp + 1; + floor = ods->floor; + + //printf("onsetsds_whiten: relaxcoef=%g, relaxtime=%g, floor=%g\n", relaxcoef, ods->relaxtime, floor); + + ////////////////////// For each bin, update the record of the peak value ///////////////////// + + val = fabs(curr->dc); // Grab current magnitude + oldval = psp[0]; + // If it beats the amplitude stored then that's our new amplitude; + // otherwise our new amplitude is a decayed version of the old one + if(val < oldval) { + val = val + (oldval - val) * relaxcoef; + } + psp[0] = val; // Store the "amplitude trace" back + + val = fabs(curr->nyq); + oldval = pspp1[numbins]; + if(val < oldval) { + val = val + (oldval - val) * relaxcoef; + } + pspp1[numbins] = val; + + for(i=0; i<numbins; ++i){ + val = fabs(curr->bin[i].mag); + oldval = pspp1[i]; + if(val < oldval) { + val = val + (oldval - val) * relaxcoef; + } + pspp1[i] = val; + } + + //////////////////////////// Now for each bin, rescale the current magnitude //////////////////////////// + curr->dc /= ods_max(floor, psp[0]); + curr->nyq /= ods_max(floor, pspp1[numbins]); + for(i=0; i<numbins; ++i){ + curr->bin[i].mag /= ods_max(floor, pspp1[i]); + } +} + +void onsetsds_odf(OnsetsDS* ods){ + + int numbins = ods->numbins; + OdsPolarBuf *curr = ods->curr; + float* val = ods->odfvals; + int i, tbpointer; + float deviation, diff, curmag; + double totdev; + + bool rectify = true; + + // Here we shunt the "old" ODF values down one place + memcpy(val + 1, val, (ods->medspan - 1)*sizeof(float)); + + // Now calculate a new value and store in ods->odfvals[0] + switch(ods->odftype){ + case ODS_ODF_POWER: + + *val = (curr->nyq * curr->nyq) + (curr->dc * curr->dc); + for(i=0; i<numbins; i++){ + *val += curr->bin[i].mag * curr->bin[i].mag; + } + break; + + case ODS_ODF_MAGSUM: + + *val = ods_abs(curr->nyq) + ods_abs(curr->dc); + + for(i=0; i<numbins; i++){ + *val += ods_abs(curr->bin[i].mag); + } + break; + + case ODS_ODF_COMPLEX: + rectify = false; + // ...and then drop through to: + case ODS_ODF_RCOMPLEX: + + // Note: "other" buf is stored in this format: mag[0],phase[0],d_phase[0],mag[1],phase[1],d_phase[1], ... + + // Iterate through, calculating the deviation from expected value. + totdev = 0.0; + tbpointer = 0; + float predmag, predphase, yesterphase, yesterphasediff; + for (i=0; i<numbins; ++i) { + curmag = ods_abs(curr->bin[i].mag); + + // Predict mag as yestermag + predmag = ods->other[tbpointer++]; + yesterphase = ods->other[tbpointer++]; + yesterphasediff = ods->other[tbpointer++]; + + // Thresholding as Brossier did - discard (ignore) bin's deviation if bin's power is minimal + if(curmag > ods->odfparam) { + // If rectifying, ignore decreasing bins + if((!rectify) || !(curmag < predmag)){ + + // Predict phase as yesterval + yesterfirstdiff + predphase = yesterphase + yesterphasediff; + + // Here temporarily using the "deviation" var to store the phase difference + // so that the rewrap macro can use it more efficiently + deviation = predphase - curr->bin[i].phase; + + // Deviation is Euclidean distance between predicted and actual. + // In polar coords: sqrt(r1^2 + r2^2 - r1r2 cos (theta1 - theta2)) + deviation = sqrtf(predmag * predmag + curmag * curmag + - predmag * curmag * cosf(onsetsds_phase_rewrap(deviation)) + ); + + totdev += deviation; + } + } + } + + // totdev will be the output, but first we need to fill tempbuf with today's values, ready for tomorrow. + tbpointer = 0; + for (i=0; i<numbins; ++i) { + ods->other[tbpointer++] = ods_abs(curr->bin[i].mag); // Storing mag + diff = curr->bin[i].phase - ods->other[tbpointer]; // Retrieving yesterphase from buf + ods->other[tbpointer++] = curr->bin[i].phase; // Storing phase + // Wrap onto +-PI range + diff = onsetsds_phase_rewrap(diff); + + ods->other[tbpointer++] = diff; // Storing first diff to buf + + } + *val = (float)totdev; + + break; + + + case ODS_ODF_PHASE: + rectify = false; // So, actually, "rectify" means "useweighting" in this context + // ...and then drop through to: + case ODS_ODF_WPHASE: + + // Note: "other" buf is stored in this format: phase[0],d_phase[0],phase[1],d_phase[1], ... + + // Iterate through, calculating the deviation from expected value. + totdev = 0.0; + tbpointer = 0; + for (i=0; i<numbins; ++i) { + // Thresholding as Brossier did - discard (ignore) bin's phase deviation if bin's power is low + if(ods_abs(curr->bin[i].mag) > ods->odfparam) { + + // Deviation is the *second difference* of the phase, which is calc'ed as curval - yesterval - yesterfirstdiff + deviation = curr->bin[i].phase - ods->other[tbpointer++] - ods->other[tbpointer++]; + // Wrap onto +-PI range + deviation = onsetsds_phase_rewrap(deviation); + + if(rectify){ // "rectify" meaning "useweighting"... + totdev += fabs(deviation * ods_abs(curr->bin[i].mag)); + } else { + totdev += fabs(deviation); + } + } + } + + // totdev will be the output, but first we need to fill tempbuf with today's values, ready for tomorrow. + tbpointer = 0; + for (i=0; i<numbins; ++i) { + diff = curr->bin[i].phase - ods->other[tbpointer]; // Retrieving yesterphase from buf + ods->other[tbpointer++] = curr->bin[i].phase; // Storing phase + // Wrap onto +-PI range + diff = onsetsds_phase_rewrap(diff); + + ods->other[tbpointer++] = diff; // Storing first diff to buf + + } + *val = (float)totdev; + break; + + + case ODS_ODF_MKL: + + // Iterate through, calculating the Modified Kullback-Liebler distance + totdev = 0.0; + tbpointer = 0; + float yestermag; + for (i=0; i<numbins; ++i) { + curmag = ods_abs(curr->bin[i].mag); + yestermag = ods->other[tbpointer]; + + // Here's the main implementation of Brossier's MKL eq'n (eqn 2.9 from his thesis): + deviation = ods_abs(curmag) / (ods_abs(yestermag) + ods->odfparam); + totdev += log(1.f + deviation); + + // Store the mag as yestermag + ods->other[tbpointer++] = curmag; + } + *val = (float)totdev; + break; + + } + +#if ODS_DEBUG_POST_CSV + printf("%g,", *val); + printf("%g,", ods->odfvals[0] * ods->normfactor); +#endif + + ods->odfvals[0] *= ods->normfactor; +} +// End of ODF function + +void SelectionSort(float *array, int length); +void SelectionSort(float *array, int length) +{ + // Algo is simply based on http://en.wikibooks.org/wiki/Algorithm_implementation/Sorting/Selection_sort + int max, i; + float temp; + while(length > 0) + { + max = 0; + for(i = 1; i < length; i++) + if(array[i] > array[max]) + max = i; + temp = array[length-1]; + array[length-1] = array[max]; + array[max] = temp; + length--; + } +} + + +void onsetsds_detect(OnsetsDS* ods){ + + // Shift the yesterval to its rightful place + ods->odfvalpostprev = ods->odfvalpost; + + ///////// MEDIAN REMOVAL //////////// + + float* sortbuf = ods->sortbuf; + int medspan = ods->medspan; + + // Copy odfvals to sortbuf + memcpy(sortbuf, ods->odfvals, medspan * sizeof(float)); + + // Sort sortbuf + SelectionSort(sortbuf, medspan); + + // Subtract the middlest value === the median + if(ods->med_odd){ + ods->odfvalpost = ods->odfvals[0] + - sortbuf[(medspan - 1) >> 1]; + }else{ + ods->odfvalpost = ods->odfvals[0] + - ((sortbuf[medspan >> 1] + + sortbuf[(medspan >> 1) - 1]) * 0.5f); + + } + + // Detection not allowed if we're too close to a previous detection. + if(ods->gapleft != 0) { + ods->gapleft--; + ods->detected = false; + } else { + // Now do the detection. + ods->detected = (ods->odfvalpost > ods->thresh) && (ods->odfvalpostprev <= ods->thresh); + if(ods->detected){ + ods->gapleft = ods->mingap; + } + } +#if ODS_DEBUG_POST_CSV + printf("%g\n", ods->odfvalpost); +#endif +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsds/onsetsds.h Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,275 @@ +/* + OnsetsDS - real time musical onset detection library. + Copyright (c) 2007 Dan Stowell. All rights reserved. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** \file */ + +#ifndef _OnsetsDS_ +#define _OnsetsDS_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include <string.h> +#include <stdbool.h> +#include <math.h> + + +//////////////////////////////////////////////////////////////////////////////// +// Macros and consts + +//log(0.1) +#define ods_log1 -2.30258509 + +#define PI 3.1415926535898f +#define MINUSPI -3.1415926535898f +#define TWOPI 6.28318530717952646f +#define INV_TWOPI 0.1591549430919f + +#define ods_abs(a) ((a)<0? -(a) : (a)) +#define ods_max(a,b) (((a) > (b)) ? (a) : (b)) +#define ods_min(a,b) (((a) < (b)) ? (a) : (b)) + +#define ODS_LOG_LOWER_LIMIT 2e-42 +#define ODS_LOGOF_LOG_LOWER_LIMIT -96.0154267 +#define ODS_ABSINVOF_LOGOF_LOG_LOWER_LIMIT 0.010414993 + +//////////////////////////////////////////////////////////////////////////////// +// Constants + +/** +* Types of incoming FFT data format. OnsetsDS needs to know where the FFT +* data comes from in order to interpret it correctly. +*/ +enum onsetsds_fft_types { + ODS_FFT_SC3_COMPLEX, ///< SuperCollider, cartesian co-ords ("SCComplexBuf") - NB it's more efficient to provide polar data from SC + ODS_FFT_SC3_POLAR, ///< SuperCollider, polar co-ords ("SCPolarBuf") + ODS_FFT_FFTW3_HC, ///< FFTW <a href="http://www.fftw.org/fftw3_doc/The-Halfcomplex_002dformat-DFT.html">"halfcomplex"</a> format + ODS_FFT_FFTW3_R2C ///< FFTW regular format, typically produced using <a href="http://www.fftw.org/fftw3_doc/One_002dDimensional-DFTs-of-Real-Data.html#One_002dDimensional-DFTs-of-Real-Data">real-to-complex</a> transform +}; + +/** +* Types of onset detection function +*/ +enum onsetsds_odf_types { + ODS_ODF_POWER, ///< Power + ODS_ODF_MAGSUM, ///< Sum of magnitudes + ODS_ODF_COMPLEX, ///< Complex-domain deviation + ODS_ODF_RCOMPLEX, ///< Complex-domain deviation, rectified (only increases counted) + ODS_ODF_PHASE, ///< Phase deviation + ODS_ODF_WPHASE, ///< Weighted phase deviation + ODS_ODF_MKL ///< Modified Kullback-Liebler deviation +}; + +/** +* Types of whitening - may not all be implemented yet. +*/ +enum onsetsds_wh_types { + ODS_WH_NONE, ///< No whitening - onsetsds_whiten() becomes a no-op + ODS_WH_ADAPT_MAX1, ///< Adaptive whitening - tracks recent-peak-magnitude in each bin, normalises that to 1 + ODS_WH_NORMMAX, ///< Simple normalisation - each frame is normalised (independent of others) so largest magnitude becomes 1. Not implemented. + ODS_WH_NORMMEAN ///< Simple normalisation - each frame is normalised (independent of others) so mean magnitude becomes 1. Not implemented. +}; + +//////////////////////////////////////////////////////////////////////////////// +// Structs + +typedef struct OdsPolarBin { float mag, phase; } OdsPolarBin; + +typedef struct OdsPolarBuf { + float dc, nyq; + OdsPolarBin bin[1]; +} OdsPolarBuf; + +/// The main data structure for the onset detection routine +typedef struct OnsetsDS { + /// "data" is a pointer to the memory that must be EXTERNALLY allocated. + /// Other pointers will point to locations within this memory. + float *data, + *psp, ///< Peak Spectral Profile - size is numbins+2, data is stored in order dc through to nyquist + *odfvals, // odfvals[0] will be the current val, odfvals[1] prev, etc + *sortbuf, // Used to calculate the median + *other; // Typically stores data about the previous frame + OdsPolarBuf* curr; // Current FFT frame, as polar + + float + srate, ///< The sampling rate of the input audio. Set by onsetsds_init() + // Adaptive whitening params + relaxtime, ///< Do NOT set this directly. Use onsetsds_setrelax() which will also update relaxcoef. + relaxcoef, ///< Relaxation coefficient (memory coefficient). See also onsetsds_setrelax() + floor, ///< floor - the lowest value that a PSP magnitude can take. + /// A parameter for the ODF. For most this is a magnitude threshold for a single bin to be considered; + /// but for #ODS_ODF_MKL it is the "epsilon" parameter. + odfparam, + /// Value used internally to scale ODF value according to the FFT frame size. Automatically set by onsetsds_init() + normfactor, + // ODF val after median processing + odfvalpost, + // Previous val is needed for threshold-crossing detection + odfvalpostprev, + /// Threshold (of ODF value, after median processing) for detection. + /// Values between 0 and 1 are expected, but outside this range may + /// sometimes be appropriate too. + thresh; + + int odftype, ///< Choose from #onsetsds_odf_types + whtype, ///< Choose from #onsetsds_wh_types + fftformat; ///< Choose from #onsetsds_fft_types + bool whiten, ///< Whether to apply whitening - onsetsds_init() decides this on your behalf + detected,///< Output val - true if onset detected in curr frame + /** + NOT YET USED: Whether to convert magnitudes to log domain before processing. This is done as follows: + Magnitudes below a log-lower-limit threshold (ODS_LOG_LOWER_LIMIT) are pushed up to that threshold (to avoid log(0) infinity problems), + then the log is taken. The values are re-scaled to a similar range as the linear-domain values (assumed to lie + between zero and approximately one) by subtracting log(ODS_LOG_LOWER_LIMIT) and then dividing by abs(log(ODS_LOG_LOWER_LIMIT)). + */ + logmags, + med_odd; ///< Whether median span is odd or not (used internally) + + unsigned int + /// Number of frames used in median calculation + medspan, + /// Size of enforced gap between detections, measured in FFT frames. + mingap, gapleft; + size_t fftsize, numbins; // numbins is the count not including DC/nyq +} OnsetsDS; + + +//////////////////////////////////////////////////////////////////////////////// +// Function prototypes + + +/** + * \defgroup MainUserFuncs Main user functions + */ + //@{ + +/** +* Determine how many bytes of memory must be allocated (e.g. using malloc) to +* accompany the OnsetsDS struct, operating using the specified settings (used to +* store part-processed FFT data etc). The user must +* call this, and then allocate the memory, BEFORE calling onsetsds_init(). +* @param odftype Which onset detection function (ODF) you'll be using, chosen from #onsetsds_odf_types +* @param fftsize Size of FFT: 512 is recommended. +* @param medspan The number of past frames that will be used for median calculation during triggering +*/ +size_t onsetsds_memneeded (int odftype, size_t fftsize, unsigned int medspan); + +/** +* Initialise the OnsetsDS struct and its associated memory, ready to detect +* onsets using the specified settings. Must be called before any call to +* onsetsds_process(). +* +* Note: you can change the onset detection function type in mid-operation +* by calling onsetsds_init() again, but because memory will be reset this +* will behave as if starting from scratch (rather than being aware of the past +* few frames of sound). Do not attempt to change the +* onset detection function in a more hacky way (e.g. fiddling with the struct) +* because memory is set up differently for each of the different ODFs. +* @param ods An instance of the OnsetsDS struct +* @param odsdata A pointer to the memory allocated, size given by onsetsds_memneeded(). +* @param fftformat Which format of FFT data is to be expected, chosen from #onsetsds_fft_types +* @param odftype Which onset detection function (ODF) you'll be using, chosen from #onsetsds_odf_types +* @param fftsize Size of FFT: 512 or 1024 is recommended. +* @param medspan The number of past frames that will be used for median calculation during triggering +* @param srate The sampling rate of the input audio +*/ +void onsetsds_init(OnsetsDS* ods, float* odsdata, int fftformat, + int odftype, size_t fftsize, unsigned int medspan, float srate); + +/** +* Process a single FFT data frame in the audio signal. Note that processing +* assumes that each call to onsetsds_process() is on a subsequent frame in +* the same audio stream - to handle multiple streams you must use separate +* OnsetsDS structs and memory! +* +* This function's main purpose is to call some of the library's other functions, +* in the expected sequence. +*/ +bool onsetsds_process(OnsetsDS* ods, float* fftbuf); + +//@} + + +//////////////////////////////////////////////////////////////////////////////// +// Function prototypes less commonly called by users + +/** + * \defgroup LessCommonFuncs Other useful functions + */ + //@{ +/** +* Set the "memory coefficient" indirectly via the time for the +* memory to decay by 60 dB. +* @param ods The OnsetsDS +* @param time The time in seconds +* @param hopsize The FFT frame hopsize (typically this will be half the FFT frame size) +*/ +void onsetsds_setrelax(OnsetsDS* ods, float time, size_t hopsize); + +//@} + +//////////////////////////////////////////////////////////////////////////////// +// Function prototypes not typically called by users + +/** + * \defgroup OtherFuncs Other functions, not typically called by users + */ + //@{ +/** +* Load the current frame of FFT data into the OnsetsDS struct. +* +* Not typically called directly by users since onsetsds_process() calls this. +*/ +void onsetsds_loadframe(OnsetsDS* ods, float* fftbuf); + +/** +* Apply adaptive whitening to the FFT data in the OnsetsDS struct. +* +* Not typically called directly by users since onsetsds_process() calls this. +*/ +void onsetsds_whiten(OnsetsDS* ods); + +/** +* Calculate the Onset Detection Function (includes scaling ODF outputs to +* similar range) +* +* Not typically called directly by users since onsetsds_process() calls this. +*/ +void onsetsds_odf(OnsetsDS* ods); + +/** +* Detects salient peaks in Onset Detection Function by removing the median, +* then thresholding. Afterwards, the member ods.detected will indicate whether +* or not an onset was detected. +* +* Not typically called directly by users since onsetsds_process() calls this. +*/ +void onsetsds_detect(OnsetsDS* ods); + +//@} + +//////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsds/onsetsdshelpers.c Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,177 @@ +/* + OnsetsDS - real time musical onset detection library. + Copyright (c) 2007 Dan Stowell. All rights reserved. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "onsetsdshelpers.h" + +#include <stdlib.h> +#include <sndfile.h> +#include <fftw3.h> + +void onsetsds_init_audiodata(OnsetsDSAudioBuf *odsbuf, OnsetsDS *ods, /* size_t framesize, */ size_t hopsize){ + + odsbuf->ods = ods; + odsbuf->buflen = ods->fftsize; + odsbuf->hopsize = hopsize; + + size_t framesizebytes = ods->fftsize * sizeof(float); + + // malloc odsbuf.data, odsbuf.window, odsbuf.windoweddata + odsbuf->data = (float*) malloc(framesizebytes); + odsbuf->window = (float*) malloc(framesizebytes); + odsbuf->windoweddata = (float*) fftwf_malloc(framesizebytes); + odsbuf->fftbuf = (float*) fftwf_malloc(framesizebytes); + + // Create the FFTW plan + odsbuf->fftplan = fftwf_plan_r2r_1d(ods->fftsize, odsbuf->windoweddata, odsbuf->fftbuf, FFTW_R2HC, FFTW_ESTIMATE); + + // zero odsbuf.data + memset(odsbuf->data, 0, framesizebytes); + + // Create the FFT window + double pi = acos(-1.); + double winc = pi / ods->fftsize; + int i; + for (i=0; i<ods->fftsize; ++i) { + double w = i * winc; + odsbuf->window[i] = sin(w); + } + + odsbuf->sampsElapsed = 0L; + odsbuf->writepos = 0; +} +void onsetsds_destroy_audiodata(OnsetsDSAudioBuf *odsbuf){ + // take down the FFTW stuff + fftwf_destroy_plan(odsbuf->fftplan); + // free mem + free(odsbuf->data); + free(odsbuf->window); + fftwf_free(odsbuf->windoweddata); + fftwf_free(odsbuf->fftbuf); +} + +void onsetsds_process_audiodata(OnsetsDSAudioBuf* odsbuf, float* data, size_t datalen, + ODSDataCallback callback){ + + if(datalen==0){ + printf("onsetsds_process_audiodata GRRRRRR: no audio data sent (datalen==0)\n"); + return; + }else{ + } + + size_t datareadpos = 0; + size_t dataleft = datalen; + size_t numtocopy; + int i; + while(dataleft > 0){ + // Read the smaller of how-much-available and how-much-to-fill-the-buffer + numtocopy = ods_min(dataleft, odsbuf->buflen - odsbuf->writepos); +// printf("onsetsds_process_audiodata: datalen = %i, dataleft = %i, buflen = %i, about to copy %i values to position %i\n", +// datalen, dataleft, odsbuf->buflen, numtocopy, odsbuf->writepos); + memcpy(&odsbuf->data[odsbuf->writepos], &data[datareadpos], numtocopy * sizeof(float)); + + odsbuf->writepos += numtocopy; + + // If the buffer is full, do all the FFT and stuff + if(odsbuf->writepos >= odsbuf->buflen){ + + // Copy the data into the buffer where windowing and FFT takes place + memcpy(odsbuf->windoweddata, odsbuf->data, odsbuf->buflen * sizeof(float)); + + // Shunt the audio data (and the writepos) down to make room for the next lot + memcpy(odsbuf->data, &odsbuf->data[odsbuf->hopsize], (odsbuf->buflen - odsbuf->hopsize) * sizeof(float)); + //printf("onsetsds_process_audiodata: moving writepos from %i to %i(==hopsize)\n", odsbuf->writepos, odsbuf->hopsize); + odsbuf->writepos = odsbuf->hopsize; + + // Windowing + for(i=0; i<odsbuf->buflen; i++){ + odsbuf->windoweddata[i] *= odsbuf->window[i]; + } + + // FFT + fftwf_execute(odsbuf->fftplan); + + // Onset detection + if(onsetsds_process(odsbuf->ods, odsbuf->fftbuf)){ + // Call the callback! + callback(odsbuf, datareadpos); + } + + } // End buffer-is-filled + + datareadpos += numtocopy; + dataleft -= numtocopy; + } // End of still-some-data-to-push + +} + + +void onsetsds_process_audiofile_CALLBACK(OnsetsDSAudioBuf* odsbuf, size_t onsetsamplepos); +void onsetsds_process_audiofile_CALLBACK(OnsetsDSAudioBuf* odsbuf, size_t onsetsamplepos){ + // Convert the sample pos into a seconds position through the whole file + double secs = (odsbuf->sampsElapsed + onsetsamplepos) / odsbuf->samplerate; + + // Now call the file-level callback + (odsbuf->filecallback)(odsbuf->ods, secs); +} + +int onsetsds_process_audiofile(OnsetsDSAudioBuf* odsbuf, const char *infilename, + ODSFileCallback callback){ + + SNDFILE *insndfile ; + SF_INFO sfinfo ; + memset (&sfinfo, 0, sizeof (sfinfo)); + + // Attempt to get the input file + if ((insndfile = sf_open (infilename, SFM_READ, &sfinfo)) == NULL){ + printf ("onsetsds_process_audiofile ERROR: Not able to open input file %s.\n", infilename) ; + fflush (stdout) ; + return 100; + } + if(sfinfo.channels != 1){ + printf("onsetsds_process_audiofile ERROR: Only mono audio files can be processed. Num channels = %i. Exiting.\n", sfinfo.channels); + sf_close(insndfile); + return 200; + }else{ + printf("onsetsds_process_audiofile: mono audio file, sample rate %i Hz.\n", sfinfo.samplerate); + } + + odsbuf->sampsElapsed = 0L; + odsbuf->samplerate = (double) sfinfo.samplerate; + odsbuf->filecallback = callback; + + // Create a buffer for reading the raw data into + float* data = malloc(odsbuf->buflen * sizeof(float)); + + sf_count_t numread; + //printf("onsetsds_process_audiofile: Processing audio data\n", numread); + while((numread = sf_read_float(insndfile, data, odsbuf->buflen)) > 0){ + //printf("Read %i audio frames (requested %i)\n", numread, odsbuf->buflen); + + //printf("Calling onsetsds_process_audiodata\n"); + onsetsds_process_audiodata(odsbuf, data, numread, onsetsds_process_audiofile_CALLBACK); + //printf("Called onsetsds_process_audiodata\n"); + odsbuf->sampsElapsed += numread; + } + + sf_close(insndfile); + free(data); + + // Indicate success + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsds/onsetsdshelpers.h Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,171 @@ +/* + OnsetsDS - real time musical onset detection library. + Copyright (c) 2007 Dan Stowell. All rights reserved. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** \file */ + +/** + * \defgroup HelperFuncs Convenience functions to apply OnsetsDS to a chunk of audio data, or to an audio file. + * + * These functions are NOT required in order to use the core OnsetsDS functionality, but provide wrappers to + * make it easy to apply OnsetsDS to time-domain data (audio chunks, or audio files) without having to write the + * FFT processing yourself. + */ + //@{ + +#ifndef _OnsetsDSHelpers_ +#define _OnsetsDSHelpers_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <fftw3.h> +#include "../onsetsds.h" + +//////////////////////////////////////////////////////////////////////////////// + +/** +When using onsetsds_process_audiofile(), this specifies that your callback function should +take an #OnsetsDS and a double as arguments, and return void. The double will be a time +offset, from the beginning of the recording, at which the detected onset occurred. +*/ +typedef void (*ODSFileCallback)(OnsetsDS*, double); + +/** +Holds all the state data required by onsetsds_process_audiodata(), including a pointer to an #OnsetsDS +as well as the time-domain/freq-domain buffers. +Also remembers the FFT frame size, hop size. +*/ +typedef struct OnsetsDSAudioBuf{ + OnsetsDS* ods; + + size_t buflen; + size_t hopsize; + size_t writepos; + float *data; // size will be buflen + float *window; // size will be buflen + float *windoweddata; // size will be buflen + float *fftbuf; // size will be buflen + fftwf_plan fftplan; + + // Whole-file-only things (i.e. unused when you're pushing audio blocks yourself): + long sampsElapsed; + double samplerate; + ODSFileCallback filecallback; +} OnsetsDSAudioBuf; + +/** +When using onsetsds_process_audiodata(), this specifies that your callback function should +take an #OnsetsDSAudioBuf and a size_t as arguments, and return void. The size_t will be a sample +offset at which the detected onset occurred, within the audio frame that was just passed in. (More than +one onset per audio frame is possible, depending on how much data you're passing in at a time.) +*/ +typedef void (*ODSDataCallback)(OnsetsDSAudioBuf*, size_t); + +/** +This data structure stores statistics derived from using onsetsds_evaluate_audiofile(), describing how well +the onset detector matched the "ground truth" annotations. +*/ +typedef struct OnsetsDSEvalData{ + long numGT; ///< How many ground truth annotations were provided + long numAnnot; ///< How many onsets it found + long numTP; ///< How many correct detections occurred + long numFP; ///< How many false positives occurred + long numFN; ///< How many false negatives occurred + + float precision; ///< 0 to 1: a measure of resistance against false positives + float recall; ///< 0 to 1: a measure of resistance against false negatives + float f; ///< 0 to 1: the "F-measure", a combination of the precision and recall statistics + + float devimean; ///< Mean of each onset's deviation from the annotated onset, a rough indicator of reacting "too quickly"/"too slowly" + float deviabsmean; ///< Absolute mean of each onset's deviation from the annotated onset, a rough indicator of temporal accuracy + float devisd; ///< Standard deviation re devimean, useful when combining stats + float deviabssd; ///< Standard deviation re deviabsmean, useful when combining stats +} OnsetsDSEvalData; + +//////////////////////////////////////////////////////////////////////////////// + +/** +Set up the data structures for use by onsetsds_process_audiodata(). + +@param odsbuf Will be set up nicely by this function. +@param ods Must have been initialised properly before calling this function. +@param hopsize Hop size in samples (256 is recommended) +*/ +void onsetsds_init_audiodata(OnsetsDSAudioBuf* odsbuf, OnsetsDS* ods, size_t hopsize); +/** +Correctly deallocate and destroy the #OnsetsDSAudioBuf. Use this after onsetsds_process_audiofile(), or after you've finished +running a series of onsetsds_process_audiodata() calls. + +@param odsbuf +*/ +void onsetsds_destroy_audiodata(OnsetsDSAudioBuf* odsbuf); + +/** +Process a new chunk of audio data. + +@param odsbuf Must have been initialised properly before calling this function, using onsetsds_init_audiodata() +@param data The *new* chunk of mono, time-domain audio data. Internal buffers will handle frame overlap etc. The size + of the input data does *not* need to have a relation to the frame size or hop size. +@param datalen Size of the data buffer. +@param callback Name of your callback function, which will be called whenever an onset is detected. + It will be passed the #OnsetsDSAudioBuf object and (more importantly) the sample offset at which the onset was detected + (i.e. a value between 0 and datalen). +*/ +void onsetsds_process_audiodata(OnsetsDSAudioBuf* odsbuf, float* data, size_t datalen, + ODSDataCallback callback); + +//////////////////////////////////////////////////////////////////////////////// + +/** +Process an entire file of audio data. Returns 0 if successful (may fail if it can't find/open the audio file, for example). + +@param odsbuf Must have been initialised properly before calling this function, using onsetsds_init_audiodata() +@param infilename The file to be loaded. +@param callback Name of your callback function, which will be called whenever an onset is detected. + It will be passed the #OnsetsDS object and (more importantly) the time offset in seconds at which the onset was detected + (a double-precision-floating-point value between 0 and the duration of the audio file). +*/ +int onsetsds_process_audiofile(OnsetsDSAudioBuf* odsbuf, const char *infilename, + ODSFileCallback callback); + +/** +Process an entire file of audio data and compare the onset detector's output against a single "ground truth" annotation of where the +onsets really are. + +@param odsbuf Must have been initialised properly before calling this function, using onsetsds_init_audiodata() +@param infilename The file to be loaded. +@param gtfilename The file containing a text list of ground-truth annotations, one number per line, each being an onset's + position in seconds from the beginning of the file. The numbers must be in ascending order. + This format can be easily exported from programs + such as <a href="http://www.sonicvisualiser.org/">Sonic Visualiser</a>. +@param results Pointer to the #OnsetsDSEvalData where the results should be written. + +*/ +int onsetsds_evaluate_audiofile(OnsetsDSAudioBuf* odsbuf, const char *infilename, const char *gtfilename, OnsetsDSEvalData* results); + +//////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif + +//@}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsdsplugin.cpp Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,286 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ +/* + Vamp feature extraction plugin using the OnsetsDS onset detector. + This file copyright (c) 2008 Chris Cannam. + + OnsetsDS - real time musical onset detection library. + Copyright (c) 2007 Dan Stowell. All rights reserved. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "onsetsdsplugin.h" +#include <vamp-sdk/PluginAdapter.h> + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + + +OnsetsDSPlugin::OnsetsDSPlugin(float inputSampleRate) : + Vamp::Plugin(inputSampleRate), + m_ods(0), + m_odsdata(0), + m_dfType(ODS_ODF_RCOMPLEX), + m_medspan(11), + m_stepSize(512), + m_fftSize(1024) +{ +} + +OnsetsDSPlugin::~OnsetsDSPlugin() +{ + delete[] m_odsdata; + delete m_ods; +} + +string +OnsetsDSPlugin::getIdentifier() const +{ + return "onsetsds"; +} + +string +OnsetsDSPlugin::getName() const +{ + return "OnsetsDS Onset Detector"; +} + +string +OnsetsDSPlugin::getDescription() const +{ + return "Detect note onsets"; +} + +string +OnsetsDSPlugin::getMaker() const +{ + return "Dan Stowell"; +} + +int +OnsetsDSPlugin::getPluginVersion() const +{ + return 1; +} + +string +OnsetsDSPlugin::getCopyright() const +{ + return "Copyright (c) 2007-2008 Dan Stowell"; +} + +OnsetsDSPlugin::ParameterList +OnsetsDSPlugin::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + desc.identifier = "dftype"; + desc.name = "Onset detection function"; + desc.description = "Method used to calculate the onset detection function"; + desc.minValue = 0; + desc.maxValue = 6; + desc.defaultValue = 3; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.valueNames.push_back("Power"); + desc.valueNames.push_back("Sum of magnitudes"); + desc.valueNames.push_back("Complex-domain deviation"); + desc.valueNames.push_back("Rectified complex-domain deviation"); + desc.valueNames.push_back("Phase deviation"); + desc.valueNames.push_back("Weighted phase deviation"); + desc.valueNames.push_back("Modified Kullback-Liebler deviation"); + list.push_back(desc); + + desc.identifier = "medspan"; + desc.name = "Median frame span"; + desc.description = "Number of past frames used in median calculation"; + desc.minValue = 5; + desc.maxValue = 21; + desc.defaultValue = 11; + desc.isQuantized = true; + desc.quantizeStep = 2; + desc.valueNames.clear(); + list.push_back(desc); + + return list; +} + +float +OnsetsDSPlugin::getParameter(std::string name) const +{ + if (name == "dftype") { + switch (m_dfType) { + case ODS_ODF_POWER: return 0; + case ODS_ODF_MAGSUM: return 1; + case ODS_ODF_COMPLEX: return 2; + case ODS_ODF_RCOMPLEX: return 3; + case ODS_ODF_PHASE: return 4; + case ODS_ODF_WPHASE: return 5; + case ODS_ODF_MKL: return 6; + } + } else if (name == "medspan") { + return m_medspan; + } + return 0.0; +} + +void +OnsetsDSPlugin::setParameter(std::string name, float value) +{ + if (name == "dftype") { + onsetsds_odf_types dfType = m_dfType; + switch (lrintf(value)) { + case 0: dfType = ODS_ODF_POWER; break; + case 1: dfType = ODS_ODF_MAGSUM; break; + case 2: dfType = ODS_ODF_COMPLEX; break; + case 3: dfType = ODS_ODF_RCOMPLEX; break; + case 4: dfType = ODS_ODF_PHASE; break; + case 5: dfType = ODS_ODF_WPHASE; break; + case 6: dfType = ODS_ODF_MKL; break; + } + if (dfType == m_dfType) return; + m_dfType = dfType; + } else if (name == "medspan") { + m_medspan = lrintf(value); + } +} + +bool +OnsetsDSPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) { + std::cerr << "OnsetsDSPlugin::initialise: Unsupported channel count: " + << channels << std::endl; + return false; + } + + if (stepSize != getPreferredStepSize()) { + std::cerr << "WARNING: OnsetsDSPlugin::initialise: Using unusual step size: " + << stepSize << " (wanted " << (getPreferredStepSize()) << ")" << std::endl; + } + + if (blockSize != getPreferredBlockSize()) { + std::cerr << "WARNING: OnsetsDSPlugin::initialise: Using unusual block size: " + << blockSize << " (wanted " << (getPreferredBlockSize()) << ")" << std::endl; + } + + m_stepSize = stepSize; + m_fftSize = blockSize; + + delete[] m_odsdata; + delete m_ods; + + m_odsdata = new float[onsetsds_memneeded(m_dfType, m_fftSize, m_medspan)]; + m_ods = new OnsetsDS; + memset(m_ods, 0, sizeof(OnsetsDS)); + onsetsds_init(m_ods, m_odsdata, ODS_FFT_FFTW3_R2C, m_dfType, m_fftSize, + m_medspan, m_inputSampleRate); + + return true; +} + +void +OnsetsDSPlugin::reset() +{ + if (!m_ods) { + std::cerr << "ERROR: OnsetsDSPlugin::reset: Plugin has not been initialised" << std::endl; + return; + } + onsetsds_init(m_ods, m_odsdata, ODS_FFT_FFTW3_R2C, m_dfType, m_fftSize, + m_medspan, m_inputSampleRate); +} + +size_t +OnsetsDSPlugin::getPreferredStepSize() const +{ + return 512; +} + +size_t +OnsetsDSPlugin::getPreferredBlockSize() const +{ + return 1024; +} + +OnsetsDSPlugin::OutputList +OnsetsDSPlugin::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor onsets; + onsets.identifier = "onsets"; + onsets.name = "Note Onsets"; + onsets.description = "Note onset positions"; + onsets.unit = ""; + onsets.hasFixedBinCount = true; + onsets.binCount = 0; + onsets.sampleType = OutputDescriptor::VariableSampleRate; + onsets.sampleRate = (m_inputSampleRate / m_stepSize); + + list.push_back(onsets); + + return list; +} + +OnsetsDSPlugin::FeatureSet +OnsetsDSPlugin::process(const float *const *inputBuffers, + Vamp::RealTime timestamp) +{ + if (!m_ods) { + cerr << "ERROR: OnsetsDSPlugin::process: Plugin has not been initialised" + << endl; + return FeatureSet(); + } + + // We can const_cast because we happen to know onsetsds_process + // does not modify this buffer + bool result = onsetsds_process(m_ods, const_cast<float *>(inputBuffers[0])); + + FeatureSet returnFeatures; + + if (result) { + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = timestamp; + returnFeatures[0].push_back(feature); // onsets are output 0 + } + + return returnFeatures; +} + +OnsetsDSPlugin::FeatureSet +OnsetsDSPlugin::getRemainingFeatures() +{ + return FeatureSet(); +} + + +static Vamp::PluginAdapter<OnsetsDSPlugin> adapter; + +const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version, + unsigned int index) +{ + if (version < 1) return 0; + + switch (index) { + case 0: return adapter.getDescriptor(); + default: return 0; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/onsetsdsplugin.h Thu Jun 19 12:30:15 2008 +0000 @@ -0,0 +1,73 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ +/* + Vamp feature extraction plugin using the OnsetsDS onset detector. + This file copyright (c) 2008 Chris Cannam. + + OnsetsDS - real time musical onset detection library. + Copyright (c) 2007 Dan Stowell. All rights reserved. + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _ONSETSDS_PLUGIN_H_ +#define _ONSETSDS_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> + +#include "onsetsds/onsetsds.h" + +class OnsetsDSPlugin : public Vamp::Plugin +{ +public: + OnsetsDSPlugin(float inputSampleRate); + virtual ~OnsetsDSPlugin(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const { return FrequencyDomain; } + + std::string getIdentifier() const; + std::string getName() const; + std::string getDescription() const; + std::string getMaker() const; + int getPluginVersion() const; + std::string getCopyright() const; + + ParameterList getParameterDescriptors() const; + float getParameter(std::string) const; + void setParameter(std::string, float); + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + + OutputList getOutputDescriptors() const; + + FeatureSet process(const float *const *inputBuffers, + Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + OnsetsDS *m_ods; + float *m_odsdata; + onsetsds_odf_types m_dfType; + size_t m_medspan; + size_t m_stepSize; + size_t m_fftSize; +}; + + +#endif