Mercurial > hg > segmenter-vamp-plugin
changeset 1:f44aa6d29642
Plugin Code - The main file is songparts.cpp
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/COPYING Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/INSTALL_linux.txt Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,22 @@ + +QM Vamp Plugins +=============== + +To Install +========== + +This package contains plugins compiled for Linux on 32-bit x86 +(Intel/AMD) systems using GNU libc v6. + +To install them, copy the following files: + + qm-vamp-plugins.so + qm-vamp-plugins.cat + qm-vamp-plugins.n3 + +to one of the following directories: + + /usr/local/lib/vamp/ + /usr/lib/vamp/ + $HOME/vamp/ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/INSTALL_osx.txt Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,21 @@ + +QM Vamp Plugins +=============== + +To Install +========== + +This package contains plugins for the Apple OS/X operating system, +compatible with both PPC and Intel hardware. + +To install them, copy the files + + qm-vamp-plugins.dylib + qm-vamp-plugins.cat + qm-vamp-plugins.n3 + +to either + + /Library/Audio/Plug-Ins/Vamp/ (for plugins to be available to all users) + $HOME/Library/Audio/Plug-Ins/Vamp/ (for plugins to be available to you only) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/INSTALL_win32.txt Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ + +QM Vamp Plugins +=============== + +To Install +========== + +This package contains plugins for Win32 systems (Windows XP, Vista). + +To install them, copy the files + + qm-vamp-plugins.dll + qm-vamp-plugins.cat + qm-vamp-plugins.n3 + +into the folder + + "C:\Program Files\Vamp Plugins\" + +You may also install them elsewhere, if you set the VAMP_PATH environment +variable to a semicolon-separated list of the folders in which plugins +may be found. e.g., "C:\My Plugins;C:\Program Files\Vamp Plugins". +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/Makefile.osx Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,11 @@ + +CFLAGS := -O3 -ftree-vectorize -isysroot /Developer/SDKs/MacOSX10.7.sdk -arch i386 -arch x86_64 -I../armadillo-2.4.4/include -I../vamp-plugin-sdk -I/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/Headers/ -DUSE_PTHREADS + +CXXFLAGS := $(CFLAGS) + +LDFLAGS := -isysroot /Developer/SDKs/MacOSX10.7.sdk -arch i386 -arch x86_64 -lqm-dsp ../vamp-plugin-sdk/libvamp-sdk.a -dynamiclib -framework Accelerate -lpthread -install_name qm-vamp-plugins.dylib + +PLUGIN_EXT := .dylib + +include build/general/Makefile.inc +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/Makefile_ORIGINAL.osx Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,11 @@ + +CFLAGS := -O3 -ftree-vectorize -isysroot /Developer/SDKs/MacOSX10.7.sdk -arch i386 -arch x86_64 -I../vamp-plugin-sdk -I/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/Headers/ -DUSE_PTHREADS + +CXXFLAGS := $(CFLAGS) + +LDFLAGS := -isysroot /Developer/SDKs/MacOSX10.7.sdk -arch i386 -arch x86_64 -lqm-dsp ../vamp-plugin-sdk/libvamp-sdk.a -larmadillo -dynamiclib -framework Accelerate -lpthread -install_name qm-vamp-plugins.dylib + +PLUGIN_EXT := .dylib + +include build/general/Makefile.inc +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/README.txt Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,87 @@ + +QM Vamp Plugins +=============== + +Vamp audio feature extraction plugins from the Centre for Digital +Music at Queen Mary, University of London. + +http://www.elec.qmul.ac.uk/digitalmusic/ + +Version 1.7. + +For more information about Vamp plugins, see http://www.vamp-plugins.org/ . + + +About This Release +================== + +This release corresponds to a change in the licensing terms under +which the QM plugins are published (from a closed-source license to +the GPL). It contains no new functionality over 1.6. + + +Plugins Included +================ + +This plugin set includes the following plugins: + + * Note onset detector + + * Beat tracker and tempo estimator + + * Key estimator and tonal change detector + + * Adaptive multi-resolution FFT spectrogram + + * Polyphonic note transcription estimator + + * Segmenter, to divide a track into a consistent sequence of segments + + * Timbral and rhythmic similarity between audio tracks + + * Wavelet scalogram (discrete wavelet transform) + + * Chromagram, constant-Q spectrogram, and MFCC calculation plugins + +For full details about the plugins, with references, please see + + http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html + + +License +======= + +These plugins are provided under the terms of the GNU General Public +License. You may install and use the plugin binaries without fee for +any purpose commercial or non-commercial. You may also modify and +redistribute the plugins in source or binary form, provided you comply +with the terms given by the GNU General Public License. See the file +COPYING for more details. + +If you wish to use these plugins in a proprietary application or +product for which the terms of the GPL are not appropriate, please +contact the Centre for Digital Music at Queen Mary, University of +London for further licensing terms. + +Copyright (c) 2006-2011 Queen Mary, University of London. + + +To Install +========== + +Installation depends on your operating system. + + Win 32 -> Copy qm-vamp-plugins.dll, qm-vamp-plugins.cat and + qm-vamp-plugins.n3 to C:\Program Files\Vamp Plugins\ + + Win 64 -> Copy qm-vamp-plugins.dll, qm-vamp-plugins.cat and + qm-vamp-plugins.n3 to C:\Program Files\Vamp Plugins (x86)\ + + OS/X -> Copy qm-vamp-plugins.dylib, qm-vamp-plugins.cat and + qm-vamp-plugins.n3 to $HOME/Library/Audio/Plug-Ins/Vamp/ + or /Library/Audio/Plug-Ins/Vamp/ + + Linux -> Copy qm-vamp-plugins.so, qm-vamp-plugins.cat and + qm-vamp-plugins.n3 to $HOME/vamp/ or /usr/local/lib/vamp/ + or /usr/lib/vamp/ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/general/Makefile.inc Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,55 @@ + +PLUGIN_EXT ?= .so +PLUGIN ?= qm-vamp-plugins$(PLUGIN_EXT) +CXX ?= g++ +CC ?= gcc + +CFLAGS := $(CFLAGS) -I. -I../qm-dsp -I../nnls-chroma +CXXFLAGS := $(CXXFLAGS) -I. -I../qm-dsp -I../nnls-chroma +LDFLAGS := -L../qm-dsp $(LDFLAGS) + +HEADERS := plugins/AdaptiveSpectrogram.h \ + plugins/BarBeatTrack.h \ + plugins/BeatTrack.h \ + plugins/DWT.h \ + plugins/OnsetDetect.h \ + plugins/ChromagramPlugin.h \ + plugins/ConstantQSpectrogram.h \ + plugins/KeyDetect.h \ + plugins/MFCCPlugin.h \ + plugins/SegmenterPlugin.h \ + plugins/SimilarityPlugin.h \ + plugins/SongParts.h \ + plugins/TonalChangeDetect.h \ + plugins/Transcription.h + +SOURCES := g2cstubs.c \ + plugins/AdaptiveSpectrogram.cpp \ + plugins/BarBeatTrack.cpp \ + plugins/BeatTrack.cpp \ + plugins/DWT.cpp \ + plugins/OnsetDetect.cpp \ + plugins/ChromagramPlugin.cpp \ + plugins/ConstantQSpectrogram.cpp \ + plugins/KeyDetect.cpp \ + plugins/MFCCPlugin.cpp \ + plugins/SegmenterPlugin.cpp \ + plugins/SongParts.cpp \ + plugins/SimilarityPlugin.cpp \ + plugins/TonalChangeDetect.cpp \ + plugins/Transcription.cpp \ + libmain.cpp \ + ../nnls-chroma/chromamethods.cpp \ + ../nnls-chroma/nnls.c + +OBJECTS := $(SOURCES:.cpp=.o) +OBJECTS := $(OBJECTS:.c=.o) + +$(PLUGIN): $(OBJECTS) + $(CXX) -o $@ $^ $(LDFLAGS) + +clean: + rm $(OBJECTS) + +distclean: clean + rm $(PLUGIN)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/general/Makefile.inc_original Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,55 @@ + +PLUGIN_EXT ?= .so +PLUGIN ?= qm-vamp-plugins$(PLUGIN_EXT) +CXX ?= g++ +CC ?= gcc + +CFLAGS := $(CFLAGS) -I. -I../qm-dsp -I../nnls-chroma +CXXFLAGS := $(CXXFLAGS) -I. -I../qm-dsp -I../nnls-chroma +LDFLAGS := -L../qm-dsp $(LDFLAGS) + +HEADERS := plugins/AdaptiveSpectrogram.h \ + plugins/BarBeatTrack.h \ + plugins/BeatTrack.h \ + plugins/DWT.h \ + plugins/OnsetDetect.h \ + plugins/ChromagramPlugin.h \ + plugins/ConstantQSpectrogram.h \ + plugins/KeyDetect.h \ + plugins/MFCCPlugin.h \ + plugins/SegmenterPlugin.h \ + plugins/SimilarityPlugin.h \ + plugins/SongParts.h \ + plugins/TonalChangeDetect.h \ + plugins/Transcription.h + +SOURCES := g2cstubs.c \ + plugins/AdaptiveSpectrogram.cpp \ + plugins/BarBeatTrack.cpp \ + plugins/BeatTrack.cpp \ + plugins/DWT.cpp \ + plugins/OnsetDetect.cpp \ + plugins/ChromagramPlugin.cpp \ + plugins/ConstantQSpectrogram.cpp \ + plugins/KeyDetect.cpp \ + plugins/MFCCPlugin.cpp \ + plugins/SegmenterPlugin.cpp \ + plugins/SongParts.cpp \ + plugins/SimilarityPlugin.cpp \ + plugins/TonalChangeDetect.cpp \ + plugins/Transcription.cpp \ + libmain.cpp \ + ../nnls-chroma/chromamethods.cpp \ + ../nnls-chroma/nnls.c + +OBJECTS := $(SOURCES:.cpp=.o) +OBJECTS := $(OBJECTS:.c=.o) + +$(PLUGIN): $(OBJECTS) + $(CXX) -o $@ $^ $(LDFLAGS) + +clean: + rm $(OBJECTS) + +distclean: clean + rm $(PLUGIN)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/Makefile.linux Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,11 @@ + +CFLAGS := -DNDEBUG -O3 -fno-exceptions -fPIC -ffast-math -msse -mfpmath=sse -ftree-vectorize -fomit-frame-pointer -DUSE_PTHREADS + +CXXFLAGS := $(CFLAGS) + +LDFLAGS := -Wl,-Bstatic -lqm-dsp -lvamp-sdk -L/usr/lib/sse2/atlas -L/usr/lib/atlas/sse -llapack -lblas -Wl,-Bdynamic -lpthread -Wl,--version-script=vamp-plugin.map + +PLUGIN_EXT := .so + +include build/general/Makefile.inc +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/Makefile.linux64 Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,11 @@ + +CFLAGS := -DNDEBUG -O3 -fno-exceptions -fPIC -ffast-math -msse -msse2 -mfpmath=sse -ftree-vectorize -fomit-frame-pointer -DUSE_PTHREADS + +CXXFLAGS := $(CFLAGS) + +LDFLAGS := -shared -Lbuild/linux/amd64 -Wl,-Bstatic -lqm-dsp -lvamp-sdk -L/usr/lib/sse2/atlas -L/usr/lib/atlas/sse -llapack -lcblas -latlas -Wl,-Bdynamic -lpthread -Wl,--version-script=vamp-plugin.map + +PLUGIN_EXT := .so + +include build/general/Makefile.inc +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_buildinfo.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,31 @@ +#ifndef ATL_INSTINFO_H + #define ATL_INSTINFO_H + +#define ATL_ARCH "Core2Duo64SSE3" +#define ATL_INSTFLAGS "-1 0 -a 1" +#define ATL_F2CDEFS "-DAdd__ -DF77_INTEGER=int -DStringSunStyle" +#define ATL_ARCHDEFS "-DATL_OS_Linux -DATL_ARCH_Core2Duo -DATL_CPUMHZ=1500 -DATL_SSE3 -DATL_SSE2 -DATL_SSE1 -DATL_USE64BITS -DATL_GAS_x8664" +#define ATL_DKCFLAGS "-fomit-frame-pointer -mfpmath=sse -msse3 -O2 -fPIC -m64" +#define ATL_DKC "gcc" +#define ATL_SKCFLAGS "-fomit-frame-pointer -mfpmath=sse -msse3 -O2 -fPIC -m64" +#define ATL_SKC "gcc" +#define ATL_DMCFLAGS "-fomit-frame-pointer -mfpmath=sse -msse3 -O2 -fPIC -m64" +#define ATL_DMC "gcc" +#define ATL_SMCFLAGS "-fomit-frame-pointer -mfpmath=sse -msse3 -O2 -fPIC -m64" +#define ATL_SMC "gcc" +#define ATL_ICCFLAGS "-DL2SIZE=4194304 -I/home/cannam/ATLAS/build/include -I/home/cannam/ATLAS/build/..//include -I/home/cannam/ATLAS/build/..//include/contrib -DAdd__ -DF77_INTEGER=int -DStringSunStyle -DATL_OS_Linux -DATL_ARCH_Core2Duo -DATL_CPUMHZ=1500 -DATL_SSE3 -DATL_SSE2 -DATL_SSE1 -DATL_USE64BITS -DATL_GAS_x8664 -DPentiumCPS=1000 -fomit-frame-pointer -mfpmath=sse -msse3 -O2 -fPIC -m64" +#define ATL_ICC "gcc-4.2" +#define ATL_F77FLAGS "-O -fPIC -m64" +#define ATL_F77 "g77" +#define ATL_DKCVERS "gcc (GCC) 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)" +#define ATL_SKCVERS "gcc (GCC) 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)" +#define ATL_DMCVERS "gcc (GCC) 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)" +#define ATL_SMCVERS "gcc (GCC) 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)" +#define ATL_ICCVERS "gcc-4.2 (GCC) 4.2.1 (Ubuntu 4.2.1-5ubuntu4)" +#define ATL_F77VERS "GNU Fortran (GCC) 3.4.6 (Ubuntu 3.4.6-6ubuntu2)" +#define ATL_SYSINFO "Linux yves-laptop 2.6.22-14-generic #1 SMP Thu Jan 31 23:33:13 UTC 2008 x86_64 GNU/Linux" +#define ATL_DATE "Wed Feb 13 11:25:06 GMT 2008" +#define ATL_UNAM "cannam" +#define ATL_VERS "3.8.0" + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_cNCmm.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ +#ifndef CMM_H + #define CMM_H + + #define ATL_mmMULADD + #define ATL_mmLAT 1 + #define ATL_mmMU 12 + #define ATL_mmNU 1 + #define ATL_mmKU 72 + #define MB 48 + #define NB 48 + #define KB 48 + #define NBNB 2304 + #define MBNB 2304 + #define MBKB 2304 + #define NBKB 2304 + #define NB2 96 + #define NBNB2 4608 + + #define ATL_MulByNB(N_) ((N_) * 48) + #define ATL_DivByNB(N_) ((N_) / 48) + #define ATL_MulByNBNB(N_) ((N_) * 2304) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_cacheedge.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,4 @@ +#ifndef ATLAS_CACHEEDGE_H + #define ATLAS_CACHEEDGE_H + #define CacheEdge 0 +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_cmv.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,9 @@ +#ifndef ATLAS_CMV_H +#define ATLAS_CMV_H + +#define ATL_L1mvelts 3932 +#include "atlas_cmvN.h" +#include "atlas_cmvT.h" +#include "atlas_cmvS.h" + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_cmvN.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,21 @@ +#ifndef ATLAS_MVN_H +#define ATLAS_MVN_H + +#include "atlas_misc.h" + +#define ATL_mvNMU 32 +#define ATL_mvNNU 1 +#ifndef ATL_L1mvelts + #define ATL_L1mvelts ((3*ATL_L1elts)>>2) +#endif +#define ATL_AXPYMV + +#define ATL_GetPartMVN(A_, lda_, mb_, nb_) \ +{ \ + *(mb_) = (ATL_L1mvelts - (ATL_mvNNU<<1)) / ((ATL_mvNNU<<1)+1); \ + if (*(mb_) > ATL_mvNMU) *(mb_) = ATL_mvNMU*( *(mb_)/ATL_mvNMU ); \ + else *(mb_) = ATL_mvNMU; \ + *(nb_) = ATL_mvNNU; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_cmvS.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ +#ifndef ATLAS_MVS_H +#define ATLAS_MVS_H + +#include "atlas_misc.h" + +#define ATL_mvSMU 2 +#define ATL_mvSNU 32 +#ifndef ATL_L1mvelts + #define ATL_L1mvelts ((3*ATL_L1elts)>>2) +#endif +#ifndef ATL_mvNNU + #include "atlas_cmvN.h" +#endif +#ifndef ATL_mvTNU + #include "atlas_cmvT.h" +#endif +#define ATL_GetPartSYMV(A_, lda_, mb_, nb_) \ +{ \ + *(nb_) = ATL_mvSMU; \ + *(mb_) = 320; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_cmvT.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ +#ifndef ATLAS_MVT_H +#define ATLAS_MVT_H + +#include "atlas_misc.h" + +#define ATL_mvTMU 2 +#define ATL_mvTNU 8 +#ifndef ATL_L1mvelts + #define ATL_L1mvelts ((3*ATL_L1elts)>>2) +#endif +#ifndef ATL_mvNNU + #include "atlas_cmvN.h" +#endif + +#define ATL_GetPartMVT(A_, lda_, mb_, nb_) \ +{ \ + *(mb_) = (ATL_L1mvelts - (ATL_mvTMU<<1)) / ((ATL_mvTMU<<1)+1); \ + if (*(mb_) > ATL_mvTNU) *(mb_) = (*(mb_)/ATL_mvTNU)*ATL_mvTNU; \ + else (*mb_) = ATL_mvTNU; \ + *(nb_) = ATL_mvTMU; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_cr1.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,16 @@ +#ifndef ATLAS_CR1_H +#define ATLAS_CR1_H + +#define ATL_L1r1elts 3809 +#define ATL_r1MU 16 +#define ATL_r1NU 1 + +#define ATL_GetPartR1(A_, lda_, mb_, nb_) \ +{ \ + (mb_) = (ATL_L1r1elts - (ATL_r1NU+ATL_r1NU)) / (ATL_r1NU+ATL_r1NU+1); \ + if ((mb_) > ATL_r1MU) (mb_) = ATL_r1MU*((mb_)/ATL_r1MU); \ + else (mb_) = ATL_r1MU; \ + (nb_) = ATL_r1NU; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_csNKB.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,4 @@ +#ifndef ATLAS_CSNKB_H + #define ATLAS_CSNKB_H + #define ATL_CSNKB 0 +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_csysinfo.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,11 @@ +#ifndef ATL_CSYSINFO_H + #define ATL_CSYSINFO_H + +#define ATL_MULADD +#define ATL_L1elts 2048 +#define ATL_fplat 4 +#define ATL_lbnreg 16 +#define ATL_mmnreg 18 +#define ATL_nkflop 879334 + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_dNCmm.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ +#ifndef DMM_H + #define DMM_H + + #define ATL_mmNOMULADD + #define ATL_mmLAT 1 + #define ATL_mmMU 12 + #define ATL_mmNU 1 + #define ATL_mmKU 56 + #define MB 24 + #define NB 24 + #define KB 24 + #define NBNB 576 + #define MBNB 576 + #define MBKB 576 + #define NBKB 576 + #define NB2 48 + #define NBNB2 1152 + + #define ATL_MulByNB(N_) ((N_) * 24) + #define ATL_DivByNB(N_) ((N_) / 24) + #define ATL_MulByNBNB(N_) ((N_) * 576) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_dmv.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,9 @@ +#ifndef ATLAS_DMV_H +#define ATLAS_DMV_H + +#define ATL_L1mvelts 3317 +#include "atlas_dmvN.h" +#include "atlas_dmvT.h" +#include "atlas_dmvS.h" + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_dmvN.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,21 @@ +#ifndef ATLAS_MVN_H +#define ATLAS_MVN_H + +#include "atlas_misc.h" + +#define ATL_mvNMU 32 +#define ATL_mvNNU 1 +#ifndef ATL_L1mvelts + #define ATL_L1mvelts ((3*ATL_L1elts)>>2) +#endif +#define ATL_AXPYMV + +#define ATL_GetPartMVN(A_, lda_, mb_, nb_) \ +{ \ + *(mb_) = (ATL_L1mvelts - (ATL_mvNNU<<1)) / ((ATL_mvNNU<<1)+1); \ + if (*(mb_) > ATL_mvNMU) *(mb_) = ATL_mvNMU*( *(mb_)/ATL_mvNMU ); \ + else *(mb_) = ATL_mvNMU; \ + *(nb_) = ATL_mvNNU; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_dmvS.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ +#ifndef ATLAS_MVS_H +#define ATLAS_MVS_H + +#include "atlas_misc.h" + +#define ATL_mvSMU 2 +#define ATL_mvSNU 32 +#ifndef ATL_L1mvelts + #define ATL_L1mvelts ((3*ATL_L1elts)>>2) +#endif +#ifndef ATL_mvNNU + #include "atlas_dmvN.h" +#endif +#ifndef ATL_mvTNU + #include "atlas_dmvT.h" +#endif +#define ATL_GetPartSYMV(A_, lda_, mb_, nb_) \ +{ \ + *(nb_) = ATL_mvSMU; \ + *(mb_) = 256; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_dmvT.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ +#ifndef ATLAS_MVT_H +#define ATLAS_MVT_H + +#include "atlas_misc.h" + +#define ATL_mvTMU 2 +#define ATL_mvTNU 16 +#ifndef ATL_L1mvelts + #define ATL_L1mvelts ((3*ATL_L1elts)>>2) +#endif +#ifndef ATL_mvNNU + #include "atlas_dmvN.h" +#endif + +#define ATL_GetPartMVT(A_, lda_, mb_, nb_) \ +{ \ + *(mb_) = (ATL_L1mvelts - (ATL_mvTMU<<1)) / ((ATL_mvTMU<<1)+1); \ + if (*(mb_) > ATL_mvTNU) *(mb_) = (*(mb_)/ATL_mvTNU)*ATL_mvTNU; \ + else (*mb_) = ATL_mvTNU; \ + *(nb_) = ATL_mvTMU; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_dr1.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,16 @@ +#ifndef ATLAS_DR1_H +#define ATLAS_DR1_H + +#define ATL_L1r1elts 3809 +#define ATL_r1MU 16 +#define ATL_r1NU 1 + +#define ATL_GetPartR1(A_, lda_, mb_, nb_) \ +{ \ + (mb_) = (ATL_L1r1elts - (ATL_r1NU+ATL_r1NU)) / (ATL_r1NU+ATL_r1NU+1); \ + if ((mb_) > ATL_r1MU) (mb_) = ATL_r1MU*((mb_)/ATL_r1MU); \ + else (mb_) = ATL_r1MU; \ + (nb_) = ATL_r1NU; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_dsysinfo.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,11 @@ +#ifndef ATL_DSYSINFO_H + #define ATL_DSYSINFO_H + +#define ATL_MULADD +#define ATL_L1elts 4096 +#define ATL_fplat 12 +#define ATL_lbnreg 16 +#define ATL_mmnreg 18 +#define ATL_nkflop 2159859 + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_sNCmm.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ +#ifndef SMM_H + #define SMM_H + + #define ATL_mmMULADD + #define ATL_mmLAT 1 + #define ATL_mmMU 12 + #define ATL_mmNU 1 + #define ATL_mmKU 80 + #define MB 36 + #define NB 36 + #define KB 36 + #define NBNB 1296 + #define MBNB 1296 + #define MBKB 1296 + #define NBKB 1296 + #define NB2 72 + #define NBNB2 2592 + + #define ATL_MulByNB(N_) ((N_) * 36) + #define ATL_DivByNB(N_) ((N_) / 36) + #define ATL_MulByNBNB(N_) ((N_) * 1296) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_smv.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,9 @@ +#ifndef ATLAS_SMV_H +#define ATLAS_SMV_H + +#define ATL_L1mvelts 7127 +#include "atlas_smvN.h" +#include "atlas_smvT.h" +#include "atlas_smvS.h" + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_smvN.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,21 @@ +#ifndef ATLAS_MVN_H +#define ATLAS_MVN_H + +#include "atlas_misc.h" + +#define ATL_mvNMU 32 +#define ATL_mvNNU 1 +#ifndef ATL_L1mvelts + #define ATL_L1mvelts ((3*ATL_L1elts)>>2) +#endif +#define ATL_AXPYMV + +#define ATL_GetPartMVN(A_, lda_, mb_, nb_) \ +{ \ + *(mb_) = (ATL_L1mvelts - (ATL_mvNNU<<1)) / ((ATL_mvNNU<<1)+1); \ + if (*(mb_) > ATL_mvNMU) *(mb_) = ATL_mvNMU*( *(mb_)/ATL_mvNMU ); \ + else *(mb_) = ATL_mvNMU; \ + *(nb_) = ATL_mvNNU; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_smvS.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ +#ifndef ATLAS_MVS_H +#define ATLAS_MVS_H + +#include "atlas_misc.h" + +#define ATL_mvSMU 2 +#define ATL_mvSNU 32 +#ifndef ATL_L1mvelts + #define ATL_L1mvelts ((3*ATL_L1elts)>>2) +#endif +#ifndef ATL_mvNNU + #include "atlas_smvN.h" +#endif +#ifndef ATL_mvTNU + #include "atlas_smvT.h" +#endif +#define ATL_GetPartSYMV(A_, lda_, mb_, nb_) \ +{ \ + *(nb_) = ATL_mvSMU; \ + *(mb_) = 576; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_smvT.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ +#ifndef ATLAS_MVT_H +#define ATLAS_MVT_H + +#include "atlas_misc.h" + +#define ATL_mvTMU 2 +#define ATL_mvTNU 16 +#ifndef ATL_L1mvelts + #define ATL_L1mvelts ((3*ATL_L1elts)>>2) +#endif +#ifndef ATL_mvNNU + #include "atlas_smvN.h" +#endif + +#define ATL_GetPartMVT(A_, lda_, mb_, nb_) \ +{ \ + *(mb_) = (ATL_L1mvelts - (ATL_mvTMU<<1)) / ((ATL_mvTMU<<1)+1); \ + if (*(mb_) > ATL_mvTNU) *(mb_) = (*(mb_)/ATL_mvTNU)*ATL_mvTNU; \ + else (*mb_) = ATL_mvTNU; \ + *(nb_) = ATL_mvTMU; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_sr1.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,16 @@ +#ifndef ATLAS_SR1_H +#define ATLAS_SR1_H + +#define ATL_L1r1elts 7127 +#define ATL_r1MU 16 +#define ATL_r1NU 1 + +#define ATL_GetPartR1(A_, lda_, mb_, nb_) \ +{ \ + (mb_) = (ATL_L1r1elts - (ATL_r1NU+ATL_r1NU)) / (ATL_r1NU+ATL_r1NU+1); \ + if ((mb_) > ATL_r1MU) (mb_) = ATL_r1MU*((mb_)/ATL_r1MU); \ + else (mb_) = ATL_r1MU; \ + (nb_) = ATL_r1NU; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_ssysinfo.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,11 @@ +#ifndef ATL_SSYSINFO_H + #define ATL_SSYSINFO_H + +#define ATL_MULADD +#define ATL_L1elts 8192 +#define ATL_fplat 4 +#define ATL_lbnreg 16 +#define ATL_mmnreg 18 +#define ATL_nkflop 879334 + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_trsmNB.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,12 @@ +#ifndef ATLAS_TRSMNB_H + #define ATLAS_TRSMNB_H + + #ifdef SREAL + #define TRSM_NB 60 + #elif defined(DREAL) + #define TRSM_NB 12 + #else + #define TRSM_NB 4 + #endif + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_type.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,20 @@ +#ifndef ATLAS_TYPE_H +#define ATLAS_TYPE_H + +#define ATL_isize 4 +#define ATL_ssize 4 +#define ATL_dsize 8 +#define ATL_csize 8 +#define ATL_zsize 16 +#define ATL_iMulBySize(N_) ((((N_)) << 2)) +#define ATL_sMulBySize(N_) ((((N_)) << 2)) +#define ATL_dMulBySize(N_) ((((N_)) << 3)) +#define ATL_cMulBySize(N_) ((((N_)) << 3)) +#define ATL_zMulBySize(N_) ((((N_)) << 4)) +#define ATL_iDivBySize(N_) ((N_) >> 2) +#define ATL_sDivBySize(N_) ((N_) >> 2) +#define ATL_cDivBySize(N_) ((N_) >> 3) +#define ATL_dDivBySize(N_) ((N_) >> 3) +#define ATL_zDivBySize(N_) ((N_) >> 4) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_zNCmm.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ +#ifndef ZMM_H + #define ZMM_H + + #define ATL_mmMULADD + #define ATL_mmLAT 1 + #define ATL_mmMU 12 + #define ATL_mmNU 1 + #define ATL_mmKU 48 + #define MB 36 + #define NB 36 + #define KB 36 + #define NBNB 1296 + #define MBNB 1296 + #define MBKB 1296 + #define NBKB 1296 + #define NB2 72 + #define NBNB2 2592 + + #define ATL_MulByNB(N_) ((N_) * 36) + #define ATL_DivByNB(N_) ((N_) / 36) + #define ATL_MulByNBNB(N_) ((N_) * 1296) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_zdNKB.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,4 @@ +#ifndef ATLAS_ZDNKB_H + #define ATLAS_ZDNKB_H + #define ATL_ZDNKB 0 +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_zmv.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,9 @@ +#ifndef ATLAS_ZMV_H +#define ATLAS_ZMV_H + +#define ATL_L1mvelts 2048 +#include "atlas_zmvN.h" +#include "atlas_zmvT.h" +#include "atlas_zmvS.h" + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_zmvN.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,21 @@ +#ifndef ATLAS_MVN_H +#define ATLAS_MVN_H + +#include "atlas_misc.h" + +#define ATL_mvNMU 32 +#define ATL_mvNNU 1 +#ifndef ATL_L1mvelts + #define ATL_L1mvelts ((3*ATL_L1elts)>>2) +#endif +#define ATL_AXPYMV + +#define ATL_GetPartMVN(A_, lda_, mb_, nb_) \ +{ \ + *(mb_) = (ATL_L1mvelts - (ATL_mvNNU<<1)) / ((ATL_mvNNU<<1)+1); \ + if (*(mb_) > ATL_mvNMU) *(mb_) = ATL_mvNMU*( *(mb_)/ATL_mvNMU ); \ + else *(mb_) = ATL_mvNMU; \ + *(nb_) = ATL_mvNNU; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_zmvS.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ +#ifndef ATLAS_MVS_H +#define ATLAS_MVS_H + +#include "atlas_misc.h" + +#define ATL_mvSMU 2 +#define ATL_mvSNU 32 +#ifndef ATL_L1mvelts + #define ATL_L1mvelts ((3*ATL_L1elts)>>2) +#endif +#ifndef ATL_mvNNU + #include "atlas_zmvN.h" +#endif +#ifndef ATL_mvTNU + #include "atlas_zmvT.h" +#endif +#define ATL_GetPartSYMV(A_, lda_, mb_, nb_) \ +{ \ + *(nb_) = ATL_mvSMU; \ + *(mb_) = 160; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_zmvT.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,23 @@ +#ifndef ATLAS_MVT_H +#define ATLAS_MVT_H + +#include "atlas_misc.h" + +#define ATL_mvTMU 2 +#define ATL_mvTNU 8 +#ifndef ATL_L1mvelts + #define ATL_L1mvelts ((3*ATL_L1elts)>>2) +#endif +#ifndef ATL_mvNNU + #include "atlas_zmvN.h" +#endif + +#define ATL_GetPartMVT(A_, lda_, mb_, nb_) \ +{ \ + *(mb_) = (ATL_L1mvelts - (ATL_mvTMU<<1)) / ((ATL_mvTMU<<1)+1); \ + if (*(mb_) > ATL_mvTNU) *(mb_) = (*(mb_)/ATL_mvTNU)*ATL_mvTNU; \ + else (*mb_) = ATL_mvTNU; \ + *(nb_) = ATL_mvTMU; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_zr1.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,16 @@ +#ifndef ATLAS_ZR1_H +#define ATLAS_ZR1_H + +#define ATL_L1r1elts 2048 +#define ATL_r1MU 16 +#define ATL_r1NU 1 + +#define ATL_GetPartR1(A_, lda_, mb_, nb_) \ +{ \ + (mb_) = (ATL_L1r1elts - (ATL_r1NU+ATL_r1NU)) / (ATL_r1NU+ATL_r1NU+1); \ + if ((mb_) > ATL_r1MU) (mb_) = ATL_r1MU*((mb_)/ATL_r1MU); \ + else (mb_) = ATL_r1MU; \ + (nb_) = ATL_r1NU; \ +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/atlas_zsysinfo.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,11 @@ +#ifndef ATL_ZSYSINFO_H + #define ATL_ZSYSINFO_H + +#define ATL_MULADD +#define ATL_L1elts 4096 +#define ATL_fplat 12 +#define ATL_lbnreg 16 +#define ATL_mmnreg 18 +#define ATL_nkflop 2159859 + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/cXover.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,27 @@ +#ifndef CXOVER_H +#define CXOVER_H + +#define ATL_3NB 216 +#define NN_MNK_M 7200 +#define NN_MNK_N 7200 +#define NN_MNK_MN 51840 +#define NN_MNK_K 16200 +#define NN_MNK_GE 1000 +#define NT_MNK_M 7200 +#define NT_MNK_N 7200 +#define NT_MNK_MN 51840 +#define NT_MNK_K 16200 +#define NT_MNK_GE 1000 +#define TN_MNK_M 7200 +#define TN_MNK_N 7200 +#define TN_MNK_MN 51840 +#define TN_MNK_K 41472 +#define TN_MNK_GE 3375 +#define TT_MNK_M 7200 +#define TT_MNK_N 7200 +#define TT_MNK_MN 51840 +#define TT_MNK_K 16200 +#define TT_MNK_GE 1000 +#define C2R_K 278 + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/cmm.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,51 @@ +#ifndef CMM_H + #define CMM_H + + #define ATL_mmMULADD + #define ATL_mmLAT 1 + #define ATL_mmMU 12 + #define ATL_mmNU 1 + #define ATL_mmKU 72 + #define MB 72 + #define NB 72 + #define KB 72 + #define NBNB 5184 + #define MBNB 5184 + #define MBKB 5184 + #define NBKB 5184 + #define NB2 144 + #define NBNB2 10368 + + #define ATL_MulByNB(N_) ((N_) * 72) + #define ATL_DivByNB(N_) ((N_) / 72) + #define ATL_MulByNBNB(N_) ((N_) * 5184) +void ATL_cJIK72x72x72TN72x72x0_a1_b0(const int M, const int N, const int K, const TYPE alpha, const TYPE *A, const int lda, const TYPE *B, const int ldb, const TYPE beta, TYPE *C, const int ldc); +void ATL_cJIK72x72x72TN72x72x0_a1_b1(const int M, const int N, const int K, const TYPE alpha, const TYPE *A, const int lda, const TYPE *B, const int ldb, const TYPE beta, TYPE *C, const int ldc); +void ATL_cJIK72x72x72TN72x72x0_a1_bX(const int M, const int N, const int K, const TYPE alpha, const TYPE *A, const int lda, const TYPE *B, const int ldb, const TYPE beta, TYPE *C, const int ldc); + + #define NBmm_b1(m_, n_, k_, al_, A_, lda_, B_, ldb_, be_, C_, ldc_) \ +{ \ + ATL_cJIK72x72x72TN72x72x0_a1_bX(m_, n_, k_, al_, (A_), lda_, (B_), ldb_, ATL_rnone, C_, ldc_); \ + ATL_cJIK72x72x72TN72x72x0_a1_b1(m_, n_, k_, al_, (A_), lda_, (B_)+NBNB, ldb_, ATL_rone, (C_)+1, ldc_); \ + ATL_cJIK72x72x72TN72x72x0_a1_bX(m_, n_, k_, al_, (A_)+NBNB, lda_, (B_)+NBNB, ldb_, ATL_rnone, C_, ldc_); \ + ATL_cJIK72x72x72TN72x72x0_a1_b1(m_, n_, k_, al_, (A_)+NBNB, lda_, (B_), ldb_, ATL_rone, (C_)+1, ldc_); \ + } + #define NBmm_b0(m_, n_, k_, al_, A_, lda_, B_, ldb_, be_, C_, ldc_) \ +{ \ + ATL_cJIK72x72x72TN72x72x0_a1_b0(m_, n_, k_, al_, (A_), lda_, (B_), ldb_, ATL_rzero, C_, ldc_); \ + ATL_cJIK72x72x72TN72x72x0_a1_b0(m_, n_, k_, al_, (A_), lda_, (B_)+NBNB, ldb_, ATL_rzero, (C_)+1, ldc_); \ + ATL_cJIK72x72x72TN72x72x0_a1_bX(m_, n_, k_, al_, (A_)+NBNB, lda_, (B_)+NBNB, ldb_, ATL_rnone, C_, ldc_); \ + ATL_cJIK72x72x72TN72x72x0_a1_b1(m_, n_, k_, al_, (A_)+NBNB, lda_, (B_), ldb_, ATL_rone, (C_)+1, ldc_); \ + } + #define NBmm_bX(m_, n_, k_, al_, A_, lda_, B_, ldb_, be_, C_, ldc_) \ +{ \ + ATL_cJIK72x72x72TN72x72x0_a1_bX(m_, n_, k_, al_, (A_), lda_, (B_), ldb_, -(be_), C_, ldc_); \ + ATL_cJIK72x72x72TN72x72x0_a1_bX(m_, n_, k_, al_, (A_), lda_, (B_)+NBNB, ldb_, be_, (C_)+1, ldc_); \ + ATL_cJIK72x72x72TN72x72x0_a1_bX(m_, n_, k_, al_, (A_)+NBNB, lda_, (B_)+NBNB, ldb_, ATL_rnone, C_, ldc_); \ + ATL_cJIK72x72x72TN72x72x0_a1_b1(m_, n_, k_, al_, (A_)+NBNB, lda_, (B_), ldb_, ATL_rone, (C_)+1, ldc_); \ + } + #define rNBmm_b1 ATL_sJIK72x72x72TN72x72x0_a1_b1 + #define rNBmm_b0 ATL_sJIK72x72x72TN72x72x0_a1_b0 + #define rNBmm_bX ATL_sJIK72x72x72TN72x72x0_a1_bX + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/dXover.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,26 @@ +#ifndef DXOVER_H +#define DXOVER_H + +#define ATL_3NB 168 +#define NN_MNK_M 5600 +#define NN_MNK_N 12600 +#define NN_MNK_MN 31360 +#define NN_MNK_K 80864 +#define NN_MNK_GE 13824 +#define NT_MNK_M 5600 +#define NT_MNK_N 5600 +#define NT_MNK_MN 31360 +#define NT_MNK_K 32256 +#define NT_MNK_GE 3375 +#define TN_MNK_M 5600 +#define TN_MNK_N 5600 +#define TN_MNK_MN 31360 +#define TN_MNK_K 80864 +#define TN_MNK_GE 13824 +#define TT_MNK_M 5600 +#define TT_MNK_N 12600 +#define TT_MNK_MN 31360 +#define TT_MNK_K 32256 +#define TT_MNK_GE 3375 + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/dmm.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,27 @@ +#ifndef DMM_H + #define DMM_H + + #define ATL_mmNOMULADD + #define ATL_mmLAT 1 + #define ATL_mmMU 12 + #define ATL_mmNU 1 + #define ATL_mmKU 56 + #define MB 56 + #define NB 56 + #define KB 56 + #define NBNB 3136 + #define MBNB 3136 + #define MBKB 3136 + #define NBKB 3136 + #define NB2 112 + #define NBNB2 6272 + + #define ATL_MulByNB(N_) ((N_) * 56) + #define ATL_DivByNB(N_) ((N_) / 56) + #define ATL_MulByNBNB(N_) ((N_) * 3136) + #define NBmm ATL_dJIK56x56x56TN56x56x0_a1_b1 + #define NBmm_b1 ATL_dJIK56x56x56TN56x56x0_a1_b1 + #define NBmm_b0 ATL_dJIK56x56x56TN56x56x0_a1_b0 + #define NBmm_bX ATL_dJIK56x56x56TN56x56x0_a1_bX + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/sXover.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,26 @@ +#ifndef SXOVER_H +#define SXOVER_H + +#define ATL_3NB 216 +#define NN_MNK_M 7200 +#define NN_MNK_N 16200 +#define NN_MNK_MN 51840 +#define NN_MNK_K 41472 +#define NN_MNK_GE 13824 +#define NT_MNK_M 7200 +#define NT_MNK_N 7200 +#define NT_MNK_MN 51840 +#define NT_MNK_K 16200 +#define NT_MNK_GE 3375 +#define TN_MNK_M 7200 +#define TN_MNK_N 16200 +#define TN_MNK_MN 51840 +#define TN_MNK_K 352800 +#define TN_MNK_GE 27000 +#define TT_MNK_M 7200 +#define TT_MNK_N 7200 +#define TT_MNK_MN 51840 +#define TT_MNK_K 41472 +#define TT_MNK_GE 3375 + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/smm.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,27 @@ +#ifndef SMM_H + #define SMM_H + + #define ATL_mmMULADD + #define ATL_mmLAT 1 + #define ATL_mmMU 12 + #define ATL_mmNU 1 + #define ATL_mmKU 80 + #define MB 80 + #define NB 80 + #define KB 80 + #define NBNB 6400 + #define MBNB 6400 + #define MBKB 6400 + #define NBKB 6400 + #define NB2 160 + #define NBNB2 12800 + + #define ATL_MulByNB(N_) ((N_) * 80) + #define ATL_DivByNB(N_) ((N_) / 80) + #define ATL_MulByNBNB(N_) ((N_) * 6400) + #define NBmm ATL_sJIK80x80x80TN80x80x0_a1_b1 + #define NBmm_b1 ATL_sJIK80x80x80TN80x80x0_a1_b1 + #define NBmm_b0 ATL_sJIK80x80x80TN80x80x0_a1_b0 + #define NBmm_bX ATL_sJIK80x80x80TN80x80x0_a1_bX + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/zXover.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,27 @@ +#ifndef ZXOVER_H +#define ZXOVER_H + +#define ATL_3NB 144 +#define NN_MNK_M 4800 +#define NN_MNK_N 4800 +#define NN_MNK_MN 23040 +#define NN_MNK_K 4800 +#define NN_MNK_GE 1000 +#define NT_MNK_M 4800 +#define NT_MNK_N 4800 +#define NT_MNK_MN 23040 +#define NT_MNK_K 4800 +#define NT_MNK_GE 1000 +#define TN_MNK_M 4800 +#define TN_MNK_N 4800 +#define TN_MNK_MN 23040 +#define TN_MNK_K 10800 +#define TN_MNK_GE 1000 +#define TT_MNK_M 4800 +#define TT_MNK_N 4800 +#define TT_MNK_MN 23040 +#define TT_MNK_K 10800 +#define TT_MNK_GE 1000 +#define C2R_K 570 + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/atlas/zmm.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,51 @@ +#ifndef ZMM_H + #define ZMM_H + + #define ATL_mmMULADD + #define ATL_mmLAT 1 + #define ATL_mmMU 12 + #define ATL_mmNU 1 + #define ATL_mmKU 48 + #define MB 48 + #define NB 48 + #define KB 48 + #define NBNB 2304 + #define MBNB 2304 + #define MBKB 2304 + #define NBKB 2304 + #define NB2 96 + #define NBNB2 4608 + + #define ATL_MulByNB(N_) ((N_) * 48) + #define ATL_DivByNB(N_) ((N_) / 48) + #define ATL_MulByNBNB(N_) ((N_) * 2304) +void ATL_zJIK48x48x48TN48x48x0_a1_b0(const int M, const int N, const int K, const TYPE alpha, const TYPE *A, const int lda, const TYPE *B, const int ldb, const TYPE beta, TYPE *C, const int ldc); +void ATL_zJIK48x48x48TN48x48x0_a1_b1(const int M, const int N, const int K, const TYPE alpha, const TYPE *A, const int lda, const TYPE *B, const int ldb, const TYPE beta, TYPE *C, const int ldc); +void ATL_zJIK48x48x48TN48x48x0_a1_bX(const int M, const int N, const int K, const TYPE alpha, const TYPE *A, const int lda, const TYPE *B, const int ldb, const TYPE beta, TYPE *C, const int ldc); + + #define NBmm_b1(m_, n_, k_, al_, A_, lda_, B_, ldb_, be_, C_, ldc_) \ +{ \ + ATL_zJIK48x48x48TN48x48x0_a1_bX(m_, n_, k_, al_, (A_), lda_, (B_), ldb_, ATL_rnone, C_, ldc_); \ + ATL_zJIK48x48x48TN48x48x0_a1_b1(m_, n_, k_, al_, (A_), lda_, (B_)+NBNB, ldb_, ATL_rone, (C_)+1, ldc_); \ + ATL_zJIK48x48x48TN48x48x0_a1_bX(m_, n_, k_, al_, (A_)+NBNB, lda_, (B_)+NBNB, ldb_, ATL_rnone, C_, ldc_); \ + ATL_zJIK48x48x48TN48x48x0_a1_b1(m_, n_, k_, al_, (A_)+NBNB, lda_, (B_), ldb_, ATL_rone, (C_)+1, ldc_); \ + } + #define NBmm_b0(m_, n_, k_, al_, A_, lda_, B_, ldb_, be_, C_, ldc_) \ +{ \ + ATL_zJIK48x48x48TN48x48x0_a1_b0(m_, n_, k_, al_, (A_), lda_, (B_), ldb_, ATL_rzero, C_, ldc_); \ + ATL_zJIK48x48x48TN48x48x0_a1_b0(m_, n_, k_, al_, (A_), lda_, (B_)+NBNB, ldb_, ATL_rzero, (C_)+1, ldc_); \ + ATL_zJIK48x48x48TN48x48x0_a1_bX(m_, n_, k_, al_, (A_)+NBNB, lda_, (B_)+NBNB, ldb_, ATL_rnone, C_, ldc_); \ + ATL_zJIK48x48x48TN48x48x0_a1_b1(m_, n_, k_, al_, (A_)+NBNB, lda_, (B_), ldb_, ATL_rone, (C_)+1, ldc_); \ + } + #define NBmm_bX(m_, n_, k_, al_, A_, lda_, B_, ldb_, be_, C_, ldc_) \ +{ \ + ATL_zJIK48x48x48TN48x48x0_a1_bX(m_, n_, k_, al_, (A_), lda_, (B_), ldb_, -(be_), C_, ldc_); \ + ATL_zJIK48x48x48TN48x48x0_a1_bX(m_, n_, k_, al_, (A_), lda_, (B_)+NBNB, ldb_, be_, (C_)+1, ldc_); \ + ATL_zJIK48x48x48TN48x48x0_a1_bX(m_, n_, k_, al_, (A_)+NBNB, lda_, (B_)+NBNB, ldb_, ATL_rnone, C_, ldc_); \ + ATL_zJIK48x48x48TN48x48x0_a1_b1(m_, n_, k_, al_, (A_)+NBNB, lda_, (B_), ldb_, ATL_rone, (C_)+1, ldc_); \ + } + #define rNBmm_b1 ATL_dJIK48x48x48TN48x48x0_a1_b1 + #define rNBmm_b0 ATL_dJIK48x48x48TN48x48x0_a1_b0 + #define rNBmm_bX ATL_dJIK48x48x48TN48x48x0_a1_bX + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/cblas.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,596 @@ +#ifndef CBLAS_H + +#ifndef CBLAS_ENUM_DEFINED_H + #define CBLAS_ENUM_DEFINED_H + enum CBLAS_ORDER {CblasRowMajor=101, CblasColMajor=102 }; + enum CBLAS_TRANSPOSE {CblasNoTrans=111, CblasTrans=112, CblasConjTrans=113, + AtlasConj=114}; + enum CBLAS_UPLO {CblasUpper=121, CblasLower=122}; + enum CBLAS_DIAG {CblasNonUnit=131, CblasUnit=132}; + enum CBLAS_SIDE {CblasLeft=141, CblasRight=142}; +#endif + +#ifndef CBLAS_ENUM_ONLY +#define CBLAS_H +#define CBLAS_INDEX int + +int cblas_errprn(int ierr, int info, char *form, ...); + +/* + * =========================================================================== + * Prototypes for level 1 BLAS functions (complex are recast as routines) + * =========================================================================== + */ +float cblas_sdsdot(const int N, const float alpha, const float *X, + const int incX, const float *Y, const int incY); +double cblas_dsdot(const int N, const float *X, const int incX, const float *Y, + const int incY); +float cblas_sdot(const int N, const float *X, const int incX, + const float *Y, const int incY); +double cblas_ddot(const int N, const double *X, const int incX, + const double *Y, const int incY); +/* + * Functions having prefixes Z and C only + */ +void cblas_cdotu_sub(const int N, const void *X, const int incX, + const void *Y, const int incY, void *dotu); +void cblas_cdotc_sub(const int N, const void *X, const int incX, + const void *Y, const int incY, void *dotc); + +void cblas_zdotu_sub(const int N, const void *X, const int incX, + const void *Y, const int incY, void *dotu); +void cblas_zdotc_sub(const int N, const void *X, const int incX, + const void *Y, const int incY, void *dotc); + + +/* + * Functions having prefixes S D SC DZ + */ +float cblas_snrm2(const int N, const float *X, const int incX); +float cblas_sasum(const int N, const float *X, const int incX); + +double cblas_dnrm2(const int N, const double *X, const int incX); +double cblas_dasum(const int N, const double *X, const int incX); + +float cblas_scnrm2(const int N, const void *X, const int incX); +float cblas_scasum(const int N, const void *X, const int incX); + +double cblas_dznrm2(const int N, const void *X, const int incX); +double cblas_dzasum(const int N, const void *X, const int incX); + + +/* + * Functions having standard 4 prefixes (S D C Z) + */ +CBLAS_INDEX cblas_isamax(const int N, const float *X, const int incX); +CBLAS_INDEX cblas_idamax(const int N, const double *X, const int incX); +CBLAS_INDEX cblas_icamax(const int N, const void *X, const int incX); +CBLAS_INDEX cblas_izamax(const int N, const void *X, const int incX); + +/* + * =========================================================================== + * Prototypes for level 1 BLAS routines + * =========================================================================== + */ + +/* + * Routines with standard 4 prefixes (s, d, c, z) + */ +void cblas_sswap(const int N, float *X, const int incX, + float *Y, const int incY); +void cblas_scopy(const int N, const float *X, const int incX, + float *Y, const int incY); +void cblas_saxpy(const int N, const float alpha, const float *X, + const int incX, float *Y, const int incY); +void catlas_saxpby(const int N, const float alpha, const float *X, + const int incX, const float beta, float *Y, const int incY); +void catlas_sset + (const int N, const float alpha, float *X, const int incX); + +void cblas_dswap(const int N, double *X, const int incX, + double *Y, const int incY); +void cblas_dcopy(const int N, const double *X, const int incX, + double *Y, const int incY); +void cblas_daxpy(const int N, const double alpha, const double *X, + const int incX, double *Y, const int incY); +void catlas_daxpby(const int N, const double alpha, const double *X, + const int incX, const double beta, double *Y, const int incY); +void catlas_dset + (const int N, const double alpha, double *X, const int incX); + +void cblas_cswap(const int N, void *X, const int incX, + void *Y, const int incY); +void cblas_ccopy(const int N, const void *X, const int incX, + void *Y, const int incY); +void cblas_caxpy(const int N, const void *alpha, const void *X, + const int incX, void *Y, const int incY); +void catlas_caxpby(const int N, const void *alpha, const void *X, + const int incX, const void *beta, void *Y, const int incY); +void catlas_cset + (const int N, const void *alpha, void *X, const int incX); + +void cblas_zswap(const int N, void *X, const int incX, + void *Y, const int incY); +void cblas_zcopy(const int N, const void *X, const int incX, + void *Y, const int incY); +void cblas_zaxpy(const int N, const void *alpha, const void *X, + const int incX, void *Y, const int incY); +void catlas_zaxpby(const int N, const void *alpha, const void *X, + const int incX, const void *beta, void *Y, const int incY); +void catlas_zset + (const int N, const void *alpha, void *X, const int incX); + + +/* + * Routines with S and D prefix only + */ +void cblas_srotg(float *a, float *b, float *c, float *s); +void cblas_srotmg(float *d1, float *d2, float *b1, const float b2, float *P); +void cblas_srot(const int N, float *X, const int incX, + float *Y, const int incY, const float c, const float s); +void cblas_srotm(const int N, float *X, const int incX, + float *Y, const int incY, const float *P); + +void cblas_drotg(double *a, double *b, double *c, double *s); +void cblas_drotmg(double *d1, double *d2, double *b1, const double b2, double *P); +void cblas_drot(const int N, double *X, const int incX, + double *Y, const int incY, const double c, const double s); +void cblas_drotm(const int N, double *X, const int incX, + double *Y, const int incY, const double *P); + + +/* + * Routines with S D C Z CS and ZD prefixes + */ +void cblas_sscal(const int N, const float alpha, float *X, const int incX); +void cblas_dscal(const int N, const double alpha, double *X, const int incX); +void cblas_cscal(const int N, const void *alpha, void *X, const int incX); +void cblas_zscal(const int N, const void *alpha, void *X, const int incX); +void cblas_csscal(const int N, const float alpha, void *X, const int incX); +void cblas_zdscal(const int N, const double alpha, void *X, const int incX); + +/* + * Extra reference routines provided by ATLAS, but not mandated by the standard + */ +void cblas_crotg(void *a, void *b, void *c, void *s); +void cblas_zrotg(void *a, void *b, void *c, void *s); +void cblas_csrot(const int N, void *X, const int incX, void *Y, const int incY, + const float c, const float s); +void cblas_zdrot(const int N, void *X, const int incX, void *Y, const int incY, + const double c, const double s); + +/* + * =========================================================================== + * Prototypes for level 2 BLAS + * =========================================================================== + */ + +/* + * Routines with standard 4 prefixes (S, D, C, Z) + */ +void cblas_sgemv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const float alpha, const float *A, const int lda, + const float *X, const int incX, const float beta, + float *Y, const int incY); +void cblas_sgbmv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const int KL, const int KU, const float alpha, + const float *A, const int lda, const float *X, + const int incX, const float beta, float *Y, const int incY); +void cblas_strmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const float *A, const int lda, + float *X, const int incX); +void cblas_stbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const float *A, const int lda, + float *X, const int incX); +void cblas_stpmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const float *Ap, float *X, const int incX); +void cblas_strsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const float *A, const int lda, float *X, + const int incX); +void cblas_stbsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const float *A, const int lda, + float *X, const int incX); +void cblas_stpsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const float *Ap, float *X, const int incX); + +void cblas_dgemv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const double alpha, const double *A, const int lda, + const double *X, const int incX, const double beta, + double *Y, const int incY); +void cblas_dgbmv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const int KL, const int KU, const double alpha, + const double *A, const int lda, const double *X, + const int incX, const double beta, double *Y, const int incY); +void cblas_dtrmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const double *A, const int lda, + double *X, const int incX); +void cblas_dtbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const double *A, const int lda, + double *X, const int incX); +void cblas_dtpmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const double *Ap, double *X, const int incX); +void cblas_dtrsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const double *A, const int lda, double *X, + const int incX); +void cblas_dtbsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const double *A, const int lda, + double *X, const int incX); +void cblas_dtpsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const double *Ap, double *X, const int incX); + +void cblas_cgemv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *X, const int incX, const void *beta, + void *Y, const int incY); +void cblas_cgbmv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const int KL, const int KU, const void *alpha, + const void *A, const int lda, const void *X, + const int incX, const void *beta, void *Y, const int incY); +void cblas_ctrmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *A, const int lda, + void *X, const int incX); +void cblas_ctbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const void *A, const int lda, + void *X, const int incX); +void cblas_ctpmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *Ap, void *X, const int incX); +void cblas_ctrsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *A, const int lda, void *X, + const int incX); +void cblas_ctbsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const void *A, const int lda, + void *X, const int incX); +void cblas_ctpsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *Ap, void *X, const int incX); + +void cblas_zgemv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *X, const int incX, const void *beta, + void *Y, const int incY); +void cblas_zgbmv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const int KL, const int KU, const void *alpha, + const void *A, const int lda, const void *X, + const int incX, const void *beta, void *Y, const int incY); +void cblas_ztrmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *A, const int lda, + void *X, const int incX); +void cblas_ztbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const void *A, const int lda, + void *X, const int incX); +void cblas_ztpmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *Ap, void *X, const int incX); +void cblas_ztrsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *A, const int lda, void *X, + const int incX); +void cblas_ztbsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const void *A, const int lda, + void *X, const int incX); +void cblas_ztpsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *Ap, void *X, const int incX); + + +/* + * Routines with S and D prefixes only + */ +void cblas_ssymv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const float *A, + const int lda, const float *X, const int incX, + const float beta, float *Y, const int incY); +void cblas_ssbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const int K, const float alpha, const float *A, + const int lda, const float *X, const int incX, + const float beta, float *Y, const int incY); +void cblas_sspmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const float *Ap, + const float *X, const int incX, + const float beta, float *Y, const int incY); +void cblas_sger(const enum CBLAS_ORDER Order, const int M, const int N, + const float alpha, const float *X, const int incX, + const float *Y, const int incY, float *A, const int lda); +void cblas_ssyr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const float *X, + const int incX, float *A, const int lda); +void cblas_sspr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const float *X, + const int incX, float *Ap); +void cblas_ssyr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const float *X, + const int incX, const float *Y, const int incY, float *A, + const int lda); +void cblas_sspr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const float *X, + const int incX, const float *Y, const int incY, float *A); + +void cblas_dsymv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const double *A, + const int lda, const double *X, const int incX, + const double beta, double *Y, const int incY); +void cblas_dsbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const int K, const double alpha, const double *A, + const int lda, const double *X, const int incX, + const double beta, double *Y, const int incY); +void cblas_dspmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const double *Ap, + const double *X, const int incX, + const double beta, double *Y, const int incY); +void cblas_dger(const enum CBLAS_ORDER Order, const int M, const int N, + const double alpha, const double *X, const int incX, + const double *Y, const int incY, double *A, const int lda); +void cblas_dsyr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const double *X, + const int incX, double *A, const int lda); +void cblas_dspr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const double *X, + const int incX, double *Ap); +void cblas_dsyr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const double *X, + const int incX, const double *Y, const int incY, double *A, + const int lda); +void cblas_dspr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const double *X, + const int incX, const double *Y, const int incY, double *A); + + +/* + * Routines with C and Z prefixes only + */ +void cblas_chemv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const void *alpha, const void *A, + const int lda, const void *X, const int incX, + const void *beta, void *Y, const int incY); +void cblas_chbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const int K, const void *alpha, const void *A, + const int lda, const void *X, const int incX, + const void *beta, void *Y, const int incY); +void cblas_chpmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const void *alpha, const void *Ap, + const void *X, const int incX, + const void *beta, void *Y, const int incY); +void cblas_cgeru(const enum CBLAS_ORDER Order, const int M, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); +void cblas_cgerc(const enum CBLAS_ORDER Order, const int M, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); +void cblas_cher(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const void *X, const int incX, + void *A, const int lda); +void cblas_chpr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const void *X, + const int incX, void *A); +void cblas_cher2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); +void cblas_chpr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *Ap); + +void cblas_zhemv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const void *alpha, const void *A, + const int lda, const void *X, const int incX, + const void *beta, void *Y, const int incY); +void cblas_zhbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const int K, const void *alpha, const void *A, + const int lda, const void *X, const int incX, + const void *beta, void *Y, const int incY); +void cblas_zhpmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const void *alpha, const void *Ap, + const void *X, const int incX, + const void *beta, void *Y, const int incY); +void cblas_zgeru(const enum CBLAS_ORDER Order, const int M, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); +void cblas_zgerc(const enum CBLAS_ORDER Order, const int M, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); +void cblas_zher(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const void *X, const int incX, + void *A, const int lda); +void cblas_zhpr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const void *X, + const int incX, void *A); +void cblas_zher2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); +void cblas_zhpr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *Ap); + +/* + * =========================================================================== + * Prototypes for level 3 BLAS + * =========================================================================== + */ + +/* + * Routines with standard 4 prefixes (S, D, C, Z) + */ +void cblas_sgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const float alpha, const float *A, + const int lda, const float *B, const int ldb, + const float beta, float *C, const int ldc); +void cblas_ssymm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const int M, const int N, + const float alpha, const float *A, const int lda, + const float *B, const int ldb, const float beta, + float *C, const int ldc); +void cblas_ssyrk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const float alpha, const float *A, const int lda, + const float beta, float *C, const int ldc); +void cblas_ssyr2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const float alpha, const float *A, const int lda, + const float *B, const int ldb, const float beta, + float *C, const int ldc); +void cblas_strmm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const float alpha, const float *A, const int lda, + float *B, const int ldb); +void cblas_strsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const float alpha, const float *A, const int lda, + float *B, const int ldb); + +void cblas_dgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const double alpha, const double *A, + const int lda, const double *B, const int ldb, + const double beta, double *C, const int ldc); +void cblas_dsymm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const int M, const int N, + const double alpha, const double *A, const int lda, + const double *B, const int ldb, const double beta, + double *C, const int ldc); +void cblas_dsyrk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const double alpha, const double *A, const int lda, + const double beta, double *C, const int ldc); +void cblas_dsyr2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const double alpha, const double *A, const int lda, + const double *B, const int ldb, const double beta, + double *C, const int ldc); +void cblas_dtrmm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const double alpha, const double *A, const int lda, + double *B, const int ldb); +void cblas_dtrsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const double alpha, const double *A, const int lda, + double *B, const int ldb); + +void cblas_cgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const void *alpha, const void *A, + const int lda, const void *B, const int ldb, + const void *beta, void *C, const int ldc); +void cblas_csymm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const void *beta, + void *C, const int ldc); +void cblas_csyrk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const void *alpha, const void *A, const int lda, + const void *beta, void *C, const int ldc); +void cblas_csyr2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const void *beta, + void *C, const int ldc); +void cblas_ctrmm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const void *alpha, const void *A, const int lda, + void *B, const int ldb); +void cblas_ctrsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const void *alpha, const void *A, const int lda, + void *B, const int ldb); + +void cblas_zgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const void *alpha, const void *A, + const int lda, const void *B, const int ldb, + const void *beta, void *C, const int ldc); +void cblas_zsymm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const void *beta, + void *C, const int ldc); +void cblas_zsyrk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const void *alpha, const void *A, const int lda, + const void *beta, void *C, const int ldc); +void cblas_zsyr2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const void *beta, + void *C, const int ldc); +void cblas_ztrmm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const void *alpha, const void *A, const int lda, + void *B, const int ldb); +void cblas_ztrsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const void *alpha, const void *A, const int lda, + void *B, const int ldb); + + +/* + * Routines with prefixes C and Z only + */ +void cblas_chemm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const void *beta, + void *C, const int ldc); +void cblas_cherk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const float alpha, const void *A, const int lda, + const float beta, void *C, const int ldc); +void cblas_cher2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const float beta, + void *C, const int ldc); +void cblas_zhemm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const void *beta, + void *C, const int ldc); +void cblas_zherk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const double alpha, const void *A, const int lda, + const double beta, void *C, const int ldc); +void cblas_zher2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const double beta, + void *C, const int ldc); + +int cblas_errprn(int ierr, int info, char *form, ...); + +#endif /* end #ifdef CBLAS_ENUM_ONLY */ +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/clapack.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,149 @@ +/* + * Automatically Tuned Linear Algebra Software v3.8.0 + * (C) Copyright 1999 R. Clint Whaley + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions, and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the ATLAS group or the names of its contributers may + * not be used to endorse or promote products derived from this + * software without specific written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ATLAS GROUP OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CLAPACK_H + +#define CLAPACK_H +#include "cblas.h" + +#ifndef ATLAS_ORDER + #define ATLAS_ORDER CBLAS_ORDER +#endif +#ifndef ATLAS_UPLO + #define ATLAS_UPLO CBLAS_UPLO +#endif +#ifndef ATLAS_DIAG + #define ATLAS_DIAG CBLAS_DIAG +#endif +int clapack_sgesv(const enum CBLAS_ORDER Order, const int N, const int NRHS, + float *A, const int lda, int *ipiv, + float *B, const int ldb); +int clapack_sgetrf(const enum CBLAS_ORDER Order, const int M, const int N, + float *A, const int lda, int *ipiv); +int clapack_sgetrs + (const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE Trans, + const int N, const int NRHS, const float *A, const int lda, + const int *ipiv, float *B, const int ldb); +int clapack_sgetri(const enum CBLAS_ORDER Order, const int N, float *A, + const int lda, const int *ipiv); +int clapack_sposv(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, const int NRHS, float *A, const int lda, + float *B, const int ldb); +int clapack_spotrf(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, float *A, const int lda); +int clapack_spotrs(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const int NRHS, const float *A, const int lda, + float *B, const int ldb); +int clapack_spotri(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, float *A, const int lda); +int clapack_slauum(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, float *A, const int lda); +int clapack_strtri(const enum ATLAS_ORDER Order,const enum ATLAS_UPLO Uplo, + const enum ATLAS_DIAG Diag,const int N, float *A, const int lda); + +int clapack_dgesv(const enum CBLAS_ORDER Order, const int N, const int NRHS, + double *A, const int lda, int *ipiv, + double *B, const int ldb); +int clapack_dgetrf(const enum CBLAS_ORDER Order, const int M, const int N, + double *A, const int lda, int *ipiv); +int clapack_dgetrs + (const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE Trans, + const int N, const int NRHS, const double *A, const int lda, + const int *ipiv, double *B, const int ldb); +int clapack_dgetri(const enum CBLAS_ORDER Order, const int N, double *A, + const int lda, const int *ipiv); +int clapack_dposv(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, const int NRHS, double *A, const int lda, + double *B, const int ldb); +int clapack_dpotrf(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, double *A, const int lda); +int clapack_dpotrs(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const int NRHS, const double *A, const int lda, + double *B, const int ldb); +int clapack_dpotri(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, double *A, const int lda); +int clapack_dlauum(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, double *A, const int lda); +int clapack_dtrtri(const enum ATLAS_ORDER Order,const enum ATLAS_UPLO Uplo, + const enum ATLAS_DIAG Diag,const int N, double *A, const int lda); + +int clapack_cgesv(const enum CBLAS_ORDER Order, const int N, const int NRHS, + void *A, const int lda, int *ipiv, + void *B, const int ldb); +int clapack_cgetrf(const enum CBLAS_ORDER Order, const int M, const int N, + void *A, const int lda, int *ipiv); +int clapack_cgetrs + (const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE Trans, + const int N, const int NRHS, const void *A, const int lda, + const int *ipiv, void *B, const int ldb); +int clapack_cgetri(const enum CBLAS_ORDER Order, const int N, void *A, + const int lda, const int *ipiv); +int clapack_cposv(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, const int NRHS, void *A, const int lda, + void *B, const int ldb); +int clapack_cpotrf(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, void *A, const int lda); +int clapack_cpotrs(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const int NRHS, const void *A, const int lda, + void *B, const int ldb); +int clapack_cpotri(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, void *A, const int lda); +int clapack_clauum(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, void *A, const int lda); +int clapack_ctrtri(const enum ATLAS_ORDER Order,const enum ATLAS_UPLO Uplo, + const enum ATLAS_DIAG Diag,const int N, void *A, const int lda); + +int clapack_zgesv(const enum CBLAS_ORDER Order, const int N, const int NRHS, + void *A, const int lda, int *ipiv, + void *B, const int ldb); +int clapack_zgetrf(const enum CBLAS_ORDER Order, const int M, const int N, + void *A, const int lda, int *ipiv); +int clapack_zgetrs + (const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE Trans, + const int N, const int NRHS, const void *A, const int lda, + const int *ipiv, void *B, const int ldb); +int clapack_zgetri(const enum CBLAS_ORDER Order, const int N, void *A, + const int lda, const int *ipiv); +int clapack_zposv(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, const int NRHS, void *A, const int lda, + void *B, const int ldb); +int clapack_zpotrf(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, void *A, const int lda); +int clapack_zpotrs(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const int NRHS, const void *A, const int lda, + void *B, const int ldb); +int clapack_zpotri(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, void *A, const int lda); +int clapack_zlauum(const enum ATLAS_ORDER Order, const enum ATLAS_UPLO Uplo, + const int N, void *A, const int lda); +int clapack_ztrtri(const enum ATLAS_ORDER Order,const enum ATLAS_UPLO Uplo, + const enum ATLAS_DIAG Diag,const int N, void *A, const int lda); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/linux/amd64/qm-vamp-plugins.pro Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,39 @@ + +TEMPLATE = lib + +CONFIG += plugin warn_on release +CONFIG -= qt + +OBJECTS_DIR = tmp_obj +MOC_DIR = tmp_moc + +INCLUDEPATH += build/linux/amd64 ../vamp-plugin-sdk ../qm-dsp +LIBPATH += build/linux/amd64 ../vamp-plugin-sdk/src ../qm-dsp + +LIBS += -static-libgcc -Wl,-Bstatic -lqm-dsp -lvamp-sdk -llapack -lcblas -latlas -lc -Wl,-Bdynamic -Wl,--version-script=vamp-plugin.map + +DEPENDPATH += plugins +INCLUDEPATH += . plugins + +# Input +HEADERS += plugins/BeatTrack.h \ + plugins/OnsetDetect.h \ + plugins/ChromagramPlugin.h \ + plugins/ConstantQSpectrogram.h \ + plugins/KeyDetect.h \ + plugins/MFCCPlugin.h \ + plugins/SegmenterPlugin.h \ + plugins/SimilarityPlugin.h \ + plugins/TonalChangeDetect.h +SOURCES += g2cstubs.c \ + plugins/BeatTrack.cpp \ + plugins/OnsetDetect.cpp \ + plugins/ChromagramPlugin.cpp \ + plugins/ConstantQSpectrogram.cpp \ + plugins/KeyDetect.cpp \ + plugins/MFCCPlugin.cpp \ + plugins/SegmenterPlugin.cpp \ + plugins/SimilarityPlugin.cpp \ + plugins/TonalChangeDetect.cpp \ + ./libmain.cpp +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/mingw32/g2cstubs.c Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,5 @@ + +void s_wsfe() { } +void do_fio() { } +void e_wsfe() { } +void s_stop() { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/mingw32/mkspecs/win32-x-g++/qmake.conf Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,101 @@ +# +# qmake configuration for win32-g++ +# +# Written for MinGW +# + +MAKEFILE_GENERATOR = MINGW +TEMPLATE = app +CONFIG += qt warn_on release link_prl copy_dir_files debug_and_release debug_and_release_target +QT += core gui +DEFINES += UNICODE QT_LARGEFILE_SUPPORT +QMAKE_COMPILER_DEFINES += __GNUC__ WIN32 + +QMAKE_CC = i586-mingw32msvc-gcc +QMAKE_LEX = flex +QMAKE_LEXFLAGS = +QMAKE_YACC = byacc +QMAKE_YACCFLAGS = -d +QMAKE_CFLAGS = +QMAKE_CFLAGS_DEPS = -M +QMAKE_CFLAGS_WARN_ON = -Wall +QMAKE_CFLAGS_WARN_OFF = -w +QMAKE_CFLAGS_RELEASE = -O2 +QMAKE_CFLAGS_DEBUG = -g +QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses +QMAKE_CFLAGS_THREAD = -mthreads + +QMAKE_CXX = i586-mingw32msvc-g++ +QMAKE_CXXFLAGS = $$QMAKE_CFLAGS +QMAKE_CXXFLAGS_DEPS = $$QMAKE_CFLAGS_DEPS +QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON +QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF +QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE +QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG +QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC +QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD +QMAKE_CXXFLAGS_RTTI_ON = -frtti +QMAKE_CXXFLAGS_RTTI_OFF = -fno-rtti +QMAKE_CXXFLAGS_EXCEPTIONS_ON = -fexceptions +QMAKE_CXXFLAGS_EXCEPTIONS_OFF = -fno-exceptions + +QMAKE_INCDIR = +QMAKE_INCDIR_QT = /home/studio/.wine/fake_windows/Qt/4.3.0/include +QMAKE_LIBDIR_QT = /home/studio/.wine/fake_windows/Qt/4.3.0/lib + +QMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -o $obj $src +QMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< +QMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $obj $src +QMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +QMAKE_LINK = i586-mingw32msvc-g++ +QMAKE_LFLAGS = -Wl,-enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -mwindows +QMAKE_LFLAGS_RELEASE = -Wl,-s +QMAKE_LFLAGS_DEBUG = +QMAKE_LFLAGS_CONSOLE = -Wl,-subsystem,console +QMAKE_LFLAGS_WINDOWS = -Wl,-subsystem,windows +QMAKE_LFLAGS_DLL = -shared +QMAKE_LINK_OBJECT_MAX = 10 +QMAKE_LINK_OBJECT_SCRIPT= object_script + + +QMAKE_LIBS = +QMAKE_LIBS_CORE = -lkernel32 -luser32 -lshell32 -luuid -lole32 -ladvapi32 -lws2_32 +#QMAKE_LIBS_CORE = -lkernel32 -luser32 -luuid -lole32 -ladvapi32 -lws2_32 +QMAKE_LIBS_GUI = -lgdi32 -lcomdlg32 -loleaut32 -limm32 -lwinmm -lwinspool -lws2_32 -lole32 -luuid -luser32 +QMAKE_LIBS_NETWORK = -lws2_32 +QMAKE_LIBS_OPENGL = -lopengl32 -lglu32 -lgdi32 -luser32 +QMAKE_LIBS_COMPAT = -ladvapi32 -lshell32 -lcomdlg32 -luser32 -lgdi32 -lws2_32 +QMAKE_LIBS_QT_ENTRY = -lqtmain + +MINGW_IN_SHELL = $$(MINGW_IN_SHELL) +#isEqual(MINGW_IN_SHELL, 1) { + QMAKE_DIR_SEP = / + QMAKE_COPY = cp + QMAKE_COPY_DIR = cp -r + QMAKE_MOVE = mv + QMAKE_DEL_FILE = rm -f + QMAKE_MKDIR = mkdir -p + QMAKE_DEL_DIR = rm -rf +#} else { +# QMAKE_COPY = copy /y +# QMAKE_COPY_DIR = xcopy /s /q /y /i +# QMAKE_MOVE = move +# QMAKE_DEL_FILE = del +# QMAKE_MKDIR = mkdir +# QMAKE_DEL_DIR = rmdir +#} +QMAKE_MOC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}moc +QMAKE_UIC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}uic +QMAKE_IDC = $$[QT_INSTALL_BINS]$${DIR_SEPARATOR}idc + +QMAKE_IDL = midl +QMAKE_LIB = ar -ru +QMAKE_RC = i586-mingw32msvc-windres + +QMAKE_ZIP = zip -r -9 + +QMAKE_STRIP = strip +QMAKE_STRIPFLAGS_LIB += --strip-unneeded +QMAKE_CHK_DIR_EXISTS = test -d +load(qt_config)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/mingw32/mkspecs/win32-x-g++/qplatformdefs.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved. +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://www.trolltech.com/products/qt/opensource.html +** +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://www.trolltech.com/products/qt/licensing.html or contact the +** sales department at sales@trolltech.com. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +#ifdef UNICODE +#ifndef _UNICODE +#define _UNICODE +#endif +#endif + +// Get Qt defines/settings + +#include "qglobal.h" + +#include <tchar.h> +#include <io.h> +#include <direct.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <windows.h> +#include <limits.h> + +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT-0 < 0x0500) +typedef enum { + NameUnknown = 0, + NameFullyQualifiedDN = 1, + NameSamCompatible = 2, + NameDisplay = 3, + NameUniqueId = 6, + NameCanonical = 7, + NameUserPrincipal = 8, + NameCanonicalEx = 9, + NameServicePrincipal = 10, + NameDnsDomain = 12 +} EXTENDED_NAME_FORMAT, *PEXTENDED_NAME_FORMAT; +#endif + +#define Q_FS_FAT +#ifdef QT_LARGEFILE_SUPPORT +#define QT_STATBUF struct _stati64 // non-ANSI defs +#define QT_STATBUF4TSTAT struct _stati64 // non-ANSI defs +#define QT_STAT ::_stati64 +#define QT_FSTAT ::_fstati64 +#else +#define QT_STATBUF struct _stat // non-ANSI defs +#define QT_STATBUF4TSTAT struct _stat // non-ANSI defs +#define QT_STAT ::_stat +#define QT_FSTAT ::_fstat +#endif +#define QT_STAT_REG _S_IFREG +#define QT_STAT_DIR _S_IFDIR +#define QT_STAT_MASK _S_IFMT +#if defined(_S_IFLNK) +# define QT_STAT_LNK _S_IFLNK +#endif +#define QT_FILENO _fileno +#define QT_OPEN ::_open +#define QT_CLOSE ::_close +#ifdef QT_LARGEFILE_SUPPORT +#define QT_LSEEK ::_lseeki64 +#ifndef UNICODE +#define QT_TSTAT ::_stati64 +#else +#define QT_TSTAT ::_wstati64 +#endif +#else +#define QT_LSEEK ::_lseek +#ifndef UNICODE +#define QT_TSTAT ::_stat +#else +#define QT_TSTAT ::_wstat +#endif +#endif +#define QT_READ ::_read +#define QT_WRITE ::_write +#define QT_ACCESS ::_access +#define QT_GETCWD ::_getcwd +#define QT_CHDIR ::_chdir +#define QT_MKDIR ::_mkdir +#define QT_RMDIR ::_rmdir +#define QT_OPEN_LARGEFILE 0 +#define QT_OPEN_RDONLY _O_RDONLY +#define QT_OPEN_WRONLY _O_WRONLY +#define QT_OPEN_RDWR _O_RDWR +#define QT_OPEN_CREAT _O_CREAT +#define QT_OPEN_TRUNC _O_TRUNC +#define QT_OPEN_APPEND _O_APPEND +#if defined(O_TEXT) +# define QT_OPEN_TEXT _O_TEXT +# define QT_OPEN_BINARY _O_BINARY +#endif + +#define QT_FOPEN ::fopen +#ifdef QT_LARGEFILE_SUPPORT +#define QT_FSEEK ::fseeko64 +#define QT_FTELL ::ftello64 +#else +#define QT_FSEEK ::fseek +#define QT_FTELL ::ftell +#endif +#define QT_FGETPOS ::fgetpos +#define QT_FSETPOS ::fsetpos +#define QT_FPOS_T fpos_t +#ifdef QT_LARGEFILE_SUPPORT +#define QT_OFF_T off64_t +#else +#define QT_OFF_T long +#endif + +#define QT_SIGNAL_ARGS int + +#define QT_VSNPRINTF ::_vsnprintf +#define QT_SNPRINTF ::_snprintf + +# define F_OK 0 +# define X_OK 1 +# define W_OK 2 +# define R_OK 4 + + +#endif // QPLATFORMDEFS_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/mingw32/qm-vamp-plugins.pro Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,41 @@ + +TEMPLATE = lib + +CONFIG += dll plugin warn_on release +CONFIG -= qt + +linux-g++:QMAKE_CXXFLAGS_RELEASE += -DNDEBUG -O3 -march=pentium4 -msse -msse2 +QMAKE_CXXFLAGS_RELEASE += -DNDEBUG -O2 -march=pentium3 -msse + +OBJECTS_DIR = tmp_obj +MOC_DIR = tmp_moc + +INCLUDEPATH += ../vamp-plugin-sdk ../qm-dsp +LIBPATH += ./build/mingw32 ../vamp-plugin-sdk/vamp-sdk ../qm-dsp ../qm-dsp/release + +LIBS += -shared -Wl,-Bstatic -lqm-dsp -lvamp-sdk -llapack -lcblas -latlas -lf77blas -lg2cstubs -Wl,-Bdynamic + +DEPENDPATH += plugins +INCLUDEPATH += . plugins + +# Input +HEADERS += plugins/BeatTrack.h \ + plugins/OnsetDetect.h \ + plugins/ChromagramPlugin.h \ + plugins/ConstantQSpectrogram.h \ + plugins/KeyDetect.h \ + plugins/MFCCPlugin.h \ + plugins/SegmenterPlugin.h \ + plugins/SimilarityPlugin.h \ + plugins/TonalChangeDetect.h +SOURCES += plugins/BeatTrack.cpp \ + plugins/OnsetDetect.cpp \ + plugins/ChromagramPlugin.cpp \ + plugins/ConstantQSpectrogram.cpp \ + plugins/KeyDetect.cpp \ + plugins/MFCCPlugin.cpp \ + plugins/SegmenterPlugin.cpp \ + plugins/SimilarityPlugin.cpp \ + plugins/TonalChangeDetect.cpp \ + ./libmain.cpp +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/osx/Makefile.osx Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,11 @@ + +CFLAGS := -O3 -ftree-vectorize -isysroot /Developer/SDKs/MacOSX10.6.sdk -arch i386 -arch x86_64 -I../vamp-plugin-sdk -I/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/Headers/ -DUSE_PTHREADS + +CXXFLAGS := $(CFLAGS) + +LDFLAGS := -isysroot /Developer/SDKs/MacOSX10.6.sdk -arch i386 -arch x86_64 -dynamiclib -lqm-dsp ../vamp-plugin-sdk/libvamp-sdk.a -framework Accelerate -lpthread -install_name qm-vamp-plugins.dylib + +PLUGIN_EXT := .dylib + +include build/general/Makefile.inc +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/build/osx/qm-vamp-plugins.pro Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,42 @@ + +TEMPLATE = lib +QMAKE_MAC_SDK=/Developer/SDKs/MacOSX10.4u.sdk +QMAKE_CXXFLAGS_RELEASE += -O2 -g0 + +CONFIG += plugin warn_on release x86 ppc +CONFIG -= qt + +linux-g++:QMAKE_CXXFLAGS_RELEASE += -DNDEBUG -O3 -march=pentium4 -msse -msse2 + +OBJECTS_DIR = tmp_obj +MOC_DIR = tmp_moc + +INCLUDEPATH += ../vamp-plugin-sdk ../qm-dsp +LIBPATH += ../vamp-plugin-sdk/vamp-sdk ../qm-dsp + +LIBS += -install_name qm-vamp-plugins.dylib -lqm-dsp -lvamp-sdk -lblas -llapack + +DEPENDPATH += plugins +INCLUDEPATH += . plugins + +# Input +HEADERS += plugins/BeatTrack.h \ + plugins/OnsetDetect.h \ + plugins/ChromagramPlugin.h \ + plugins/ConstantQSpectrogram.h \ + plugins/KeyDetect.h \ + plugins/MFCCPlugin.h \ + plugins/SegmenterPlugin.h \ + plugins/SimilarityPlugin.h \ + plugins/TonalChangeDetect.h +SOURCES += plugins/BeatTrack.cpp \ + plugins/OnsetDetect.cpp \ + plugins/ChromagramPlugin.cpp \ + plugins/ConstantQSpectrogram.cpp \ + plugins/KeyDetect.cpp \ + plugins/MFCCPlugin.cpp \ + plugins/SegmenterPlugin.cpp \ + plugins/SimilarityPlugin.cpp \ + plugins/TonalChangeDetect.cpp \ + ./libmain.cpp +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/g2cstubs.c Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,5 @@ + +void s_wsfe() { } +void do_fio() { } +void e_wsfe() { } +void s_stop() { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/libmain.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,71 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include <vamp/vamp.h> +#include <vamp-sdk/PluginAdapter.h> + +#include "plugins/BeatTrack.h" +#include "plugins/OnsetDetect.h" +#include "plugins/ChromagramPlugin.h" +#include "plugins/ConstantQSpectrogram.h" +#include "plugins/TonalChangeDetect.h" +#include "plugins/KeyDetect.h" +#include "plugins/MFCCPlugin.h" +#include "plugins/SegmenterPlugin.h" +#include "plugins/SimilarityPlugin.h" +#include "plugins/SongParts.h" +#include "plugins/BarBeatTrack.h" +#include "plugins/AdaptiveSpectrogram.h" +#include "plugins/DWT.h" +#include "plugins/Transcription.h" + +static Vamp::PluginAdapter<BeatTracker> beatTrackerAdapter; +static Vamp::PluginAdapter<OnsetDetector> onsetDetectorAdapter; +static Vamp::PluginAdapter<ChromagramPlugin> chromagramPluginAdapter; +static Vamp::PluginAdapter<ConstantQSpectrogram> constantQAdapter; +static Vamp::PluginAdapter<TonalChangeDetect> tonalChangeDetectorAdapter; +static Vamp::PluginAdapter<KeyDetector> keyDetectorAdapter; +static Vamp::PluginAdapter<MFCCPlugin> mfccPluginAdapter; +static Vamp::PluginAdapter<SegmenterPlugin> segmenterPluginAdapter; +static Vamp::PluginAdapter<SimilarityPlugin> similarityPluginAdapter; +static Vamp::PluginAdapter<SongPartitioner> songPartitionerAdapter; +static Vamp::PluginAdapter<BarBeatTracker> barBeatTrackPluginAdapter; +static Vamp::PluginAdapter<AdaptiveSpectrogram> adaptiveSpectrogramAdapter; +static Vamp::PluginAdapter<DWT> dwtAdapter; +static Vamp::PluginAdapter<Transcription> transcriptionAdapter; + +const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int vampApiVersion, + unsigned int index) +{ + if (vampApiVersion < 1) return 0; + + switch (index) { + case 0: return beatTrackerAdapter.getDescriptor(); + case 1: return onsetDetectorAdapter.getDescriptor(); + case 2: return chromagramPluginAdapter.getDescriptor(); + case 3: return constantQAdapter.getDescriptor(); + case 4: return tonalChangeDetectorAdapter.getDescriptor(); + case 5: return keyDetectorAdapter.getDescriptor(); + case 6: return segmenterPluginAdapter.getDescriptor(); + case 7: return similarityPluginAdapter.getDescriptor(); + case 8: return mfccPluginAdapter.getDescriptor(); + case 9: return barBeatTrackPluginAdapter.getDescriptor(); + case 10: return dwtAdapter.getDescriptor(); + case 11: return adaptiveSpectrogramAdapter.getDescriptor(); + case 12: return transcriptionAdapter.getDescriptor(); + case 13: return songPartitionerAdapter.getDescriptor(); + default: return 0; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/lunchMake.sh Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,13 @@ +clear + +echo ' ' +echo ' ' +echo ' ' +echo '--------------------------------------------------------------' +make -f Makefile.osx +echo ' ' +cp -v qm-vamp-plugins.dylib /Users/maxzanoni76/Library/Audio/Plug-Ins/Vamp/ +echo '--------------------------------------------------------------' +echo ' ' + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/AdaptiveSpectrogram.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,539 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "AdaptiveSpectrogram.h" + +#include <cstdlib> +#include <cstdio> +#include <cstring> +#include <cfloat> + +#include <iostream> + +#include <dsp/transforms/FFT.h> + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + +using Vamp::RealTime; + +//#define DEBUG_VERBOSE 1 + +AdaptiveSpectrogram::AdaptiveSpectrogram(float inputSampleRate) : + Plugin(inputSampleRate), + m_w(8), + m_n(2), + m_coarse(false), + m_threaded(true), + m_threadsInUse(false) +{ +} + +AdaptiveSpectrogram::~AdaptiveSpectrogram() +{ + for (int i = 0; i < m_cutThreads.size(); ++i) { + delete m_cutThreads[i]; + } + m_cutThreads.clear(); + + for (FFTMap::iterator i = m_fftThreads.begin(); + i != m_fftThreads.end(); ++i) { + delete i->second; + } + m_fftThreads.clear(); +} + +string +AdaptiveSpectrogram::getIdentifier() const +{ + return "qm-adaptivespectrogram"; +} + +string +AdaptiveSpectrogram::getName() const +{ + return "Adaptive Spectrogram"; +} + +string +AdaptiveSpectrogram::getDescription() const +{ + return "Produce an adaptive spectrogram by adaptive selection from spectrograms at multiple resolutions"; +} + +string +AdaptiveSpectrogram::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int +AdaptiveSpectrogram::getPluginVersion() const +{ + return 1; +} + +string +AdaptiveSpectrogram::getCopyright() const +{ + return "Plugin by Wen Xue and Chris Cannam. Copyright (c) 2009 Wen Xue and QMUL - All Rights Reserved"; +} + +size_t +AdaptiveSpectrogram::getPreferredStepSize() const +{ + return ((2 << m_w) << m_n) / 2; +} + +size_t +AdaptiveSpectrogram::getPreferredBlockSize() const +{ + return (2 << m_w) << m_n; +} + +bool +AdaptiveSpectrogram::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) return false; + + return true; +} + +void +AdaptiveSpectrogram::reset() +{ + +} + +AdaptiveSpectrogram::ParameterList +AdaptiveSpectrogram::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + desc.identifier = "n"; + desc.name = "Number of resolutions"; + desc.description = "Number of consecutive powers of two in the range to be used as spectrogram resolutions, starting with the minimum resolution specified"; + desc.unit = ""; + desc.minValue = 2; + desc.maxValue = 10; + desc.defaultValue = 3; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + ParameterDescriptor desc2; + desc2.identifier = "w"; + desc2.name = "Smallest resolution"; + desc2.description = "Smallest of the consecutive powers of two to use as spectrogram resolutions"; + desc2.unit = ""; + desc2.minValue = 1; + desc2.maxValue = 14; + desc2.defaultValue = 9; + desc2.isQuantized = true; + desc2.quantizeStep = 1; + // I am so lazy + desc2.valueNames.push_back("2"); + desc2.valueNames.push_back("4"); + desc2.valueNames.push_back("8"); + desc2.valueNames.push_back("16"); + desc2.valueNames.push_back("32"); + desc2.valueNames.push_back("64"); + desc2.valueNames.push_back("128"); + desc2.valueNames.push_back("256"); + desc2.valueNames.push_back("512"); + desc2.valueNames.push_back("1024"); + desc2.valueNames.push_back("2048"); + desc2.valueNames.push_back("4096"); + desc2.valueNames.push_back("8192"); + desc2.valueNames.push_back("16384"); + list.push_back(desc2); + + ParameterDescriptor desc3; + desc3.identifier = "coarse"; + desc3.name = "Omit alternate resolutions"; + desc3.description = "Generate a coarser spectrogram faster by excluding every alternate resolution (first and last resolution are always retained)"; + desc3.unit = ""; + desc3.minValue = 0; + desc3.maxValue = 1; + desc3.defaultValue = 0; + desc3.isQuantized = true; + desc3.quantizeStep = 1; + list.push_back(desc3); + + desc3.identifier = "threaded"; + desc3.name = "Multi-threaded processing"; + desc3.description = "Perform calculations using several threads in parallel"; + desc3.unit = ""; + desc3.minValue = 0; + desc3.maxValue = 1; + desc3.defaultValue = 1; + desc3.isQuantized = true; + desc3.quantizeStep = 1; + list.push_back(desc3); + + return list; +} + +float +AdaptiveSpectrogram::getParameter(std::string id) const +{ + if (id == "n") return m_n+1; + else if (id == "w") return m_w+1; + else if (id == "threaded") return (m_threaded ? 1 : 0); + else if (id == "coarse") return (m_coarse ? 1 : 0); + return 0.f; +} + +void +AdaptiveSpectrogram::setParameter(std::string id, float value) +{ + if (id == "n") { + int n = lrintf(value); + if (n >= 1 && n <= 10) m_n = n-1; + } else if (id == "w") { + int w = lrintf(value); + if (w >= 1 && w <= 14) m_w = w-1; + } else if (id == "threaded") { + m_threaded = (value > 0.5); + } else if (id == "coarse") { + m_coarse = (value > 0.5); + } +} + +AdaptiveSpectrogram::OutputList +AdaptiveSpectrogram::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor d; + d.identifier = "output"; + d.name = "Output"; + d.description = "The output of the plugin"; + d.unit = ""; + d.hasFixedBinCount = true; + d.binCount = getPreferredBlockSize() / 2; + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::FixedSampleRate; + d.sampleRate = m_inputSampleRate / ((2 << m_w) / 2); + d.hasDuration = false; + char name[20]; + for (int i = 0; i < d.binCount; ++i) { + float freq = (m_inputSampleRate / (d.binCount * 2)) * (i + 1); // no DC bin + sprintf(name, "%d Hz", int(freq)); + d.binNames.push_back(name); + } + list.push_back(d); + + return list; +} + +AdaptiveSpectrogram::FeatureSet +AdaptiveSpectrogram::getRemainingFeatures() +{ + FeatureSet fs; + return fs; +} + +AdaptiveSpectrogram::FeatureSet +AdaptiveSpectrogram::process(const float *const *inputBuffers, RealTime ts) +{ + FeatureSet fs; + + int minwid = (2 << m_w), maxwid = ((2 << m_w) << m_n); + +#ifdef DEBUG_VERBOSE + cerr << "widths from " << minwid << " to " << maxwid << " (" + << minwid/2 << " to " << maxwid/2 << " in real parts)" << endl; +#endif + + Spectrograms s(minwid/2, maxwid/2, 1); + + int w = minwid; + int index = 0; + + while (w <= maxwid) { + + if (!isResolutionWanted(s, w/2)) { + w *= 2; + ++index; + continue; + } + + if (m_fftThreads.find(w) == m_fftThreads.end()) { + m_fftThreads[w] = new FFTThread(w); + } + if (m_threaded) { + m_fftThreads[w]->startCalculation + (inputBuffers[0], s, index, maxwid); + } else { + m_fftThreads[w]->setParameters + (inputBuffers[0], s, index, maxwid); + m_fftThreads[w]->performTask(); + } + w *= 2; + ++index; + } + + if (m_threaded) { + w = minwid; + index = 0; + while (w <= maxwid) { + if (!isResolutionWanted(s, w/2)) { + w *= 2; + ++index; + continue; + } + m_fftThreads[w]->await(); + w *= 2; + ++index; + } + } + + m_threadsInUse = false; + +// std::cerr << "maxwid/2 = " << maxwid/2 << ", minwid/2 = " << minwid/2 << ", n+1 = " << m_n+1 << ", 2^(n+1) = " << (2<<m_n) << std::endl; + + int cutwid = maxwid/2; + Cutting *cutting = cut(s, cutwid, 0, 0, cutwid, 0); + +#ifdef DEBUG_VERBOSE + printCutting(cutting, " "); +#endif + + vector<vector<float> > rmat(maxwid/minwid); + for (int i = 0; i < maxwid/minwid; ++i) { + rmat[i] = vector<float>(maxwid/2); + } + + assemble(s, cutting, rmat, 0, 0, maxwid/minwid, cutwid); + + cutting->erase(); + + for (int i = 0; i < rmat.size(); ++i) { + Feature f; + f.hasTimestamp = false; + f.values = rmat[i]; + fs[0].push_back(f); + } + +// std::cerr << "process returning!\n" << std::endl; + + return fs; +} + +void +AdaptiveSpectrogram::printCutting(Cutting *c, string pfx) const +{ + if (c->first) { + if (c->cut == Cutting::Horizontal) { + cerr << pfx << "H" << endl; + } else if (c->cut == Cutting::Vertical) { + cerr << pfx << "V" << endl; + } + printCutting(c->first, pfx + " "); + printCutting(c->second, pfx + " "); + } else { + cerr << pfx << "* " << c->value << endl; + } +} + +void +AdaptiveSpectrogram::getSubCuts(const Spectrograms &s, + int res, + int x, int y, int h, + Cutting **top, Cutting **bottom, + Cutting **left, Cutting **right, + BlockAllocator *allocator) const +{ + if (m_threaded && !m_threadsInUse) { + + m_threadsInUse = true; + + if (m_cutThreads.empty()) { + for (int i = 0; i < 4; ++i) { + CutThread *t = new CutThread(this); + m_cutThreads.push_back(t); + } + } + + // Cut threads 0 and 1 calculate the top and bottom halves; + // threads 2 and 3 calculate left and right. See notes in + // unthreaded code below for more information. + + if (top) m_cutThreads[0]->cut(s, res, x, y + h/2, h/2); + if (bottom) m_cutThreads[1]->cut(s, res, x, y, h/2); + + if (left) m_cutThreads[2]->cut(s, res/2, 2 * x, y/2, h/2); + if (right) m_cutThreads[3]->cut(s, res/2, 2 * x + 1, y/2, h/2); + + if (top) *top = m_cutThreads[0]->get(); + if (bottom) *bottom = m_cutThreads[1]->get(); + if (left) *left = m_cutThreads[2]->get(); + if (right) *right = m_cutThreads[3]->get(); + + } else { + + // Unthreaded version + + // The "vertical" division is a top/bottom split. + // Splitting this way keeps us in the same resolution, + // but with two vertical subregions of height h/2. + + if (top) *top = cut(s, res, x, y + h/2, h/2, allocator); + if (bottom) *bottom = cut(s, res, x, y, h/2, allocator); + + // The "horizontal" division is a left/right split. Splitting + // this way places us in resolution res/2, which has lower + // vertical resolution but higher horizontal resolution. We + // need to double x accordingly. + + if (left) *left = cut(s, res/2, 2 * x, y/2, h/2, allocator); + if (right) *right = cut(s, res/2, 2 * x + 1, y/2, h/2, allocator); + } +} + +AdaptiveSpectrogram::Cutting * +AdaptiveSpectrogram::cut(const Spectrograms &s, + int res, + int x, int y, int h, + BlockAllocator *allocator) const +{ +// cerr << "res = " << res << ", x = " << x << ", y = " << y << ", h = " << h << endl; + + Cutting *cutting; + if (allocator) { + cutting = (Cutting *)(allocator->allocate()); + cutting->allocator = allocator; + } else { + cutting = new Cutting; + cutting->allocator = 0; + } + + if (h > 1 && res > s.minres) { + + if (!isResolutionWanted(s, res)) { + + Cutting *left = 0, *right = 0; + getSubCuts(s, res, x, y, h, 0, 0, &left, &right, allocator); + + double hcost = left->cost + right->cost; + double henergy = left->value + right->value; + hcost = normalize(hcost, henergy); + + cutting->cut = Cutting::Horizontal; + cutting->first = left; + cutting->second = right; + cutting->cost = hcost; + cutting->value = left->value + right->value; + + } else if (h == 2 && !isResolutionWanted(s, res/2)) { + + Cutting *top = 0, *bottom = 0; + getSubCuts(s, res, x, y, h, &top, &bottom, 0, 0, allocator); + + double vcost = top->cost + bottom->cost; + double venergy = top->value + bottom->value; + vcost = normalize(vcost, venergy); + + cutting->cut = Cutting::Vertical; + cutting->first = top; + cutting->second = bottom; + cutting->cost = vcost; + cutting->value = top->value + bottom->value; + + } else { + + Cutting *top = 0, *bottom = 0, *left = 0, *right = 0; + getSubCuts(s, res, x, y, h, &top, &bottom, &left, &right, allocator); + + double vcost = top->cost + bottom->cost; + double venergy = top->value + bottom->value; + vcost = normalize(vcost, venergy); + + double hcost = left->cost + right->cost; + double henergy = left->value + right->value; + hcost = normalize(hcost, henergy); + + if (vcost > hcost) { + cutting->cut = Cutting::Horizontal; + cutting->first = left; + cutting->second = right; + cutting->cost = hcost; + cutting->value = left->value + right->value; + top->erase(); + bottom->erase(); + return cutting; + } else { + cutting->cut = Cutting::Vertical; + cutting->first = top; + cutting->second = bottom; + cutting->cost = vcost; + cutting->value = top->value + bottom->value; + left->erase(); + right->erase(); + return cutting; + } + } + + } else { + + // no cuts possible from this level + + cutting->cut = Cutting::Finished; + cutting->first = 0; + cutting->second = 0; + + int n = 0; + for (int r = res; r > s.minres; r >>= 1) ++n; + const Spectrogram *spectrogram = s.spectrograms[n]; + cutting->cost = cost(*spectrogram, x, y); + cutting->value = value(*spectrogram, x, y); + } + + return cutting; +} + +void +AdaptiveSpectrogram::assemble(const Spectrograms &s, + const Cutting *cutting, + vector<vector<float> > &rmat, + int x, int y, int w, int h) const +{ + switch (cutting->cut) { + + case Cutting::Finished: + for (int i = 0; i < w; ++i) { + for (int j = 0; j < h; ++j) { + rmat[x+i][y+j] = cutting->value; + } + } + return; + + case Cutting::Horizontal: + assemble(s, cutting->first, rmat, x, y, w/2, h); + assemble(s, cutting->second, rmat, x+w/2, y, w/2, h); + break; + + case Cutting::Vertical: + assemble(s, cutting->first, rmat, x, y+h/2, w, h/2); + assemble(s, cutting->second, rmat, x, y, w, h/2); + break; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/AdaptiveSpectrogram.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,292 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _ADAPTIVE_SPECTROGRAM_H_ +#define _ADAPTIVE_SPECTROGRAM_H_ + +#include <vamp-sdk/Plugin.h> +#include <cmath> +#include <vector> + +#include <dsp/transforms/FFT.h> +#include <base/Window.h> + +#include "thread/Thread.h" +#include "thread/AsynchronousTask.h" +#include "thread/BlockAllocator.h" + +class AdaptiveSpectrogram : public Vamp::Plugin +{ +public: + AdaptiveSpectrogram(float inputSampleRate); + virtual ~AdaptiveSpectrogram(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const { return TimeDomain; } + + std::string getIdentifier() const; + std::string getName() const; + std::string getDescription() const; + std::string getMaker() const; + int getPluginVersion() const; + std::string getCopyright() const; + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + + ParameterList getParameterDescriptors() const; + float getParameter(std::string id) const; + void setParameter(std::string id, float value); + + OutputList getOutputDescriptors() const; + + FeatureSet process(const float *const *inputBuffers, + Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + int m_w; + int m_n; + bool m_coarse; + bool m_threaded; + + struct Spectrogram + { + int resolution; + int width; + double **data; + + Spectrogram(int r, int w) : + resolution(r), width(w) { + data = new double *[width]; + for (int i = 0; i < width; ++i) data[i] = new double[resolution]; + } + + ~Spectrogram() { + for (int i = 0; i < width; ++i) delete[] data[i]; + delete[] data; + } + }; + + struct Spectrograms + { + int minres; + int maxres; + int n; + Spectrogram **spectrograms; + + Spectrograms(int mn, int mx, int widthofmax) : + minres(mn), maxres(mx) { + n = log2(maxres/minres) + 1; + spectrograms = new Spectrogram *[n]; + int r = mn; + for (int i = 0; i < n; ++i) { + spectrograms[i] = new Spectrogram(r, widthofmax * (mx / r)); + r = r * 2; + } + } + ~Spectrograms() { + for (int i = 0; i < n; ++i) { + delete spectrograms[i]; + } + delete[] spectrograms; + } + }; + + struct Cutting + { + enum Cut { Horizontal, Vertical, Finished }; + Cut cut; + Cutting *first; + Cutting *second; + double cost; + double value; + BlockAllocator *allocator; + + ~Cutting() { + if (first) first->erase(); + if (second) second->erase(); + } + + void erase() { + if (allocator) { + if (first) first->erase(); + if (second) second->erase(); + allocator->deallocate(this); + } else { + delete this; + } + } + }; + + class FFTThread : public AsynchronousTask + { + public: + FFTThread(int w) : + m_window(HanningWindow, w) { + m_w = w; + m_fft = new FFTReal(m_w); + m_rin = new double[m_w]; + m_rout = new double[m_w]; + m_iout = new double[m_w]; + } + ~FFTThread() { + delete[] m_rin; + delete[] m_rout; + delete[] m_iout; + delete m_fft; + } + + int getW() const { return m_w; } + + void startCalculation(const float *timeDomain, Spectrograms &s, + int res, int maxwidth) { + setParameters(timeDomain, s, res, maxwidth); + startTask(); + } + + void await() { + awaitTask(); + } + + void setParameters(const float *timeDomain, Spectrograms &s, + int res, int maxwidth) { + m_in = timeDomain; + m_s = &s; + m_res = res; + m_maxwid = maxwidth; + } + + void performTask() { + for (int i = 0; i < m_maxwid / m_w; ++i) { + int origin = m_maxwid/4 - m_w/4; // for 50% overlap + for (int j = 0; j < m_w; ++j) { + m_rin[j] = m_in[origin + i * m_w/2 + j]; + } + m_window.cut(m_rin); + m_fft->process(false, m_rin, m_rout, m_iout); + for (int j = 0; j < m_w/2; ++j) { + int k = j+1; // include Nyquist but not DC + double mag = sqrt(m_rout[k] * m_rout[k] + + m_iout[k] * m_iout[k]); + double scaled = mag / (m_w/2); + m_s->spectrograms[m_res]->data[i][j] = scaled; + } + } + } + + private: + Window<double> m_window; + FFTReal *m_fft; + const float *m_in; + double *m_rin; + double *m_rout; + double *m_iout; + Spectrograms *m_s; + int m_res; + int m_w; + int m_maxwid; + }; + + typedef std::map<int, FFTThread *> FFTMap; + FFTMap m_fftThreads; + + class CutThread : public AsynchronousTask + { + public: + CutThread(const AdaptiveSpectrogram *as) : m_as(as), m_result(0) { + m_allocator = new BlockAllocator(sizeof(Cutting)); + } + ~CutThread() { + delete m_allocator; + } + + void cut(const Spectrograms &s, int res, int x, int y, int h) { + m_s = &s; + m_res = res; + m_x = x; + m_y = y; + m_h = h; + startTask(); + } + + Cutting *get() { + awaitTask(); + return m_result; + } + + protected: + void performTask() { + m_result = m_as->cut(*m_s, m_res, m_x, m_y, m_h, m_allocator); + } + + private: + const AdaptiveSpectrogram *m_as; + BlockAllocator *m_allocator; + const Spectrograms *m_s; + int m_res; + int m_x; + int m_y; + int m_h; + Cutting *m_result; + }; + + mutable std::vector<CutThread *> m_cutThreads; + mutable bool m_threadsInUse; + + inline double xlogx(double x) const { + if (x == 0.0) return 0.0; + else return x * log(x); + } + + inline double cost(const Spectrogram &s, int x, int y) const { + return xlogx(s.data[x][y]); + } + + inline double value(const Spectrogram &s, int x, int y) const { + return s.data[x][y]; + } + + inline double normalize(double vcost, double venergy) const { + return (vcost + (venergy * log(venergy))) / venergy; + } + + inline bool isResolutionWanted(const Spectrograms &s, int res) const { + if (!m_coarse) return true; + if (res == s.minres || res == s.maxres) return true; + int n = 0; + for (int r = res; r > s.minres; r >>= 1) ++n; + return ((n & 0x1) == 0); + } + + Cutting *cut(const Spectrograms &, int res, int x, int y, int h, + BlockAllocator *allocator) const; + + void getSubCuts(const Spectrograms &, int res, int x, int y, int h, + Cutting **top, Cutting **bottom, + Cutting **left, Cutting **right, + BlockAllocator *allocator) const; + + void printCutting(Cutting *, std::string) const; + + void assemble(const Spectrograms &, const Cutting *, + std::vector<std::vector<float> > &, + int x, int y, int w, int h) const; + }; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/BarBeatTrack.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,416 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "BarBeatTrack.h" + +#include <dsp/onsets/DetectionFunction.h> +#include <dsp/onsets/PeakPicking.h> +#include <dsp/tempotracking/TempoTrackV2.h> +#include <dsp/tempotracking/DownBeat.h> +#include <maths/MathUtilities.h> + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + +#ifndef __GNUC__ +#include <alloca.h> +#endif + +float BarBeatTracker::m_stepSecs = 0.01161; // 512 samples at 44100 + +class BarBeatTrackerData +{ +public: + BarBeatTrackerData(float rate, const DFConfig &config) : dfConfig(config) { + df = new DetectionFunction(config); + // decimation factor aims at resampling to c. 3KHz; must be power of 2 + int factor = MathUtilities::nextPowerOfTwo(rate / 3000); +// std::cerr << "BarBeatTrackerData: factor = " << factor << std::endl; + downBeat = new DownBeat(rate, factor, config.stepSize); + } + ~BarBeatTrackerData() { + delete df; + delete downBeat; + } + void reset() { + delete df; + df = new DetectionFunction(dfConfig); + dfOutput.clear(); + downBeat->resetAudioBuffer(); + origin = Vamp::RealTime::zeroTime; + } + + DFConfig dfConfig; + DetectionFunction *df; + DownBeat *downBeat; + vector<double> dfOutput; + Vamp::RealTime origin; +}; + + +BarBeatTracker::BarBeatTracker(float inputSampleRate) : + Vamp::Plugin(inputSampleRate), + m_d(0), + m_bpb(4) +{ +} + +BarBeatTracker::~BarBeatTracker() +{ + delete m_d; +} + +string +BarBeatTracker::getIdentifier() const +{ + return "qm-barbeattracker"; +} + +string +BarBeatTracker::getName() const +{ + return "Bar and Beat Tracker"; +} + +string +BarBeatTracker::getDescription() const +{ + return "Estimate bar and beat locations"; +} + +string +BarBeatTracker::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int +BarBeatTracker::getPluginVersion() const +{ + return 2; +} + +string +BarBeatTracker::getCopyright() const +{ + return "Plugin by Matthew Davies, Christian Landone and Chris Cannam. Copyright (c) 2006-2009 QMUL - All Rights Reserved"; +} + +BarBeatTracker::ParameterList +BarBeatTracker::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + + desc.identifier = "bpb"; + desc.name = "Beats per Bar"; + desc.description = "The number of beats in each bar"; + desc.minValue = 2; + desc.maxValue = 16; + desc.defaultValue = 4; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + return list; +} + +float +BarBeatTracker::getParameter(std::string name) const +{ + if (name == "bpb") return m_bpb; + return 0.0; +} + +void +BarBeatTracker::setParameter(std::string name, float value) +{ + if (name == "bpb") m_bpb = lrintf(value); +} + +bool +BarBeatTracker::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (m_d) { + delete m_d; + m_d = 0; + } + + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) { + std::cerr << "BarBeatTracker::initialise: Unsupported channel count: " + << channels << std::endl; + return false; + } + + if (stepSize != getPreferredStepSize()) { + std::cerr << "ERROR: BarBeatTracker::initialise: Unsupported step size for this sample rate: " + << stepSize << " (wanted " << (getPreferredStepSize()) << ")" << std::endl; + return false; + } + + if (blockSize != getPreferredBlockSize()) { + std::cerr << "WARNING: BarBeatTracker::initialise: Sub-optimal block size for this sample rate: " + << blockSize << " (wanted " << getPreferredBlockSize() << ")" << std::endl; +// return false; + } + + DFConfig dfConfig; + dfConfig.DFType = DF_COMPLEXSD; + dfConfig.stepSize = stepSize; + dfConfig.frameLength = blockSize; + dfConfig.dbRise = 3; + dfConfig.adaptiveWhitening = false; + dfConfig.whiteningRelaxCoeff = -1; + dfConfig.whiteningFloor = -1; + + m_d = new BarBeatTrackerData(m_inputSampleRate, dfConfig); + m_d->downBeat->setBeatsPerBar(m_bpb); + return true; +} + +void +BarBeatTracker::reset() +{ + if (m_d) m_d->reset(); +} + +size_t +BarBeatTracker::getPreferredStepSize() const +{ + size_t step = size_t(m_inputSampleRate * m_stepSecs + 0.0001); + if (step < 1) step = 1; +// std::cerr << "BarBeatTracker::getPreferredStepSize: input sample rate is " << m_inputSampleRate << ", step size is " << step << std::endl; + return step; +} + +size_t +BarBeatTracker::getPreferredBlockSize() const +{ + size_t theoretical = getPreferredStepSize() * 2; + + // I think this is not necessarily going to be a power of two, and + // the host might have a problem with that, but I'm not sure we + // can do much about it here + return theoretical; +} + +BarBeatTracker::OutputList +BarBeatTracker::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor beat; + beat.identifier = "beats"; + beat.name = "Beats"; + beat.description = "Beat locations labelled with metrical position"; + beat.unit = ""; + beat.hasFixedBinCount = true; + beat.binCount = 0; + beat.sampleType = OutputDescriptor::VariableSampleRate; + beat.sampleRate = 1.0 / m_stepSecs; + + OutputDescriptor bars; + bars.identifier = "bars"; + bars.name = "Bars"; + bars.description = "Bar locations"; + bars.unit = ""; + bars.hasFixedBinCount = true; + bars.binCount = 0; + bars.sampleType = OutputDescriptor::VariableSampleRate; + bars.sampleRate = 1.0 / m_stepSecs; + + OutputDescriptor beatcounts; + beatcounts.identifier = "beatcounts"; + beatcounts.name = "Beat Count"; + beatcounts.description = "Beat counter function"; + beatcounts.unit = ""; + beatcounts.hasFixedBinCount = true; + beatcounts.binCount = 1; + beatcounts.sampleType = OutputDescriptor::VariableSampleRate; + beatcounts.sampleRate = 1.0 / m_stepSecs; + + OutputDescriptor beatsd; + beatsd.identifier = "beatsd"; + beatsd.name = "Beat Spectral Difference"; + beatsd.description = "Beat spectral difference function used for bar-line detection"; + beatsd.unit = ""; + beatsd.hasFixedBinCount = true; + beatsd.binCount = 1; + beatsd.sampleType = OutputDescriptor::VariableSampleRate; + beatsd.sampleRate = 1.0 / m_stepSecs; + + list.push_back(beat); + list.push_back(bars); + list.push_back(beatcounts); + list.push_back(beatsd); + + return list; +} + +BarBeatTracker::FeatureSet +BarBeatTracker::process(const float *const *inputBuffers, + Vamp::RealTime timestamp) +{ + if (!m_d) { + cerr << "ERROR: BarBeatTracker::process: " + << "BarBeatTracker has not been initialised" + << endl; + return FeatureSet(); + } + + // We use time domain input, because DownBeat requires it -- so we + // use the time-domain version of DetectionFunction::process which + // does its own FFT. It requires doubles as input, so we need to + // make a temporary copy + + // We only support a single input channel + + const int fl = m_d->dfConfig.frameLength; +#ifndef __GNUC__ + double *dfinput = (double *)alloca(fl * sizeof(double)); +#else + double dfinput[fl]; +#endif + for (int i = 0; i < fl; ++i) dfinput[i] = inputBuffers[0][i]; + + double output = m_d->df->process(dfinput); + + if (m_d->dfOutput.empty()) m_d->origin = timestamp; + +// std::cerr << "df[" << m_d->dfOutput.size() << "] is " << output << std::endl; + m_d->dfOutput.push_back(output); + + // Downsample and store the incoming audio block. + // We have an overlap on the incoming audio stream (step size is + // half block size) -- this function is configured to take only a + // step size's worth, so effectively ignoring the overlap. Note + // however that this means we omit the last blocksize - stepsize + // samples completely for the purposes of barline detection + // (hopefully not a problem) + m_d->downBeat->pushAudioBlock(inputBuffers[0]); + + return FeatureSet(); +} + +BarBeatTracker::FeatureSet +BarBeatTracker::getRemainingFeatures() +{ + if (!m_d) { + cerr << "ERROR: BarBeatTracker::getRemainingFeatures: " + << "BarBeatTracker has not been initialised" + << endl; + return FeatureSet(); + } + + return barBeatTrack(); +} + +BarBeatTracker::FeatureSet +BarBeatTracker::barBeatTrack() +{ + vector<double> df; + vector<double> beatPeriod; + vector<double> tempi; + + for (size_t i = 2; i < m_d->dfOutput.size(); ++i) { // discard first two elts + df.push_back(m_d->dfOutput[i]); + beatPeriod.push_back(0.0); + } + if (df.empty()) return FeatureSet(); + + TempoTrackV2 tt(m_inputSampleRate, m_d->dfConfig.stepSize); + tt.calculateBeatPeriod(df, beatPeriod, tempi); + + vector<double> beats; + tt.calculateBeats(df, beatPeriod, beats); + + vector<int> downbeats; + size_t downLength = 0; + const float *downsampled = m_d->downBeat->getBufferedAudio(downLength); + m_d->downBeat->findDownBeats(downsampled, downLength, beats, downbeats); + + vector<double> beatsd; + m_d->downBeat->getBeatSD(beatsd); + +// std::cerr << "BarBeatTracker: found downbeats at: "; +// for (int i = 0; i < downbeats.size(); ++i) std::cerr << downbeats[i] << " " << std::endl; + + FeatureSet returnFeatures; + + char label[20]; + + int dbi = 0; + int beat = 0; + int bar = 0; + + if (!downbeats.empty()) { + // get the right number for the first beat; this will be + // incremented before use (at top of the following loop) + int firstDown = downbeats[0]; + beat = m_bpb - firstDown - 1; + if (beat == m_bpb) beat = 0; + } + + for (size_t i = 0; i < beats.size(); ++i) { + + size_t frame = beats[i] * m_d->dfConfig.stepSize; + + if (dbi < downbeats.size() && i == downbeats[dbi]) { + beat = 0; + ++bar; + ++dbi; + } else { + ++beat; + } + + // outputs are: + // + // 0 -> beats + // 1 -> bars + // 2 -> beat counter function + + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime + (frame, lrintf(m_inputSampleRate)); + + sprintf(label, "%d", beat + 1); + feature.label = label; + returnFeatures[0].push_back(feature); // labelled beats + + feature.values.push_back(beat + 1); + returnFeatures[2].push_back(feature); // beat function + + if (i > 0 && i <= beatsd.size()) { + feature.values.clear(); + feature.values.push_back(beatsd[i-1]); + feature.label = ""; + returnFeatures[3].push_back(feature); // beat spectral difference + } + + if (beat == 0) { + feature.values.clear(); + sprintf(label, "%d", bar); + feature.label = label; + returnFeatures[1].push_back(feature); // bars + } + } + + return returnFeatures; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/BarBeatTrack.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,62 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _BAR_BEAT_TRACK_PLUGIN_H_ +#define _BAR_BEAT_TRACK_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> + +class BarBeatTrackerData; + +class BarBeatTracker : public Vamp::Plugin +{ +public: + BarBeatTracker(float inputSampleRate); + virtual ~BarBeatTracker(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const { return TimeDomain; } + + 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: + BarBeatTrackerData *m_d; + static float m_stepSecs; + int m_bpb; + FeatureSet barBeatTrack(); +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/BeatTrack.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,525 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "BeatTrack.h" + +#include <dsp/onsets/DetectionFunction.h> +#include <dsp/onsets/PeakPicking.h> +#include <dsp/tempotracking/TempoTrack.h> +#include <dsp/tempotracking/TempoTrackV2.h> + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + +float BeatTracker::m_stepSecs = 0.01161; // 512 samples at 44100 + +#define METHOD_OLD 0 +#define METHOD_NEW 1 + +class BeatTrackerData +{ +public: + BeatTrackerData(const DFConfig &config) : dfConfig(config) { + df = new DetectionFunction(config); + } + ~BeatTrackerData() { + delete df; + } + void reset() { + delete df; + df = new DetectionFunction(dfConfig); + dfOutput.clear(); + origin = Vamp::RealTime::zeroTime; + } + + DFConfig dfConfig; + DetectionFunction *df; + vector<double> dfOutput; + Vamp::RealTime origin; +}; + + +BeatTracker::BeatTracker(float inputSampleRate) : + Vamp::Plugin(inputSampleRate), + m_d(0), + m_method(METHOD_NEW), + m_dfType(DF_COMPLEXSD), + m_whiten(false) +{ +} + +BeatTracker::~BeatTracker() +{ + delete m_d; +} + +string +BeatTracker::getIdentifier() const +{ + return "qm-tempotracker"; +} + +string +BeatTracker::getName() const +{ + return "Tempo and Beat Tracker"; +} + +string +BeatTracker::getDescription() const +{ + return "Estimate beat locations and tempo"; +} + +string +BeatTracker::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int +BeatTracker::getPluginVersion() const +{ + return 5; +} + +string +BeatTracker::getCopyright() const +{ + return "Plugin by Christian Landone and Matthew Davies. Copyright (c) 2006-2009 QMUL - All Rights Reserved"; +} + +BeatTracker::ParameterList +BeatTracker::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + + desc.identifier = "method"; + desc.name = "Beat Tracking Method"; + desc.description = "Basic method to use "; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = METHOD_NEW; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.valueNames.push_back("Old"); + desc.valueNames.push_back("New"); + list.push_back(desc); + + desc.identifier = "dftype"; + desc.name = "Onset Detection Function Type"; + desc.description = "Method used to calculate the onset detection function"; + desc.minValue = 0; + desc.maxValue = 4; + desc.defaultValue = 3; + desc.valueNames.clear(); + desc.valueNames.push_back("High-Frequency Content"); + desc.valueNames.push_back("Spectral Difference"); + desc.valueNames.push_back("Phase Deviation"); + desc.valueNames.push_back("Complex Domain"); + desc.valueNames.push_back("Broadband Energy Rise"); + list.push_back(desc); + + desc.identifier = "whiten"; + desc.name = "Adaptive Whitening"; + desc.description = "Normalize frequency bin magnitudes relative to recent peak levels"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = 0; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.unit = ""; + desc.valueNames.clear(); + list.push_back(desc); + + return list; +} + +float +BeatTracker::getParameter(std::string name) const +{ + if (name == "dftype") { + switch (m_dfType) { + case DF_HFC: return 0; + case DF_SPECDIFF: return 1; + case DF_PHASEDEV: return 2; + default: case DF_COMPLEXSD: return 3; + case DF_BROADBAND: return 4; + } + } else if (name == "method") { + return m_method; + } else if (name == "whiten") { + return m_whiten ? 1.0 : 0.0; + } + return 0.0; +} + +void +BeatTracker::setParameter(std::string name, float value) +{ + if (name == "dftype") { + switch (lrintf(value)) { + case 0: m_dfType = DF_HFC; break; + case 1: m_dfType = DF_SPECDIFF; break; + case 2: m_dfType = DF_PHASEDEV; break; + default: case 3: m_dfType = DF_COMPLEXSD; break; + case 4: m_dfType = DF_BROADBAND; break; + } + } else if (name == "method") { + m_method = lrintf(value); + } else if (name == "whiten") { + m_whiten = (value > 0.5); + } +} + +bool +BeatTracker::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (m_d) { + delete m_d; + m_d = 0; + } + + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) { + std::cerr << "BeatTracker::initialise: Unsupported channel count: " + << channels << std::endl; + return false; + } + + if (stepSize != getPreferredStepSize()) { + std::cerr << "ERROR: BeatTracker::initialise: Unsupported step size for this sample rate: " + << stepSize << " (wanted " << (getPreferredStepSize()) << ")" << std::endl; + return false; + } + + if (blockSize != getPreferredBlockSize()) { + std::cerr << "WARNING: BeatTracker::initialise: Sub-optimal block size for this sample rate: " + << blockSize << " (wanted " << getPreferredBlockSize() << ")" << std::endl; +// return false; + } + + DFConfig dfConfig; + dfConfig.DFType = m_dfType; + dfConfig.stepSize = stepSize; + dfConfig.frameLength = blockSize; + dfConfig.dbRise = 3; + dfConfig.adaptiveWhitening = m_whiten; + dfConfig.whiteningRelaxCoeff = -1; + dfConfig.whiteningFloor = -1; + + m_d = new BeatTrackerData(dfConfig); + return true; +} + +void +BeatTracker::reset() +{ + if (m_d) m_d->reset(); +} + +size_t +BeatTracker::getPreferredStepSize() const +{ + size_t step = size_t(m_inputSampleRate * m_stepSecs + 0.0001); +// std::cerr << "BeatTracker::getPreferredStepSize: input sample rate is " << m_inputSampleRate << ", step size is " << step << std::endl; + return step; +} + +size_t +BeatTracker::getPreferredBlockSize() const +{ + size_t theoretical = getPreferredStepSize() * 2; + + // I think this is not necessarily going to be a power of two, and + // the host might have a problem with that, but I'm not sure we + // can do much about it here + return theoretical; +} + +BeatTracker::OutputList +BeatTracker::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor beat; + beat.identifier = "beats"; + beat.name = "Beats"; + beat.description = "Estimated metrical beat locations"; + beat.unit = ""; + beat.hasFixedBinCount = true; + beat.binCount = 0; + beat.sampleType = OutputDescriptor::VariableSampleRate; + beat.sampleRate = 1.0 / m_stepSecs; + + OutputDescriptor df; + df.identifier = "detection_fn"; + df.name = "Onset Detection Function"; + df.description = "Probability function of note onset likelihood"; + df.unit = ""; + df.hasFixedBinCount = true; + df.binCount = 1; + df.hasKnownExtents = false; + df.isQuantized = false; + df.sampleType = OutputDescriptor::OneSamplePerStep; + + OutputDescriptor tempo; + tempo.identifier = "tempo"; + tempo.name = "Tempo"; + tempo.description = "Locked tempo estimates"; + tempo.unit = "bpm"; + tempo.hasFixedBinCount = true; + tempo.binCount = 1; + tempo.hasKnownExtents = false; + tempo.isQuantized = false; + tempo.sampleType = OutputDescriptor::VariableSampleRate; + tempo.sampleRate = 1.0 / m_stepSecs; + + list.push_back(beat); + list.push_back(df); + list.push_back(tempo); + + return list; +} + +BeatTracker::FeatureSet +BeatTracker::process(const float *const *inputBuffers, + Vamp::RealTime timestamp) +{ + if (!m_d) { + cerr << "ERROR: BeatTracker::process: " + << "BeatTracker has not been initialised" + << endl; + return FeatureSet(); + } + + size_t len = m_d->dfConfig.frameLength / 2; + + double *magnitudes = new double[len]; + double *phases = new double[len]; + + // We only support a single input channel + + for (size_t i = 0; i < len; ++i) { + + magnitudes[i] = sqrt(inputBuffers[0][i*2 ] * inputBuffers[0][i*2 ] + + inputBuffers[0][i*2+1] * inputBuffers[0][i*2+1]); + + phases[i] = atan2(-inputBuffers[0][i*2+1], inputBuffers[0][i*2]); + } + + double output = m_d->df->process(magnitudes, phases); + + delete[] magnitudes; + delete[] phases; + + if (m_d->dfOutput.empty()) m_d->origin = timestamp; + + m_d->dfOutput.push_back(output); + + FeatureSet returnFeatures; + + Feature feature; + feature.hasTimestamp = false; + feature.values.push_back(output); + + returnFeatures[1].push_back(feature); // detection function is output 1 + return returnFeatures; +} + +BeatTracker::FeatureSet +BeatTracker::getRemainingFeatures() +{ + if (!m_d) { + cerr << "ERROR: BeatTracker::getRemainingFeatures: " + << "BeatTracker has not been initialised" + << endl; + return FeatureSet(); + } + + if (m_method == METHOD_OLD) return beatTrackOld(); + else return beatTrackNew(); +} + +BeatTracker::FeatureSet +BeatTracker::beatTrackOld() +{ + double aCoeffs[] = { 1.0000, -0.5949, 0.2348 }; + double bCoeffs[] = { 0.1600, 0.3200, 0.1600 }; + + TTParams ttParams; + ttParams.winLength = 512; + ttParams.lagLength = 128; + ttParams.LPOrd = 2; + ttParams.LPACoeffs = aCoeffs; + ttParams.LPBCoeffs = bCoeffs; + ttParams.alpha = 9; + ttParams.WinT.post = 8; + ttParams.WinT.pre = 7; + + TempoTrack tempoTracker(ttParams); + + vector<double> tempi; + vector<int> beats = tempoTracker.process(m_d->dfOutput, &tempi); + + FeatureSet returnFeatures; + + char label[100]; + + for (size_t i = 0; i < beats.size(); ++i) { + + size_t frame = beats[i] * m_d->dfConfig.stepSize; + + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime + (frame, lrintf(m_inputSampleRate)); + + float bpm = 0.0; + int frameIncrement = 0; + + if (i < beats.size() - 1) { + + frameIncrement = (beats[i+1] - beats[i]) * m_d->dfConfig.stepSize; + + // one beat is frameIncrement frames, so there are + // samplerate/frameIncrement bps, so + // 60*samplerate/frameIncrement bpm + + if (frameIncrement > 0) { + bpm = (60.0 * m_inputSampleRate) / frameIncrement; + bpm = int(bpm * 100.0 + 0.5) / 100.0; + sprintf(label, "%.2f bpm", bpm); + feature.label = label; + } + } + + returnFeatures[0].push_back(feature); // beats are output 0 + } + + double prevTempo = 0.0; + + for (size_t i = 0; i < tempi.size(); ++i) { + + size_t frame = i * m_d->dfConfig.stepSize * ttParams.lagLength; + +// std::cerr << "unit " << i << ", step size " << m_d->dfConfig.stepSize << ", hop " << ttParams.lagLength << ", frame = " << frame << std::endl; + + if (tempi[i] > 1 && int(tempi[i] * 100) != int(prevTempo * 100)) { + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime + (frame, lrintf(m_inputSampleRate)); + feature.values.push_back(tempi[i]); + sprintf(label, "%.2f bpm", tempi[i]); + feature.label = label; + returnFeatures[2].push_back(feature); // tempo is output 2 + prevTempo = tempi[i]; + } + } + + return returnFeatures; +} + +BeatTracker::FeatureSet +BeatTracker::beatTrackNew() +{ + vector<double> df; + vector<double> beatPeriod; + vector<double> tempi; + + size_t nonZeroCount = m_d->dfOutput.size(); + while (nonZeroCount > 0) { + if (m_d->dfOutput[nonZeroCount-1] > 0.0) { + break; + } + --nonZeroCount; + } + + std::cerr << "Note: nonZeroCount was " << m_d->dfOutput.size() << ", is now " << nonZeroCount << std::endl; + + for (size_t i = 2; i < nonZeroCount; ++i) { // discard first two elts + df.push_back(m_d->dfOutput[i]); + beatPeriod.push_back(0.0); + } + if (df.empty()) return FeatureSet(); + + TempoTrackV2 tt(m_inputSampleRate, m_d->dfConfig.stepSize); + + tt.calculateBeatPeriod(df, beatPeriod, tempi); + + vector<double> beats; + tt.calculateBeats(df, beatPeriod, beats); + + FeatureSet returnFeatures; + + char label[100]; + + for (size_t i = 0; i < beats.size(); ++i) { + + size_t frame = beats[i] * m_d->dfConfig.stepSize; + + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime + (frame, lrintf(m_inputSampleRate)); + + float bpm = 0.0; + int frameIncrement = 0; + + if (i+1 < beats.size()) { + + frameIncrement = (beats[i+1] - beats[i]) * m_d->dfConfig.stepSize; + + // one beat is frameIncrement frames, so there are + // samplerate/frameIncrement bps, so + // 60*samplerate/frameIncrement bpm + + if (frameIncrement > 0) { + bpm = (60.0 * m_inputSampleRate) / frameIncrement; + bpm = int(bpm * 100.0 + 0.5) / 100.0; + sprintf(label, "%.2f bpm", bpm); + feature.label = label; + } + } + + returnFeatures[0].push_back(feature); // beats are output 0 + } + + double prevTempo = 0.0; + + for (size_t i = 0; i < tempi.size(); ++i) { + + size_t frame = i * m_d->dfConfig.stepSize; + + if (tempi[i] > 1 && int(tempi[i] * 100) != int(prevTempo * 100)) { + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime + (frame, lrintf(m_inputSampleRate)); + feature.values.push_back(tempi[i]); + sprintf(label, "%.2f bpm", tempi[i]); + feature.label = label; + returnFeatures[2].push_back(feature); // tempo is output 2 + prevTempo = tempi[i]; + } + } + + return returnFeatures; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/BeatTrack.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,65 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _BEAT_TRACK_PLUGIN_H_ +#define _BEAT_TRACK_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> + +class BeatTrackerData; + +class BeatTracker : public Vamp::Plugin +{ +public: + BeatTracker(float inputSampleRate); + virtual ~BeatTracker(); + + 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: + BeatTrackerData *m_d; + int m_method; + int m_dfType; + bool m_whiten; + static float m_stepSecs; + FeatureSet beatTrackOld(); + FeatureSet beatTrackNew(); +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/ChromagramPlugin.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,416 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "ChromagramPlugin.h" + +#include <base/Pitch.h> +#include <dsp/chromagram/Chromagram.h> + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + +ChromagramPlugin::ChromagramPlugin(float inputSampleRate) : + Vamp::Plugin(inputSampleRate), + m_chromagram(0), + m_step(0), + m_block(0) +{ + m_minMIDIPitch = 36; + m_maxMIDIPitch = 96; + m_tuningFrequency = 440; + m_normalise = MathUtilities::NormaliseNone; + m_bpo = 12; + + setupConfig(); +} + +void +ChromagramPlugin::setupConfig() +{ + m_config.FS = lrintf(m_inputSampleRate); + m_config.min = Pitch::getFrequencyForPitch + (m_minMIDIPitch, 0, m_tuningFrequency); + m_config.max = Pitch::getFrequencyForPitch + (m_maxMIDIPitch, 0, m_tuningFrequency); + m_config.BPO = m_bpo; + m_config.CQThresh = 0.0054; + m_config.normalise = m_normalise; + + m_step = 0; + m_block = 0; +} + +ChromagramPlugin::~ChromagramPlugin() +{ + delete m_chromagram; +} + +string +ChromagramPlugin::getIdentifier() const +{ + return "qm-chromagram"; +} + +string +ChromagramPlugin::getName() const +{ + return "Chromagram"; +} + +string +ChromagramPlugin::getDescription() const +{ + return "Extract a series of tonal chroma vectors from the audio"; +} + +string +ChromagramPlugin::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int +ChromagramPlugin::getPluginVersion() const +{ + return 4; +} + +string +ChromagramPlugin::getCopyright() const +{ + return "Plugin by Chris Cannam and Christian Landone. Copyright (c) 2006-2009 QMUL - All Rights Reserved"; +} + +ChromagramPlugin::ParameterList +ChromagramPlugin::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + desc.identifier = "minpitch"; + desc.name = "Minimum Pitch"; + desc.unit = "MIDI units"; + desc.description = "MIDI pitch corresponding to the lowest frequency to be included in the chromagram"; + desc.minValue = 0; + desc.maxValue = 127; + desc.defaultValue = 36; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "maxpitch"; + desc.name = "Maximum Pitch"; + desc.unit = "MIDI units"; + desc.description = "MIDI pitch corresponding to the highest frequency to be included in the chromagram"; + desc.minValue = 0; + desc.maxValue = 127; + desc.defaultValue = 96; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "tuning"; + desc.name = "Tuning Frequency"; + desc.unit = "Hz"; + desc.description = "Frequency of concert A"; + desc.minValue = 360; + desc.maxValue = 500; + desc.defaultValue = 440; + desc.isQuantized = false; + list.push_back(desc); + + desc.identifier = "bpo"; + desc.name = "Bins per Octave"; + desc.unit = "bins"; + desc.description = "Number of constant-Q transform bins per octave, and the number of bins for the chromagram outputs"; + desc.minValue = 2; + desc.maxValue = 480; + desc.defaultValue = 12; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "normalization"; + desc.name = "Normalization"; + desc.unit = ""; + desc.description = "Normalization for each chromagram output column"; + desc.minValue = 0; + desc.maxValue = 2; + desc.defaultValue = 0; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.valueNames.push_back("None"); + desc.valueNames.push_back("Unit Sum"); + desc.valueNames.push_back("Unit Maximum"); + list.push_back(desc); + + return list; +} + +float +ChromagramPlugin::getParameter(std::string param) const +{ + if (param == "minpitch") { + return m_minMIDIPitch; + } + if (param == "maxpitch") { + return m_maxMIDIPitch; + } + if (param == "tuning") { + return m_tuningFrequency; + } + if (param == "bpo") { + return m_bpo; + } + if (param == "normalization") { + return int(m_normalise); + } + std::cerr << "WARNING: ChromagramPlugin::getParameter: unknown parameter \"" + << param << "\"" << std::endl; + return 0.0; +} + +void +ChromagramPlugin::setParameter(std::string param, float value) +{ + if (param == "minpitch") { + m_minMIDIPitch = lrintf(value); + } else if (param == "maxpitch") { + m_maxMIDIPitch = lrintf(value); + } else if (param == "tuning") { + m_tuningFrequency = value; + } else if (param == "bpo") { + m_bpo = lrintf(value); + } else if (param == "normalization") { + m_normalise = MathUtilities::NormaliseType(int(value + 0.0001)); + } else { + std::cerr << "WARNING: ChromagramPlugin::setParameter: unknown parameter \"" + << param << "\"" << std::endl; + } + + setupConfig(); +} + + +bool +ChromagramPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (m_chromagram) { + delete m_chromagram; + m_chromagram = 0; + } + + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) return false; + + m_chromagram = new Chromagram(m_config); + m_binsums = vector<double>(m_config.BPO); + + for (int i = 0; i < m_config.BPO; ++i) { + m_binsums[i] = 0.0; + } + + m_count = 0; + + m_step = m_chromagram->getHopSize(); + m_block = m_chromagram->getFrameSize(); + if (m_step < 1) m_step = 1; + + if (blockSize != m_block) { + std::cerr << "ChromagramPlugin::initialise: ERROR: supplied block size " << blockSize << " differs from required block size " << m_block << ", initialise failing" << std::endl; + delete m_chromagram; + m_chromagram = 0; + return false; + } + + if (stepSize != m_step) { + std::cerr << "ChromagramPlugin::initialise: NOTE: supplied step size " << stepSize << " differs from expected step size " << m_step << " (for block size = " << m_block << ")" << std::endl; + } + + return true; +} + +void +ChromagramPlugin::reset() +{ + if (m_chromagram) { + delete m_chromagram; + m_chromagram = new Chromagram(m_config); + for (int i = 0; i < m_config.BPO; ++i) { + m_binsums[i] = 0.0; + } + m_count = 0; + } +} + +size_t +ChromagramPlugin::getPreferredStepSize() const +{ + if (!m_step) { + Chromagram chroma(m_config); + m_step = chroma.getHopSize(); + m_block = chroma.getFrameSize(); + if (m_step < 1) m_step = 1; + } + + return m_step; +} + +size_t +ChromagramPlugin::getPreferredBlockSize() const +{ + if (!m_block) { + Chromagram chroma(m_config); + m_step = chroma.getHopSize(); + m_block = chroma.getFrameSize(); + if (m_step < 1) m_step = 1; + } + + return m_block; +} + +ChromagramPlugin::OutputList +ChromagramPlugin::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor d; + d.identifier = "chromagram"; + d.name = "Chromagram"; + d.unit = ""; + d.description = "Output of chromagram, as a single vector per process block"; + d.hasFixedBinCount = true; + d.binCount = m_config.BPO; + + const char *names[] = + { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; + + if (d.binCount % 12 == 0) { + for (int i = 0; i < 12; ++i) { + int ipc = m_minMIDIPitch % 12; + int index = (i + ipc) % 12; + d.binNames.push_back(names[index]); + for (int j = 0; j < int(d.binCount) / 12 - 1; ++j) { + d.binNames.push_back(""); + } + } + } else { + d.binNames.push_back(names[m_minMIDIPitch % 12]); + } + + d.hasKnownExtents = (m_normalise != MathUtilities::NormaliseNone); + d.minValue = 0.0; + d.maxValue = (d.hasKnownExtents ? 1.0 : 0.0); + d.isQuantized = false; + d.sampleType = OutputDescriptor::OneSamplePerStep; + list.push_back(d); + + d.identifier = "chromameans"; + d.name = "Chroma Means"; + d.description = "Mean values of chromagram bins across the duration of the input audio"; + d.sampleType = OutputDescriptor::FixedSampleRate; + d.sampleRate = 1; + list.push_back(d); + + return list; +} + +ChromagramPlugin::FeatureSet +ChromagramPlugin::process(const float *const *inputBuffers, + Vamp::RealTime timestamp) +{ + if (!m_chromagram) { + cerr << "ERROR: ChromagramPlugin::process: " + << "Chromagram has not been initialised" + << endl; + return FeatureSet(); + } + + double *real = new double[m_block]; + double *imag = new double[m_block]; + + for (size_t i = 0; i <= m_block/2; ++i) { + real[i] = inputBuffers[0][i*2]; + if (i > 0) real[m_block - i] = real[i]; + imag[i] = inputBuffers[0][i*2+1]; + if (i > 0) imag[m_block - i] = imag[i]; + } + +// cerr << "chromagram: timestamp = " << timestamp << endl; +/* + bool printThis = false; + + if (timestamp.sec == 3 && timestamp.nsec < 250000000) { + printThis = true; + } + if (printThis) { + cerr << "\n\nchromagram: timestamp " << timestamp << ": input data starts:" << endl; + for (int i = 0; i < m_block && i < 1000; ++i) { + cerr << real[i] << "," << imag[i] << " "; + } + cerr << endl << "values:" << endl; + } +*/ + double *output = m_chromagram->process(real, imag); + + delete[] real; + delete[] imag; + + Feature feature; + feature.hasTimestamp = false; + for (size_t i = 0; i < m_config.BPO; ++i) { + double value = output[i]; +/* + if (printThis) { + cerr << value << " "; + } +*/ + if (ISNAN(value)) value = 0.0; + m_binsums[i] += value; + feature.values.push_back(value); + } + feature.label = ""; + ++m_count; +/* + if (printThis) { + cerr << endl; + } +*/ + + FeatureSet returnFeatures; + returnFeatures[0].push_back(feature); + return returnFeatures; +} + +ChromagramPlugin::FeatureSet +ChromagramPlugin::getRemainingFeatures() +{ + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = Vamp::RealTime::zeroTime; + + for (size_t i = 0; i < m_config.BPO; ++i) { + double v = m_binsums[i]; + if (m_count > 0) v /= m_count; + feature.values.push_back(v); + } + feature.label = "Chromagram bin means"; + + FeatureSet returnFeatures; + returnFeatures[1].push_back(feature); + return returnFeatures; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/ChromagramPlugin.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,72 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _CHROMAGRAM_PLUGIN_H_ +#define _CHROMAGRAM_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> +#include <dsp/chromagram/Chromagram.h> + +class ChromagramPlugin : public Vamp::Plugin +{ +public: + ChromagramPlugin(float inputSampleRate); + virtual ~ChromagramPlugin(); + + 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: + int m_minMIDIPitch; + int m_maxMIDIPitch; + float m_tuningFrequency; + MathUtilities::NormaliseType m_normalise; + int m_bpo; + + void setupConfig(); + + ChromaConfig m_config; + Chromagram *m_chromagram; + mutable size_t m_step; + mutable size_t m_block; + + vector<double> m_binsums; + size_t m_count; +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/ConstantQSpectrogram.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,394 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "ConstantQSpectrogram.h" + +#include <base/Pitch.h> +#include <dsp/chromagram/ConstantQ.h> + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + +ConstantQSpectrogram::ConstantQSpectrogram(float inputSampleRate) : + Vamp::Plugin(inputSampleRate), + m_bins(1), + m_cq(0), + m_step(0), + m_block(0) +{ + m_minMIDIPitch = 36; + m_maxMIDIPitch = 84; + m_tuningFrequency = 440; + m_normalized = false; + m_bpo = 12; + + setupConfig(); +} + +void +ConstantQSpectrogram::setupConfig() +{ + m_config.FS = lrintf(m_inputSampleRate); + m_config.min = Pitch::getFrequencyForPitch + (m_minMIDIPitch, 0, m_tuningFrequency); + m_config.max = Pitch::getFrequencyForPitch + (m_maxMIDIPitch, 0, m_tuningFrequency); + m_config.BPO = m_bpo; + m_config.CQThresh = 0.0054; + + m_step = 0; + m_block = 0; +} + +ConstantQSpectrogram::~ConstantQSpectrogram() +{ + delete m_cq; +} + +string +ConstantQSpectrogram::getIdentifier() const +{ + return "qm-constantq"; +} + +string +ConstantQSpectrogram::getName() const +{ + return "Constant-Q Spectrogram"; +} + +string +ConstantQSpectrogram::getDescription() const +{ + return "Extract a spectrogram with constant ratio of centre frequency to resolution from the input audio"; +} + +string +ConstantQSpectrogram::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int +ConstantQSpectrogram::getPluginVersion() const +{ + return 3; +} + +string +ConstantQSpectrogram::getCopyright() const +{ + return "Plugin by Chris Cannam and Christian Landone. Copyright (c) 2006-2009 QMUL - All Rights Reserved"; +} + +ConstantQSpectrogram::ParameterList +ConstantQSpectrogram::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + desc.identifier = "minpitch"; + desc.name = "Minimum Pitch"; + desc.unit = "MIDI units"; + desc.description = "MIDI pitch corresponding to the lowest frequency to be included in the constant-Q transform"; + desc.minValue = 0; + desc.maxValue = 127; + desc.defaultValue = 36; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "maxpitch"; + desc.name = "Maximum Pitch"; + desc.unit = "MIDI units"; + desc.description = "MIDI pitch corresponding to the highest frequency to be included in the constant-Q transform"; + desc.minValue = 0; + desc.maxValue = 127; + desc.defaultValue = 84; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "tuning"; + desc.name = "Tuning Frequency"; + desc.unit = "Hz"; + desc.description = "Frequency of concert A"; + desc.minValue = 360; + desc.maxValue = 500; + desc.defaultValue = 440; + desc.isQuantized = false; + list.push_back(desc); + + desc.identifier = "bpo"; + desc.name = "Bins per Octave"; + desc.unit = "bins"; + desc.description = "Number of constant-Q transform bins per octave"; + desc.minValue = 2; + desc.maxValue = 480; + desc.defaultValue = 12; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "normalized"; + desc.name = "Normalized"; + desc.unit = ""; + desc.description = "Whether to normalize each output column to unit maximum"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = 0; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + return list; +} + +float +ConstantQSpectrogram::getParameter(std::string param) const +{ + if (param == "minpitch") { + return m_minMIDIPitch; + } + if (param == "maxpitch") { + return m_maxMIDIPitch; + } + if (param == "tuning") { + return m_tuningFrequency; + } + if (param == "bpo") { + return m_bpo; + } + if (param == "normalized") { + return m_normalized; + } + std::cerr << "WARNING: ConstantQSpectrogram::getParameter: unknown parameter \"" + << param << "\"" << std::endl; + return 0.0; +} + +void +ConstantQSpectrogram::setParameter(std::string param, float value) +{ + if (param == "minpitch") { + m_minMIDIPitch = lrintf(value); + } else if (param == "maxpitch") { + m_maxMIDIPitch = lrintf(value); + } else if (param == "tuning") { + m_tuningFrequency = value; + } else if (param == "bpo") { + m_bpo = lrintf(value); + } else if (param == "normalized") { + m_normalized = (value > 0.0001); + } else { + std::cerr << "WARNING: ConstantQSpectrogram::setParameter: unknown parameter \"" + << param << "\"" << std::endl; + } + + setupConfig(); +} + + +bool +ConstantQSpectrogram::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (m_cq) { + delete m_cq; + m_cq = 0; + } + + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) return false; + + setupConfig(); + + m_cq = new ConstantQ(m_config); + m_bins = m_cq->getK(); + m_cq->sparsekernel(); + m_step = m_cq->gethop(); + m_block = m_cq->getfftlength(); + + if (blockSize != m_block) { + std::cerr << "ConstantQSpectrogram::initialise: ERROR: supplied block size " << blockSize << " differs from required block size " << m_block << ", initialise failing" << std::endl; + delete m_cq; + m_cq = 0; + return false; + } + + if (stepSize != m_step) { + std::cerr << "ConstantQSpectrogram::initialise: NOTE: supplied step size " << stepSize << " differs from expected step size " << m_step << " (for block size = " << m_block << ")" << std::endl; + } + + return true; +} + +void +ConstantQSpectrogram::reset() +{ + if (m_cq) { + delete m_cq; + m_cq = new ConstantQ(m_config); + m_bins = m_cq->getK(); + m_cq->sparsekernel(); + m_step = m_cq->gethop(); + m_block = m_cq->getfftlength(); + } +} + +size_t +ConstantQSpectrogram::getPreferredStepSize() const +{ + if (!m_step) { + ConstantQ cq(m_config); + m_step = cq.gethop(); + m_block = cq.getfftlength(); + } + + return m_step; +} + +size_t +ConstantQSpectrogram::getPreferredBlockSize() const +{ + if (!m_block) { + ConstantQ cq(m_config); + m_step = cq.gethop(); + m_block = cq.getfftlength(); + } + + return m_block; +} + +ConstantQSpectrogram::OutputList +ConstantQSpectrogram::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor d; + d.identifier = "constantq"; + d.name = "Constant-Q Spectrogram"; + d.unit = ""; + d.description = "Output of constant-Q transform, as a single vector per process block"; + d.hasFixedBinCount = true; + d.binCount = m_bins; + +// std::cerr << "Bin count " << d.binCount << std::endl; + + const char *names[] = + { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; + + if (m_bpo == 12) { + for (int i = 0; i < int(d.binCount); ++i) { + int ipc = m_minMIDIPitch % 12; + int index = (i + ipc) % 12; + d.binNames.push_back(names[index]); + } + } else { + d.binNames.push_back(names[m_minMIDIPitch % 12]); + } + + d.hasKnownExtents = m_normalized; + d.minValue = 0.0; + d.maxValue = (m_normalized ? 1.0 : 0.0); + d.isQuantized = false; + d.sampleType = OutputDescriptor::OneSamplePerStep; + list.push_back(d); + + return list; +} + +ConstantQSpectrogram::Feature +ConstantQSpectrogram::normalize(const Feature &feature) +{ + float min = 0.0, max = 0.0; + + for (size_t i = 0; i < feature.values.size(); ++i) { + if (i == 0 || feature.values[i] < min) min = feature.values[i]; + if (i == 0 || feature.values[i] > max) max = feature.values[i]; + } + + if (max == 0.0 || max == min) return feature; + + Feature normalized; + normalized.hasTimestamp = false; + + for (size_t i = 0; i < feature.values.size(); ++i) { + normalized.values.push_back((feature.values[i] - min) / (max - min)); + } + + return normalized; +} + +ConstantQSpectrogram::FeatureSet +ConstantQSpectrogram::process(const float *const *inputBuffers, + Vamp::RealTime /* timestamp */) +{ + if (!m_cq) { + cerr << "ERROR: ConstantQSpectrogram::process: " + << "Constant-Q has not been initialised" + << endl; + return FeatureSet(); + } + + double *real = new double[m_block]; + double *imag = new double[m_block]; + double *cqre = new double[m_bins]; + double *cqim = new double[m_bins]; + +// std::cout << "in:" << std::endl; + for (size_t i = 0; i <= m_block/2; ++i) { + real[i] = inputBuffers[0][i*2]; + if (i > 0) real[m_block - i] = real[i]; + imag[i] = inputBuffers[0][i*2+1]; + if (i > 0) imag[m_block - i] = imag[i]; //!!! huh? surely -imag[i] ? +// std::cout << real[i] << "," << imag[i] << " "; + } + + m_cq->process(real, imag, cqre, cqim); + + delete[] real; + delete[] imag; + +// std::cout << "\nout:" << std::endl; + Feature feature; + feature.hasTimestamp = false; + for (int i = 0; i < m_bins; ++i) { + double re = cqre[i]; + double im = cqim[i]; +// std::cout << re << "," << im << ":"; + if (ISNAN(re)) re = 0.0; + if (ISNAN(im)) im = 0.0; + double value = sqrt(re * re + im * im); +// std::cout << value << " "; + feature.values.push_back(value); + } + feature.label = ""; + + delete[] cqre; + delete[] cqim; + + FeatureSet returnFeatures; + if (m_normalized) returnFeatures[0].push_back(normalize(feature)); + else returnFeatures[0].push_back(feature); + return returnFeatures; +} + +ConstantQSpectrogram::FeatureSet +ConstantQSpectrogram::getRemainingFeatures() +{ + return FeatureSet(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/ConstantQSpectrogram.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,74 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _CONSTANT_Q_SPECTROGRAM_PLUGIN_H_ +#define _CONSTANT_Q_SPECTROGRAM_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> +#include <dsp/chromagram/ConstantQ.h> + +#include <queue> + +class ConstantQSpectrogram : public Vamp::Plugin +{ +public: + ConstantQSpectrogram(float inputSampleRate); + virtual ~ConstantQSpectrogram(); + + 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: + int m_minMIDIPitch; + int m_maxMIDIPitch; + float m_tuningFrequency; + bool m_normalized; + int m_bpo; + int m_bins; + + void setupConfig(); + + CQConfig m_config; + ConstantQ *m_cq; + mutable size_t m_step; + mutable size_t m_block; + + Feature normalize(const Feature &); +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/DWT.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,448 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2009 Thomas Wilmering. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "DWT.h" + +#include <cmath> + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + +DWT::DWT(float inputSampleRate) : + Plugin(inputSampleRate), + m_stepSize(0), + m_blockSize(0) +{ + m_scales = 10; + m_flength = 0; + m_wavelet = Wavelet::Haar; + m_threshold = 0; + m_absolute = 0; +} + +DWT::~DWT() +{ +} + +string +DWT::getIdentifier() const +{ + return "qm-dwt"; +} + +string +DWT::getName() const +{ + return "Discrete Wavelet Transform"; +} + +string +DWT::getDescription() const +{ + return "Visualisation by scalogram"; +} + +string +DWT::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int +DWT::getPluginVersion() const +{ + return 1; +} + +string +DWT::getCopyright() const +{ + return "Plugin by Thomas Wilmering. Copyright (c) 2009 Thomas Wilmering and QMUL - All Rights Reserved"; +} + +size_t +DWT::getPreferredBlockSize() const +{ + size_t s = (1 << m_scales); + while (s < 1024) s *= 2; + return s; +} + +size_t +DWT::getPreferredStepSize() const +{ + return 0; +} + +bool +DWT::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) return false; + + if ((1 << m_scales) > blockSize) { + std::cerr << "DWT::initialise: ERROR: Block size must be at least 2^scales (specified block size " << blockSize << " < " << (1 << m_scales) << ")" << std::endl; + return false; + } + + m_stepSize = stepSize; + m_blockSize = blockSize; + + Wavelet::createDecompositionFilters(m_wavelet, m_lpd, m_hpd); + + m_flength = m_lpd.size(); // or m_hpd.size() + + m_samplePass.resize(m_scales); // resize buffer for samples to pass to next block + + for (int i=0; i<m_scales; ++i) { + m_samplePass[i].resize(m_flength-2, 0.0); + } + + return true; +} + +void +DWT::reset() +{ + m_samplePass.clear(); + + m_samplePass.resize(m_scales); + + for (int i=0; i<m_scales; ++i) { + m_samplePass[i].resize(m_flength-2, 0.0); + } +} + +DWT::OutputList +DWT::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor sg; + sg.identifier = "wcoeff"; + sg.name = "Wavelet Coefficients"; + sg.description = "Wavelet coefficients"; + sg.unit = ""; + sg.hasFixedBinCount = true; // depends on block size + sg.binCount = m_scales; // number of scales + sg.hasKnownExtents = false; + sg.isQuantized = false; + sg.sampleType = OutputDescriptor::FixedSampleRate; + sg.sampleRate = .5 * m_inputSampleRate; + + list.push_back(sg); + + return list; +} + + +DWT::ParameterList +DWT::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor d; + d.identifier = "scales"; + d.name = "Scales"; + d.description = "Scale depth"; + d.unit = ""; + d.minValue = 1.0f; + d.maxValue = 16.0f; + d.defaultValue = 10.0f; + d.isQuantized = true; + d.quantizeStep = 1.0f; + list.push_back(d); + + d.identifier = "wavelet"; + d.name = "Wavelet"; + d.description = "Wavelet type to use"; + d.unit = ""; + d.minValue = 0.f; + d.maxValue = int(Wavelet::LastType); + d.defaultValue = int(Wavelet::Haar); + d.isQuantized = true; + d.quantizeStep = 1.0f; + + for (int i = 0; i <= int(Wavelet::LastType); ++i) { + d.valueNames.push_back(Wavelet::getWaveletName(Wavelet::Type(i))); + } + list.push_back(d); + d.valueNames.clear(); + + d.identifier = "threshold"; + d.name = "Threshold"; + d.description = "Wavelet coefficient threshold"; + d.unit = ""; + d.minValue = 0.0f; + d.maxValue = 0.01f; + d.defaultValue = 0.0f; + d.isQuantized = false; + list.push_back(d); + + d.identifier = "absolute"; + d.name = "Absolute values"; + d.description = "Return absolute values"; + d.unit = ""; + d.minValue = 0.0f; + d.maxValue = 1.00f; + d.defaultValue = 0.0f; + d.isQuantized = true; + d.quantizeStep = 1.0f; + list.push_back(d); + + return list; +} + +void DWT::setParameter(std::string paramid, float newval) +{ + if (paramid == "scales") { + m_scales = newval; + } + else if (paramid == "wavelet") { + m_wavelet = (Wavelet::Type)(int(newval + 0.1)); + } + else if (paramid == "threshold") { + m_threshold = newval; + } + else if (paramid == "absolute") { + m_absolute = newval; + } +} + +float DWT::getParameter(std::string paramid) const +{ + if (paramid == "scales") { + return m_scales; + } + else if (paramid == "wavelet") { + return int(m_wavelet); + } + else if (paramid == "threshold") { + return m_threshold; + } + else if (paramid == "absolute") { + return m_absolute; + } + + return 0.0f; +} + + +DWT::FeatureSet +DWT::process(const float *const *inputBuffers, + Vamp::RealTime) +{ + FeatureSet fs; + + if (m_blockSize == 0) { + cerr << "ERROR: DWT::process: Not initialised" << endl; + return fs; + } + + int s = m_scales; + int b = m_blockSize; + int b_init = b; + + if ((1 << s) > b) b = 1 << s; // correct blocksize if smaller than 2^(max scale) + +//-------------------------------------------------------------------------------------------------- + + float tempDet; + float aTempDet; + int outloc; + int halfblocksize = int(.5 * b); + int fbufloc; + int fbufloc2; + + vector< vector<float> > wCoefficients(m_scales); // result + vector<float> tempAprx(halfblocksize,0.0); // approximation + vector<float> fbuf(b+m_flength-2,0.0); // input buffer + + for (int n=m_flength-2; n<b+m_flength-2; n++) // copy input buffer to dwt input + fbuf[n] = inputBuffers[0][n-m_flength+2]; + + for (int scale=0; scale<m_scales; ++scale) // do for each scale + { + for (int n=0; n<m_flength-2; ++n) // get samples from previous block + fbuf[n] = m_samplePass[scale][n]; + + + if ((m_flength-2)<b) // pass samples to next block + for (int n=0; n<m_flength-2; ++n) + m_samplePass[scale][n] = fbuf[b+n]; + else { + for (int n=0; n<b; ++n) // if number of samples to pass > blocksize + m_samplePass[scale].push_back(fbuf[m_flength-2+n]); + m_samplePass[scale].erase (m_samplePass[scale].begin(),m_samplePass[scale].begin()+b); + } + + for (int n=0; n<halfblocksize; ++n) { // do for every other sample of the input buffer + tempDet = 0; + fbufloc = 2*n+m_flength-1; + for (int m=0; m<m_flength; ++m) { // Convolve the sample with filter coefficients + fbufloc2 = fbufloc - m; + tempAprx[n] += fbuf[fbufloc2] * m_lpd[m]; // approximation + tempDet += fbuf[fbufloc2] * m_hpd[m]; // detail + } + + aTempDet = fabs(tempDet); + if (m_absolute == 1) tempDet = aTempDet; + + + if (aTempDet < m_threshold) tempDet = 0; // simple hard thresholding, same for each scale + wCoefficients[scale].push_back(tempDet); + } + + if (scale+1<m_scales) { // prepare variables for next scale + b = b >> 1; // the approximation in tmpfwd is stored as + halfblocksize = halfblocksize >> 1; // input for next level + + for (int n=m_flength-2; n<b+m_flength-2; n++) // copy approximation to dwt input + fbuf[n] = tempAprx[n-m_flength+2]; + + //vector<float>(b+m_flength-2).swap(fbuf); + vector<float>(halfblocksize).swap(tempAprx); // set new size with zeros + } + } + + +//----------------------------------------------------------------------------------------- + + halfblocksize = int(.5 * b_init); + + for (int m = 0; m<halfblocksize; m++) { + + Feature feature; + feature.hasTimestamp = false; + + for (int j = 0; j < s; j++) { + outloc = m / (1 << j); // This one pushes a single result bin + // onto the top of a feature column + feature.values.push_back(wCoefficients[j][outloc]); // each coefficient on higher scales need + } // to be copied multiple times to feature columns + fs[0].push_back(feature); + } + return fs; +} + + + +DWT::FeatureSet +DWT::getRemainingFeatures() +{ + int s = m_scales; + + FeatureSet fs; + +/* + int b = 1; + while (b<((m_flength-1) * (1 << s))) { //set blocksize to tail length + b= (b << 1); + } + int b_init = b; + +*/ + int b = m_blockSize; + int b_init = b; + int tailIterations = int(((m_flength-1) * (1 << s)) / b) + 1; // number of iterations for tail + + + for(int m=0; m<tailIterations; ++m) + { + + b = b_init; + + //------------------------------------------------------------------------------------------- + float tempDet; + float aTempDet; + int outloc; + int halfblocksize = int(.5 * b); + int fbufloc; + int fbufloc2; + int len = m_flength; + + vector< vector<float> > wCoefficients(m_scales); // result + vector<float> tempAprx(halfblocksize,0.0); // approximation + vector<float> fbuf(b+len-2,0.0); // input buffer + + //for (int n=len-2; n<b+len-2; n++) // copy input buffer to dwt input + // fbuf[n] = 0; //inputBuffers[0][n-len+2]; + + for (int scale=0; scale<m_scales; ++scale) // do for each scale + { + for (int n=0; n<len-2; ++n) // get samples from previous block + fbuf[n] = m_samplePass[scale][n]; + + + if ((len-2)<b) // pass samples to next block + for (int n=0; n<len-2; ++n) + m_samplePass[scale][n] = fbuf[b+n]; + else { + for (int n=0; n<b; ++n) // if number of samples to pass > blocksize + m_samplePass[scale].push_back(fbuf[len-2+n]); + m_samplePass[scale].erase (m_samplePass[scale].begin(),m_samplePass[scale].begin()+b); + } + + for (int n=0; n<halfblocksize; ++n) { // do for every other sample of the input buffer + tempDet = 0; + fbufloc = 2*n+len-1; + for (int m=0; m<len; ++m) { // Convolve the sample with filter coefficients + fbufloc2 = fbufloc - m; + tempAprx[n] += fbuf[fbufloc2] * m_lpd[m]; // approximation + tempDet += fbuf[fbufloc2] * m_hpd[m]; // detail + } + + aTempDet = fabs(tempDet); + if (m_absolute == 1) tempDet = aTempDet; + if (aTempDet < m_threshold) tempDet = 0; // simple hard thresholding, same for each scale + wCoefficients[scale].push_back(tempDet); + } + + if (scale+1<m_scales) { // prepare variables for next scale + b = b >> 1; // the approximation in tmpfwd is stored as + halfblocksize = halfblocksize >> 1; // input for next level + + for (int n=len-2; n<b+len-2; n++) // copy approximation to dwt input + fbuf[n] = tempAprx[n-len+2]; + + //vector<float>(b+len-2).swap(fbuf); + vector<float>(halfblocksize).swap(tempAprx); // set new size with zeros + } + + } + +//----------------------------------------------------------------------------------------- + + halfblocksize = int(.5 * b_init + 0.1); + + for (int m = 0; m<halfblocksize; m++) { + + Feature feature; + feature.hasTimestamp = false; + + for (int j = 0; j < s; j++) { + outloc = m / (1 << j); // This one pushes a single result bin + // onto the top of a feature column + feature.values.push_back(wCoefficients[j][outloc]); // each coefficient on higher scales need + } // to be copied multiple times to feature columns + fs[0].push_back(feature); + } + } + return fs; + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/DWT.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,73 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2009 Thomas Wilmering. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _DWT_PLUGIN_H_ +#define _DWT_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> + +#include <dsp/wavelet/Wavelet.h> + +using std::vector; + +class DWT : public Vamp::Plugin +{ +public: + DWT(float inputSampleRate); + virtual ~DWT(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const { return TimeDomain; } + + std::string getIdentifier() const; + std::string getName() const; + std::string getDescription() const; + std::string getMaker() const; + int getPluginVersion() const; + std::string getCopyright() const; + size_t getPreferredBlockSize() const; + size_t getPreferredStepSize() const; + + OutputList getOutputDescriptors() const; + + ParameterList getParameterDescriptors() const; + float getParameter(std::string paramid) const; + void setParameter(std::string paramid, float newval); + + FeatureSet process(const float *const *inputBuffers, + Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + size_t m_stepSize; + size_t m_blockSize; + + int m_scales; + int m_flength; + Wavelet::Type m_wavelet; + float m_threshold; + float m_absolute; + + vector<float> m_lpd; + vector<float> m_hpd; + + vector< vector<float> > m_samplePass; +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/KeyDetect.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,407 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "KeyDetect.h" + +using std::string; +using std::vector; +//using std::cerr; +using std::endl; + +#include <cmath> + + +// Order for circle-of-5ths plotting +static int conversion[24] = +{ 7, 12, 5, 10, 3, 8, 1, 6, 11, 4, 9, 2, + 16, 21, 14, 19, 24, 17, 22, 15, 20, 13, 18, 23 }; + + +KeyDetector::KeyDetector(float inputSampleRate) : + Plugin(inputSampleRate), + m_stepSize(0), + m_blockSize(0), + m_tuningFrequency(440), + m_length(10), + m_getKeyMode(0), + m_inputFrame(0), + m_prevKey(-1) +{ +} + +KeyDetector::~KeyDetector() +{ + delete m_getKeyMode; + if ( m_inputFrame ) { + delete [] m_inputFrame; + } +} + +string +KeyDetector::getIdentifier() const +{ + return "qm-keydetector"; +} + +string +KeyDetector::getName() const +{ + return "Key Detector"; +} + +string +KeyDetector::getDescription() const +{ + return "Estimate the key of the music"; +} + +string +KeyDetector::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int +KeyDetector::getPluginVersion() const +{ + return 4; +} + +string +KeyDetector::getCopyright() const +{ + return "Plugin by Katy Noland and Christian Landone. Copyright (c) 2006-2009 QMUL - All Rights Reserved"; +} + +KeyDetector::ParameterList +KeyDetector::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + desc.identifier = "tuning"; + desc.name = "Tuning Frequency"; + desc.description = "Frequency of concert A"; + desc.unit = "Hz"; + desc.minValue = 420; + desc.maxValue = 460; + desc.defaultValue = 440; + desc.isQuantized = false; + list.push_back(desc); + + desc.identifier = "length"; + desc.name = "Window Length"; + desc.unit = "chroma frames"; + desc.description = "Number of chroma analysis frames per key estimation"; + desc.minValue = 1; + desc.maxValue = 30; + desc.defaultValue = 10; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + return list; +} + +float +KeyDetector::getParameter(std::string param) const +{ + if (param == "tuning") { + return m_tuningFrequency; + } + if (param == "length") { + return m_length; + } + std::cerr << "WARNING: KeyDetector::getParameter: unknown parameter \"" + << param << "\"" << std::endl; + return 0.0; +} + +void +KeyDetector::setParameter(std::string param, float value) +{ + if (param == "tuning") { + m_tuningFrequency = value; + } else if (param == "length") { + m_length = int(value + 0.1); + } else { + std::cerr << "WARNING: KeyDetector::setParameter: unknown parameter \"" + << param << "\"" << std::endl; + } +} + +bool +KeyDetector::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (m_getKeyMode) { + delete m_getKeyMode; + m_getKeyMode = 0; + } + + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) return false; + + m_getKeyMode = new GetKeyMode(int(m_inputSampleRate + 0.1), + m_tuningFrequency, + m_length, m_length); + + m_stepSize = m_getKeyMode->getHopSize(); + m_blockSize = m_getKeyMode->getBlockSize(); + + if (stepSize != m_stepSize || blockSize != m_blockSize) { + std::cerr << "KeyDetector::initialise: ERROR: step/block sizes " + << stepSize << "/" << blockSize << " differ from required " + << m_stepSize << "/" << m_blockSize << std::endl; + delete m_getKeyMode; + m_getKeyMode = 0; + return false; + } + + m_inputFrame = new double[m_blockSize]; + + m_prevKey = -1; + m_first = true; + + return true; +} + +void +KeyDetector::reset() +{ + if (m_getKeyMode) { + delete m_getKeyMode; + m_getKeyMode = new GetKeyMode(int(m_inputSampleRate + 0.1), + m_tuningFrequency, + m_length, m_length); + } + + if (m_inputFrame) { + for( unsigned int i = 0; i < m_blockSize; i++ ) { + m_inputFrame[ i ] = 0.0; + } + } + + m_prevKey = -1; + m_first = true; +} + + +KeyDetector::OutputList +KeyDetector::getOutputDescriptors() const +{ + OutputList list; + + float osr = 0.0f; + if (m_stepSize == 0) (void)getPreferredStepSize(); + osr = m_inputSampleRate / m_stepSize; + + OutputDescriptor d; + d.identifier = "tonic"; + d.name = "Tonic Pitch"; + d.unit = ""; + d.description = "Tonic of the estimated key (from C = 1 to B = 12)"; + d.hasFixedBinCount = true; + d.binCount = 1; + d.hasKnownExtents = true; + d.isQuantized = true; + d.minValue = 1; + d.maxValue = 12; + d.quantizeStep = 1; + d.sampleRate = osr; + d.sampleType = OutputDescriptor::VariableSampleRate; + list.push_back(d); + + d.identifier = "mode"; + d.name = "Key Mode"; + d.unit = ""; + d.description = "Major or minor mode of the estimated key (major = 0, minor = 1)"; + d.hasFixedBinCount = true; + d.binCount = 1; + d.hasKnownExtents = true; + d.isQuantized = true; + d.minValue = 0; + d.maxValue = 1; + d.quantizeStep = 1; + d.sampleRate = osr; + d.sampleType = OutputDescriptor::VariableSampleRate; + list.push_back(d); + + d.identifier = "key"; + d.name = "Key"; + d.unit = ""; + d.description = "Estimated key (from C major = 1 to B major = 12 and C minor = 13 to B minor = 24)"; + d.hasFixedBinCount = true; + d.binCount = 1; + d.hasKnownExtents = true; + d.isQuantized = true; + d.minValue = 1; + d.maxValue = 24; + d.quantizeStep = 1; + d.sampleRate = osr; + d.sampleType = OutputDescriptor::VariableSampleRate; + list.push_back(d); + + d.identifier = "keystrength"; + d.name = "Key Strength Plot"; + d.unit = ""; + d.description = "Correlation of the chroma vector with stored key profile for each major and minor key"; + d.hasFixedBinCount = true; + d.binCount = 25; + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::OneSamplePerStep; + for (int i = 0; i < 24; ++i) { + if (i == 12) d.binNames.push_back(" "); + int idx = conversion[i]; + std::string label = getKeyName(idx > 12 ? idx-12 : idx, + i >= 12, + true); + d.binNames.push_back(label); + } + list.push_back(d); + + return list; +} + +KeyDetector::FeatureSet +KeyDetector::process(const float *const *inputBuffers, + Vamp::RealTime now) +{ + if (m_stepSize == 0) { + return FeatureSet(); + } + + FeatureSet returnFeatures; + + for ( unsigned int i = 0 ; i < m_blockSize; i++ ) { + m_inputFrame[i] = (double)inputBuffers[0][i]; + } + +// int key = (m_getKeyMode->process(m_inputFrame) % 24); + int key = m_getKeyMode->process(m_inputFrame); + bool minor = m_getKeyMode->isModeMinor(key); + int tonic = key; + if (tonic > 12) tonic -= 12; + + int prevTonic = m_prevKey; + if (prevTonic > 12) prevTonic -= 12; + + if (m_first || (tonic != prevTonic)) { + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = now; +// feature.timestamp = now; + feature.values.push_back((float)tonic); + feature.label = getKeyName(tonic, minor, false); + returnFeatures[0].push_back(feature); // tonic + } + + if (m_first || (minor != (m_getKeyMode->isModeMinor(m_prevKey)))) { + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = now; + feature.values.push_back(minor ? 1.f : 0.f); + feature.label = (minor ? "Minor" : "Major"); + returnFeatures[1].push_back(feature); // mode + } + + if (m_first || (key != m_prevKey)) { + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = now; + feature.values.push_back((float)key); + feature.label = getKeyName(tonic, minor, true); + returnFeatures[2].push_back(feature); // key + } + + m_prevKey = key; + m_first = false; + + Feature ksf; + ksf.values.reserve(25); + double *keystrengths = m_getKeyMode->getKeyStrengths(); + for (int i = 0; i < 24; ++i) { + if (i == 12) ksf.values.push_back(-1); + ksf.values.push_back(keystrengths[conversion[i]-1]); + } + ksf.hasTimestamp = false; + returnFeatures[3].push_back(ksf); + + return returnFeatures; +} + +KeyDetector::FeatureSet +KeyDetector::getRemainingFeatures() +{ + return FeatureSet(); +} + + +size_t +KeyDetector::getPreferredStepSize() const +{ + if (!m_stepSize) { + GetKeyMode gkm(int(m_inputSampleRate + 0.1), + m_tuningFrequency, m_length, m_length); + m_stepSize = gkm.getHopSize(); + m_blockSize = gkm.getBlockSize(); + } + return m_stepSize; +} + +size_t +KeyDetector::getPreferredBlockSize() const +{ + if (!m_blockSize) { + GetKeyMode gkm(int(m_inputSampleRate + 0.1), + m_tuningFrequency, m_length, m_length); + m_stepSize = gkm.getHopSize(); + m_blockSize = gkm.getBlockSize(); + } + return m_blockSize; +} + +std::string +KeyDetector::getKeyName(int index, bool minor, bool includeMajMin) const +{ + // Keys are numbered with 1 => C, 12 => B + // This is based on chromagram base set to a C in qm-dsp's GetKeyMode.cpp + + static const char *namesMajor[] = { + "C", "Db", "D", "Eb", + "E", "F", "F# / Gb", "G", + "Ab", "A", "Bb", "B" + }; + + static const char *namesMinor[] = { + "C", "C#", "D", "Eb / D#", + "E", "F", "F#", "G", + "G#", "A", "Bb", "B" + }; + + if (index < 1 || index > 12) { + return "(unknown)"; + } + + std::string base; + + if (minor) base = namesMinor[index - 1]; + else base = namesMajor[index - 1]; + + if (!includeMajMin) return base; + + if (minor) return base + " minor"; + else return base + " major"; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/KeyDetect.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,69 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _GETMODE_PLUGIN_H_ +#define _GETMODE_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> + +#include <dsp/keydetection/GetKeyMode.h> + +class KeyDetector : public Vamp::Plugin +{ +public: + KeyDetector(float inputSampleRate); + virtual ~KeyDetector(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const { return TimeDomain; } + + 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); + + OutputList getOutputDescriptors() const; + + FeatureSet process(const float *const *inputBuffers, + Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + +protected: + mutable size_t m_stepSize; + mutable size_t m_blockSize; + float m_tuningFrequency; + int m_length; + + std::string getKeyName(int index, bool minor, bool includeMajMin) const; + + GetKeyMode* m_getKeyMode; + double* m_inputFrame; + int m_prevKey; + bool m_first; +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/MFCCPlugin.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,311 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "MFCCPlugin.h" + +#include <dsp/mfcc/MFCC.h> +#include <maths/MathUtilities.h> + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + +MFCCPlugin::MFCCPlugin(float inputSampleRate) : + Vamp::Plugin(inputSampleRate), + m_config(lrintf(inputSampleRate)), + m_mfcc(0), + m_step(1024), + m_block(2048), + m_count(0) +{ + m_bins = 20; + m_wantC0 = true; + m_logpower = 1; + + setupConfig(); +} + +void +MFCCPlugin::setupConfig() +{ + m_config.FS = lrintf(m_inputSampleRate); + m_config.fftsize = m_block; + m_config.nceps = (m_wantC0 ? m_bins-1 : m_bins); + m_config.want_c0 = m_wantC0; + m_config.logpower = m_logpower; +} + +MFCCPlugin::~MFCCPlugin() +{ + delete m_mfcc; +} + +string +MFCCPlugin::getIdentifier() const +{ + return "qm-mfcc"; +} + +string +MFCCPlugin::getName() const +{ + return "Mel-Frequency Cepstral Coefficients"; +} + +string +MFCCPlugin::getDescription() const +{ + return "Calculate a series of MFCC vectors from the audio"; +} + +string +MFCCPlugin::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int +MFCCPlugin::getPluginVersion() const +{ + return 1; +} + +string +MFCCPlugin::getCopyright() const +{ + return "Plugin by Nicolas Chetry and Chris Cannam. Copyright (c) 2009 QMUL - All Rights Reserved"; +} + +MFCCPlugin::ParameterList +MFCCPlugin::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + desc.identifier = "nceps"; + desc.name = "Number of Coefficients"; + desc.unit = ""; + desc.description = "Number of MFCCs to return, starting from C0 if \"Include C0\" is specified or from C1 otherwise"; + desc.minValue = 1; + desc.maxValue = 40; + desc.defaultValue = 20; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "logpower"; + desc.name = "Power for Mel Amplitude Logs"; + desc.unit = ""; + desc.description = "Power to raise the amplitude log values to before applying DCT. Values greater than 1 may reduce contribution of noise"; + desc.minValue = 0; + desc.maxValue = 5; + desc.defaultValue = 1; + desc.isQuantized = false; + desc.quantizeStep = 0; + list.push_back(desc); + + desc.identifier = "wantc0"; + desc.name = "Include C0"; + desc.unit = ""; + desc.description = "Whether to include the C0 (energy level) coefficient in the returned results"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = 1; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + return list; +} + +float +MFCCPlugin::getParameter(std::string param) const +{ + if (param == "nceps") { + return m_bins; + } + if (param == "logpower") { + return m_logpower; + } + if (param == "wantc0") { + return m_wantC0 ? 1 : 0; + } + std::cerr << "WARNING: MFCCPlugin::getParameter: unknown parameter \"" + << param << "\"" << std::endl; + return 0.0; +} + +void +MFCCPlugin::setParameter(std::string param, float value) +{ + if (param == "nceps") { + m_bins = lrintf(value); + } else if (param == "logpower") { + m_logpower = lrintf(value); + } else if (param == "wantc0") { + m_wantC0 = (value > 0.5); + } else { + std::cerr << "WARNING: MFCCPlugin::setParameter: unknown parameter \"" + << param << "\"" << std::endl; + } + + setupConfig(); +} + +bool +MFCCPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (m_mfcc) { + delete m_mfcc; + m_mfcc = 0; + } + + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) return false; + +// std::cerr << "MFCCPlugin::initialise: step " << stepSize << ", block " +// << blockSize << std::endl; + + m_step = stepSize; + m_block = blockSize; + setupConfig(); + + m_mfcc = new MFCC(m_config); + + m_binsums = vector<double>(m_bins); + for (int i = 0; i < m_bins; ++i) { + m_binsums[i] = 0.0; + } + + return true; +} + +void +MFCCPlugin::reset() +{ + if (m_mfcc) { + delete m_mfcc; + m_mfcc = new MFCC(m_config); + for (int i = 0; i < m_bins; ++i) { + m_binsums[i] = 0.0; + } + } + m_count = 0; +} + +size_t +MFCCPlugin::getPreferredStepSize() const +{ + return 1024; +} + +size_t +MFCCPlugin::getPreferredBlockSize() const +{ + return 2048; +} + +MFCCPlugin::OutputList +MFCCPlugin::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor d; + d.identifier = "coefficients"; + d.name = "Coefficients"; + d.unit = ""; + d.description = "MFCC values"; + d.hasFixedBinCount = true; + d.binCount = m_bins; + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::OneSamplePerStep; + list.push_back(d); + + d.identifier = "means"; + d.name = "Means of Coefficients"; + d.description = "Mean values of MFCCs across duration of audio input"; + d.sampleType = OutputDescriptor::FixedSampleRate; + d.sampleRate = 1; + list.push_back(d); + + return list; +} + +MFCCPlugin::FeatureSet +MFCCPlugin::process(const float *const *inputBuffers, + Vamp::RealTime /* timestamp */) +{ + if (!m_mfcc) { + cerr << "ERROR: MFCCPlugin::process: " + << "MFCC has not been initialised" + << endl; + return FeatureSet(); + } + + double *real = new double[m_block]; + double *imag = new double[m_block]; + + for (size_t i = 0; i <= m_block/2; ++i) { + real[i] = inputBuffers[0][i*2]; + if (i > 0) real[m_block - i] = real[i]; + imag[i] = inputBuffers[0][i*2+1]; + if (i > 0) imag[m_block - i] = imag[i]; + } + + double *output = new double[m_bins]; + + m_mfcc->process(real, imag, output); + + delete[] real; + delete[] imag; + + Feature feature; + feature.hasTimestamp = false; + for (size_t i = 0; i < m_bins; ++i) { + double value = output[i]; + if (ISNAN(value)) value = 0.0; + m_binsums[i] += value; + feature.values.push_back(value); + } + feature.label = ""; + ++m_count; + + delete[] output; + + FeatureSet returnFeatures; + returnFeatures[0].push_back(feature); + return returnFeatures; +} + +MFCCPlugin::FeatureSet +MFCCPlugin::getRemainingFeatures() +{ + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = Vamp::RealTime::zeroTime; + + for (size_t i = 0; i < m_bins; ++i) { + double v = m_binsums[i]; + if (m_count > 0) v /= m_count; + feature.values.push_back(v); + } + feature.label = "Coefficient means"; + + FeatureSet returnFeatures; + returnFeatures[1].push_back(feature); + return returnFeatures; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/MFCCPlugin.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,74 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _MFCC_PLUGIN_H_ +#define _MFCC_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> +#include <dsp/mfcc/MFCC.h> + +#include <vector> + +class MFCCPlugin : public Vamp::Plugin +{ +public: + MFCCPlugin(float inputSampleRate); + virtual ~MFCCPlugin(); + + 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: + int m_bins; // == nceps is m_wantC0 false or nceps+1 if m_wantC0 true + bool m_wantC0; + float m_logpower; + + void setupConfig(); + + MFCCConfig m_config; + MFCC *m_mfcc; + mutable size_t m_step; + mutable size_t m_block; + + std::vector<double> m_binsums; + size_t m_count; + + Feature normalize(const Feature &); +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/OnsetDetect.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,494 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "OnsetDetect.h" + +#include <dsp/onsets/DetectionFunction.h> +#include <dsp/onsets/PeakPicking.h> +#include <dsp/tempotracking/TempoTrack.h> + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + +float OnsetDetector::m_preferredStepSecs = 0.01161; + +class OnsetDetectorData +{ +public: + OnsetDetectorData(const DFConfig &config) : dfConfig(config) { + df = new DetectionFunction(config); + } + ~OnsetDetectorData() { + delete df; + } + void reset() { + delete df; + df = new DetectionFunction(dfConfig); + dfOutput.clear(); + origin = Vamp::RealTime::zeroTime; + } + + DFConfig dfConfig; + DetectionFunction *df; + vector<double> dfOutput; + Vamp::RealTime origin; +}; + + +OnsetDetector::OnsetDetector(float inputSampleRate) : + Vamp::Plugin(inputSampleRate), + m_d(0), + m_dfType(DF_COMPLEXSD), + m_sensitivity(50), + m_whiten(false) +{ +} + +OnsetDetector::~OnsetDetector() +{ + delete m_d; +} + +string +OnsetDetector::getIdentifier() const +{ + return "qm-onsetdetector"; +} + +string +OnsetDetector::getName() const +{ + return "Note Onset Detector"; +} + +string +OnsetDetector::getDescription() const +{ + return "Estimate individual note onset positions"; +} + +string +OnsetDetector::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int +OnsetDetector::getPluginVersion() const +{ + return 3; +} + +string +OnsetDetector::getCopyright() const +{ + return "Plugin by Christian Landone, Chris Duxbury and Juan Pablo Bello. Copyright (c) 2006-2009 QMUL - All Rights Reserved"; +} + +OnsetDetector::ParameterList +OnsetDetector::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + desc.identifier = "dftype"; + desc.name = "Onset Detection Function Type"; + desc.description = "Method used to calculate the onset detection function"; + desc.minValue = 0; + desc.maxValue = 4; + desc.defaultValue = 3; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.valueNames.push_back("High-Frequency Content"); + desc.valueNames.push_back("Spectral Difference"); + desc.valueNames.push_back("Phase Deviation"); + desc.valueNames.push_back("Complex Domain"); + desc.valueNames.push_back("Broadband Energy Rise"); + list.push_back(desc); + + desc.identifier = "sensitivity"; + desc.name = "Onset Detector Sensitivity"; + desc.description = "Sensitivity of peak-picker for onset detection"; + desc.minValue = 0; + desc.maxValue = 100; + desc.defaultValue = 50; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.unit = "%"; + desc.valueNames.clear(); + list.push_back(desc); + + desc.identifier = "whiten"; + desc.name = "Adaptive Whitening"; + desc.description = "Normalize frequency bin magnitudes relative to recent peak levels"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = 0; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.unit = ""; + list.push_back(desc); + + return list; +} + +float +OnsetDetector::getParameter(std::string name) const +{ + if (name == "dftype") { + switch (m_dfType) { + case DF_HFC: return 0; + case DF_SPECDIFF: return 1; + case DF_PHASEDEV: return 2; + default: case DF_COMPLEXSD: return 3; + case DF_BROADBAND: return 4; + } + } else if (name == "sensitivity") { + return m_sensitivity; + } else if (name == "whiten") { + return m_whiten ? 1.0 : 0.0; + } + return 0.0; +} + +void +OnsetDetector::setParameter(std::string name, float value) +{ + if (name == "dftype") { + int dfType = m_dfType; + switch (lrintf(value)) { + case 0: dfType = DF_HFC; break; + case 1: dfType = DF_SPECDIFF; break; + case 2: dfType = DF_PHASEDEV; break; + default: case 3: dfType = DF_COMPLEXSD; break; + case 4: dfType = DF_BROADBAND; break; + } + if (dfType == m_dfType) return; + m_dfType = dfType; + m_program = ""; + } else if (name == "sensitivity") { + if (m_sensitivity == value) return; + m_sensitivity = value; + m_program = ""; + } else if (name == "whiten") { + if (m_whiten == (value > 0.5)) return; + m_whiten = (value > 0.5); + m_program = ""; + } +} + +OnsetDetector::ProgramList +OnsetDetector::getPrograms() const +{ + ProgramList programs; + programs.push_back(""); + programs.push_back("General purpose"); + programs.push_back("Soft onsets"); + programs.push_back("Percussive onsets"); + return programs; +} + +std::string +OnsetDetector::getCurrentProgram() const +{ + if (m_program == "") return ""; + else return m_program; +} + +void +OnsetDetector::selectProgram(std::string program) +{ + if (program == "General purpose") { + setParameter("dftype", 3); // complex + setParameter("sensitivity", 50); + setParameter("whiten", 0); + } else if (program == "Soft onsets") { + setParameter("dftype", 3); // complex + setParameter("sensitivity", 40); + setParameter("whiten", 1); + } else if (program == "Percussive onsets") { + setParameter("dftype", 4); // broadband energy rise + setParameter("sensitivity", 40); + setParameter("whiten", 0); + } else { + return; + } + m_program = program; +} + +bool +OnsetDetector::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (m_d) { + delete m_d; + m_d = 0; + } + + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) { + std::cerr << "OnsetDetector::initialise: Unsupported channel count: " + << channels << std::endl; + return false; + } + + if (stepSize != getPreferredStepSize()) { + std::cerr << "WARNING: OnsetDetector::initialise: Possibly sub-optimal step size for this sample rate: " + << stepSize << " (wanted " << (getPreferredStepSize()) << ")" << std::endl; + } + + if (blockSize != getPreferredBlockSize()) { + std::cerr << "WARNING: OnsetDetector::initialise: Possibly sub-optimal block size for this sample rate: " + << blockSize << " (wanted " << (getPreferredBlockSize()) << ")" << std::endl; + } + + DFConfig dfConfig; + dfConfig.DFType = m_dfType; + dfConfig.stepSize = stepSize; + dfConfig.frameLength = blockSize; + dfConfig.dbRise = 6.0 - m_sensitivity / 16.6667; + dfConfig.adaptiveWhitening = m_whiten; + dfConfig.whiteningRelaxCoeff = -1; + dfConfig.whiteningFloor = -1; + + m_d = new OnsetDetectorData(dfConfig); + return true; +} + +void +OnsetDetector::reset() +{ + if (m_d) m_d->reset(); +} + +size_t +OnsetDetector::getPreferredStepSize() const +{ + size_t step = size_t(m_inputSampleRate * m_preferredStepSecs + 0.0001); + if (step < 1) step = 1; +// std::cerr << "OnsetDetector::getPreferredStepSize: input sample rate is " << m_inputSampleRate << ", step size is " << step << std::endl; + return step; +} + +size_t +OnsetDetector::getPreferredBlockSize() const +{ + return getPreferredStepSize() * 2; +} + +OnsetDetector::OutputList +OnsetDetector::getOutputDescriptors() const +{ + OutputList list; + + float stepSecs = m_preferredStepSecs; +// if (m_d) stepSecs = m_d->dfConfig.stepSecs; + + OutputDescriptor onsets; + onsets.identifier = "onsets"; + onsets.name = "Note Onsets"; + onsets.description = "Perceived note onset positions"; + onsets.unit = ""; + onsets.hasFixedBinCount = true; + onsets.binCount = 0; + onsets.sampleType = OutputDescriptor::VariableSampleRate; + onsets.sampleRate = 1.0 / stepSecs; + + OutputDescriptor df; + df.identifier = "detection_fn"; + df.name = "Onset Detection Function"; + df.description = "Probability function of note onset likelihood"; + df.unit = ""; + df.hasFixedBinCount = true; + df.binCount = 1; + df.hasKnownExtents = false; + df.isQuantized = false; + df.sampleType = OutputDescriptor::OneSamplePerStep; + + OutputDescriptor sdf; + sdf.identifier = "smoothed_df"; + sdf.name = "Smoothed Detection Function"; + sdf.description = "Smoothed probability function used for peak-picking"; + sdf.unit = ""; + sdf.hasFixedBinCount = true; + sdf.binCount = 1; + sdf.hasKnownExtents = false; + sdf.isQuantized = false; + + sdf.sampleType = OutputDescriptor::VariableSampleRate; + +//!!! SV doesn't seem to handle these correctly in getRemainingFeatures +// sdf.sampleType = OutputDescriptor::FixedSampleRate; + sdf.sampleRate = 1.0 / stepSecs; + + list.push_back(onsets); + list.push_back(df); + list.push_back(sdf); + + return list; +} + +OnsetDetector::FeatureSet +OnsetDetector::process(const float *const *inputBuffers, + Vamp::RealTime timestamp) +{ + if (!m_d) { + cerr << "ERROR: OnsetDetector::process: " + << "OnsetDetector has not been initialised" + << endl; + return FeatureSet(); + } + + size_t len = m_d->dfConfig.frameLength / 2; + +// float mean = 0.f; +// for (size_t i = 0; i < len; ++i) { +//// std::cerr << inputBuffers[0][i] << " "; +// mean += inputBuffers[0][i]; +// } +//// std::cerr << std::endl; +// mean /= len; + +// std::cerr << "OnsetDetector::process(" << timestamp << "): " +// << "dftype " << m_dfType << ", sens " << m_sensitivity +// << ", len " << len << ", mean " << mean << std::endl; + + double *magnitudes = new double[len]; + double *phases = new double[len]; + + // We only support a single input channel + + for (size_t i = 0; i < len; ++i) { + + magnitudes[i] = sqrt(inputBuffers[0][i*2 ] * inputBuffers[0][i*2 ] + + inputBuffers[0][i*2+1] * inputBuffers[0][i*2+1]); + + phases[i] = atan2(-inputBuffers[0][i*2+1], inputBuffers[0][i*2]); + } + + double output = m_d->df->process(magnitudes, phases); + + delete[] magnitudes; + delete[] phases; + + if (m_d->dfOutput.empty()) m_d->origin = timestamp; + + m_d->dfOutput.push_back(output); + + FeatureSet returnFeatures; + + Feature feature; + feature.hasTimestamp = false; + feature.values.push_back(output); + +// std::cerr << "df: " << output << std::endl; + + returnFeatures[1].push_back(feature); // detection function is output 1 + return returnFeatures; +} + +OnsetDetector::FeatureSet +OnsetDetector::getRemainingFeatures() +{ + if (!m_d) { + cerr << "ERROR: OnsetDetector::getRemainingFeatures: " + << "OnsetDetector has not been initialised" + << endl; + return FeatureSet(); + } + + if (m_dfType == DF_BROADBAND) { + for (size_t i = 0; i < m_d->dfOutput.size(); ++i) { + if (m_d->dfOutput[i] < ((110 - m_sensitivity) * + m_d->dfConfig.frameLength) / 200) { + m_d->dfOutput[i] = 0; + } + } + } + + double aCoeffs[] = { 1.0000, -0.5949, 0.2348 }; + double bCoeffs[] = { 0.1600, 0.3200, 0.1600 }; + + FeatureSet returnFeatures; + + PPickParams ppParams; + ppParams.length = m_d->dfOutput.size(); + // tau and cutoff appear to be unused in PeakPicking, but I've + // inserted some moderately plausible values rather than leave + // them unset. The QuadThresh values come from trial and error. + // The rest of these are copied from ttParams in the BeatTracker + // code: I don't claim to know whether they're good or not --cc + ppParams.tau = m_d->dfConfig.stepSize / m_inputSampleRate; + ppParams.alpha = 9; + ppParams.cutoff = m_inputSampleRate/4; + ppParams.LPOrd = 2; + ppParams.LPACoeffs = aCoeffs; + ppParams.LPBCoeffs = bCoeffs; + ppParams.WinT.post = 8; + ppParams.WinT.pre = 7; + ppParams.QuadThresh.a = (100 - m_sensitivity) / 1000.0; + ppParams.QuadThresh.b = 0; + ppParams.QuadThresh.c = (100 - m_sensitivity) / 1500.0; + + PeakPicking peakPicker(ppParams); + + double *ppSrc = new double[ppParams.length]; + for (unsigned int i = 0; i < ppParams.length; ++i) { + ppSrc[i] = m_d->dfOutput[i]; + } + + vector<int> onsets; + peakPicker.process(ppSrc, ppParams.length, onsets); + + for (size_t i = 0; i < onsets.size(); ++i) { + + size_t index = onsets[i]; + + if (m_dfType != DF_BROADBAND) { + double prevDiff = 0.0; + while (index > 1) { + double diff = ppSrc[index] - ppSrc[index-1]; + if (diff < prevDiff * 0.9) break; + prevDiff = diff; + --index; + } + } + + size_t frame = index * m_d->dfConfig.stepSize; + + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime + (frame, lrintf(m_inputSampleRate)); + + returnFeatures[0].push_back(feature); // onsets are output 0 + } + + for (unsigned int i = 0; i < ppParams.length; ++i) { + + Feature feature; +// feature.hasTimestamp = false; + feature.hasTimestamp = true; + size_t frame = i * m_d->dfConfig.stepSize; + feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime + (frame, lrintf(m_inputSampleRate)); + + feature.values.push_back(ppSrc[i]); + returnFeatures[2].push_back(feature); // smoothed df is output 2 + } + + return returnFeatures; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/OnsetDetect.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,68 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _ONSET_DETECT_PLUGIN_H_ +#define _ONSET_DETECT_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> + +class OnsetDetectorData; + +class OnsetDetector : public Vamp::Plugin +{ +public: + OnsetDetector(float inputSampleRate); + virtual ~OnsetDetector(); + + 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); + + ProgramList getPrograms() const; + std::string getCurrentProgram() const; + void selectProgram(std::string program); + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + + OutputList getOutputDescriptors() const; + + FeatureSet process(const float *const *inputBuffers, + Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + OnsetDetectorData *m_d; + int m_dfType; + float m_sensitivity; + bool m_whiten; + std::string m_program; + static float m_preferredStepSecs; +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/SegmenterPlugin.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,323 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + * SegmenterPlugin.cpp + * + * Created by Mark Levy on 24/03/2006. + * Copyright 2006 Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. + */ + +#include <iostream> +#include <sstream> + +#include "SegmenterPlugin.h" +#include "dsp/segmentation/ClusterMeltSegmenter.h" + +using std::string; +using std::vector; +using std::cerr; +using std::endl; +using std::ostringstream; + +SegmenterPlugin::SegmenterPlugin(float inputSampleRate) : + Plugin(inputSampleRate), + segmenter(0), + nSegmentTypes(10), + neighbourhoodLimit(4), + featureType(feature_types(1)) +{ + +} + +SegmenterPlugin::~SegmenterPlugin() +{ + delete segmenter; +} + +std::string SegmenterPlugin::getIdentifier() const +{ + return "qm-segmenter"; +} + +std::string SegmenterPlugin::getName() const +{ + return "Segmenter"; +} + +std::string SegmenterPlugin::getDescription() const +{ + return "Divide the track into a sequence of consistent segments"; +} + +string +SegmenterPlugin::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int +SegmenterPlugin::getPluginVersion() const +{ + return 2; +} + +string +SegmenterPlugin::getCopyright() const +{ + return "Plugin by Mark Levy. Copyright (c) 2006-2009 QMUL - All Rights Reserved"; +} + +bool +SegmenterPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) return false; + + if (!segmenter) makeSegmenter(); + + if (stepSize != hopsize) { + std::cerr << "SegmenterPlugin::initialise: supplied step size " + << stepSize << " differs from required step size " << hopsize + << std::endl; + return false; + } + + if (blockSize != windowsize) { + std::cerr << "SegmenterPlugin::initialise: supplied block size " + << blockSize << " differs from required block size " << windowsize + << std::endl; + return false; + } + + return true; +} + +void +SegmenterPlugin::reset() +{ + // re-make segmenter only if it has already been made; otherwise + // there's nothing to reset + if (segmenter) makeSegmenter(); +} + +size_t +SegmenterPlugin::getPreferredStepSize() const +{ + if (!segmenter) makeSegmenter(); + return hopsize; +} + +size_t +SegmenterPlugin::getPreferredBlockSize() const +{ + if (!segmenter) makeSegmenter(); + return windowsize; +} + +SegmenterPlugin::ParameterList SegmenterPlugin::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + desc.identifier = "nSegmentTypes"; + desc.name = "Number of segment-types"; + desc.description = "Maximum number of different kinds of segment to find"; + desc.unit = ""; + desc.minValue = 2; + desc.maxValue = 12; + desc.defaultValue = 10; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + ParameterDescriptor desc2; + desc2.identifier = "featureType"; + desc2.name = "Feature Type"; + desc2.description = "Try Chromatic for acoustic or pre-1980 recordings, otherwise use Hybrid"; + desc2.unit = ""; + desc2.minValue = 1; + desc2.maxValue = 3; + desc2.defaultValue = 1; + desc2.isQuantized = true; + desc2.quantizeStep = 1; + desc2.valueNames.push_back("Hybrid (Constant-Q)"); + desc2.valueNames.push_back("Chromatic (Chroma)"); + desc2.valueNames.push_back("Timbral (MFCC)"); + list.push_back(desc2); + + ParameterDescriptor desc3; + desc3.identifier = "neighbourhoodLimit"; + desc3.name = "Minimum segment duration"; + desc3.description = "Approximate expected minimum duration for each segment"; + desc3.unit = "s"; + desc3.minValue = 1; + desc3.maxValue = 15; + desc3.defaultValue = 4; + desc3.isQuantized = true; + desc3.quantizeStep = 0.2; + list.push_back(desc3); + + return list; +} + +float +SegmenterPlugin::getParameter(std::string param) const +{ + if (param == "nSegmentTypes") { + return nSegmentTypes; + } + + if (param == "featureType") { + return featureType; + } + + if (param == "neighbourhoodLimit") { + return neighbourhoodLimit; + } + + std::cerr << "WARNING: SegmenterPlugin::getParameter: unknown parameter \"" + << param << "\"" << std::endl; + return 0.0; +} + +void +SegmenterPlugin::setParameter(std::string param, float value) +{ + if (param == "nSegmentTypes") { + + nSegmentTypes = int(value + 0.0001); + return; + } + + if (param == "featureType") { + if (featureType != feature_types(value)) // feature type changed, create a new segmenter + { + featureType = feature_types(value); + makeSegmenter(); + } + return; + } + + if (param == "neighbourhoodLimit") { + if (neighbourhoodLimit != value) { + neighbourhoodLimit = value; + makeSegmenter(); + } + return; + } + + std::cerr << "WARNING: SegmenterPlugin::setParameter: unknown parameter \"" + << param << "\"" << std::endl; +} + +void +SegmenterPlugin::makeSegmenter() const +{ + ClusterMeltSegmenterParams params = ClusterMeltSegmenterParams(); + params.featureType = (feature_types) featureType; + + if (params.featureType == FEATURE_TYPE_CONSTQ) + { + params.ncomponents = 20; + } + if (params.featureType == FEATURE_TYPE_CHROMA) + { + params.hopSize = 0.1; + params.windowSize = 0.372; + params.nbins = 12; + params.histogramLength = 20; + } + if (params.featureType == FEATURE_TYPE_MFCC) + { + params.ncomponents = 20; + } + delete segmenter; + + params.neighbourhoodLimit = + int(neighbourhoodLimit / params.hopSize + 0.0001); + + segmenter = new ClusterMeltSegmenter(params); + segmenter->initialise(m_inputSampleRate); + hopsize = segmenter->getHopsize(); + windowsize = segmenter->getWindowsize(); + +// std::cerr << "segmenter window size: " << segmenter->getWindowsize() +// << std::endl; +} + +SegmenterPlugin::OutputList +SegmenterPlugin::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor segmentation; + segmentation.identifier = "segmentation"; + segmentation.name = "Segmentation"; + segmentation.description = "Segmentation"; + segmentation.unit = "segment-type"; + segmentation.hasFixedBinCount = true; + segmentation.binCount = 1; + segmentation.hasKnownExtents = true; + segmentation.minValue = 1; + segmentation.maxValue = nSegmentTypes; + segmentation.isQuantized = true; + segmentation.quantizeStep = 1; + segmentation.sampleType = OutputDescriptor::VariableSampleRate; + segmentation.sampleRate = m_inputSampleRate / getPreferredStepSize(); + + list.push_back(segmentation); + + return list; +} + +SegmenterPlugin::FeatureSet +SegmenterPlugin::process(const float *const *inputBuffers, Vamp::RealTime /* timestamp */) +{ + // convert float* to double* + double *tempBuffer = new double[windowsize]; + for (size_t i = 0; i < windowsize; ++i) { + tempBuffer[i] = inputBuffers[0][i]; + } + + segmenter->extractFeatures(tempBuffer, segmenter->getWindowsize()); + + delete [] tempBuffer; + + return FeatureSet(); +} + +SegmenterPlugin::FeatureSet +SegmenterPlugin::getRemainingFeatures() +{ + segmenter->segment(nSegmentTypes); + Segmentation segm = segmenter->getSegmentation(); + + FeatureSet returnFeatures; + + for (int i = 0; i < segm.segments.size(); ++i) { + + Segment s = segm.segments[i]; + + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = Vamp::RealTime::frame2RealTime(s.start, static_cast<unsigned int>(m_inputSampleRate)); + + vector<float> floatval; + floatval.push_back(s.type); + feature.values = floatval; + + ostringstream oss; + oss << s.type; + feature.label = oss.str(); + + returnFeatures[0].push_back(feature); + } + + return returnFeatures; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/SegmenterPlugin.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,68 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + * SegmenterPlugin.h + * + * Created by Mark Levy on 24/03/2006. + * Copyright 2006 Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. + */ + +#ifndef _SEGMENTER_PLUGIN_H_ +#define _SEGMENTER_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> +#include <vamp-sdk/RealTime.h> +#include "dsp/segmentation/Segmenter.h" +#include "dsp/segmentation/segment.h" + +class Decimator; + +class SegmenterPlugin : public Vamp::Plugin +{ +public: + SegmenterPlugin(float inputSampleRate); + virtual ~SegmenterPlugin(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + std::string getIdentifier() const; + std::string getName() const; + std::string getDescription() const; + std::string getMaker() const; + int getPluginVersion() const; + std::string getCopyright() const; + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + InputDomain getInputDomain() const { return TimeDomain; } + + SegmenterPlugin::ParameterList getParameterDescriptors() const; + float getParameter(std::string param) const; + void setParameter(std::string param, float value); + + OutputList getOutputDescriptors() const; + + FeatureSet process(const float *const *inputBuffers, Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + mutable Segmenter* segmenter; + mutable int hopsize; + mutable int windowsize; + mutable float neighbourhoodLimit; // in sec + int nSegmentTypes; + feature_types featureType; // 1 = constant-Q, 2 = chroma + + void makeSegmenter() const; +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/SimilarityPlugin.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,939 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + * SimilarityPlugin.cpp + * + * Copyright 2009 Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. + */ + +#include <iostream> +#include <cstdio> + +#include "SimilarityPlugin.h" +#include "base/Pitch.h" +#include "dsp/mfcc/MFCC.h" +#include "dsp/chromagram/Chromagram.h" +#include "dsp/rateconversion/Decimator.h" +#include "dsp/rhythm/BeatSpectrum.h" +#include "maths/KLDivergence.h" +#include "maths/CosineDistance.h" +#include "maths/MathUtilities.h" + +using std::string; +using std::vector; +using std::cerr; +using std::endl; +using std::ostringstream; + +const float +SimilarityPlugin::m_noRhythm = 0.009; + +const float +SimilarityPlugin::m_allRhythm = 0.991; + +SimilarityPlugin::SimilarityPlugin(float inputSampleRate) : + Plugin(inputSampleRate), + m_type(TypeMFCC), + m_mfcc(0), + m_rhythmfcc(0), + m_chromagram(0), + m_decimator(0), + m_featureColumnSize(20), + m_rhythmWeighting(0.5f), + m_rhythmClipDuration(4.f), // seconds + m_rhythmClipOrigin(40.f), // seconds + m_rhythmClipFrameSize(0), + m_rhythmClipFrames(0), + m_rhythmColumnSize(20), + m_blockSize(0), + m_channels(0), + m_processRate(0), + m_frameNo(0), + m_done(false) +{ + int rate = lrintf(m_inputSampleRate); + int internalRate = 22050; + int decimationFactor = rate / internalRate; + if (decimationFactor < 1) decimationFactor = 1; + + // must be a power of two + while (decimationFactor & (decimationFactor - 1)) ++decimationFactor; + + m_processRate = rate / decimationFactor; // may be 22050, 24000 etc +} + +SimilarityPlugin::~SimilarityPlugin() +{ + delete m_mfcc; + delete m_rhythmfcc; + delete m_chromagram; + delete m_decimator; +} + +string +SimilarityPlugin::getIdentifier() const +{ + return "qm-similarity"; +} + +string +SimilarityPlugin::getName() const +{ + return "Similarity"; +} + +string +SimilarityPlugin::getDescription() const +{ + return "Return a distance matrix for similarity between the input audio channels"; +} + +string +SimilarityPlugin::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int +SimilarityPlugin::getPluginVersion() const +{ + return 1; +} + +string +SimilarityPlugin::getCopyright() const +{ + return "Plugin by Mark Levy, Kurt Jacobson and Chris Cannam. Copyright (c) 2009 QMUL - All Rights Reserved"; +} + +size_t +SimilarityPlugin::getMinChannelCount() const +{ + return 1; +} + +size_t +SimilarityPlugin::getMaxChannelCount() const +{ + return 1024; +} + +int +SimilarityPlugin::getDecimationFactor() const +{ + int rate = lrintf(m_inputSampleRate); + return rate / m_processRate; +} + +size_t +SimilarityPlugin::getPreferredStepSize() const +{ + if (m_blockSize == 0) calculateBlockSize(); + + // there is also an assumption to this effect in process() + // (referring to m_fftSize/2 instead of a literal post-decimation + // step size): + return m_blockSize/2; +} + +size_t +SimilarityPlugin::getPreferredBlockSize() const +{ + if (m_blockSize == 0) calculateBlockSize(); + return m_blockSize; +} + +void +SimilarityPlugin::calculateBlockSize() const +{ + if (m_blockSize != 0) return; + int decimationFactor = getDecimationFactor(); + m_blockSize = 2048 * decimationFactor; +} + +SimilarityPlugin::ParameterList SimilarityPlugin::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + desc.identifier = "featureType"; + desc.name = "Feature Type"; + desc.description = "Audio feature used for similarity measure. Timbral: use the first 20 MFCCs (19 plus C0). Chromatic: use 12 bin-per-octave chroma. Rhythmic: compare beat spectra of short regions."; + desc.unit = ""; + desc.minValue = 0; + desc.maxValue = 4; + desc.defaultValue = 1; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.valueNames.push_back("Timbre"); + desc.valueNames.push_back("Timbre and Rhythm"); + desc.valueNames.push_back("Chroma"); + desc.valueNames.push_back("Chroma and Rhythm"); + desc.valueNames.push_back("Rhythm only"); + list.push_back(desc); +/* + desc.identifier = "rhythmWeighting"; + desc.name = "Influence of Rhythm"; + desc.description = "Proportion of similarity measure made up from rhythmic similarity component, from 0 (entirely timbral or chromatic) to 100 (entirely rhythmic)."; + desc.unit = "%"; + desc.minValue = 0; + desc.maxValue = 100; + desc.defaultValue = 0; + desc.isQuantized = false; + desc.valueNames.clear(); + list.push_back(desc); +*/ + return list; +} + +float +SimilarityPlugin::getParameter(std::string param) const +{ + if (param == "featureType") { + + if (m_rhythmWeighting > m_allRhythm) { + return 4; + } + + switch (m_type) { + + case TypeMFCC: + if (m_rhythmWeighting < m_noRhythm) return 0; + else return 1; + break; + + case TypeChroma: + if (m_rhythmWeighting < m_noRhythm) return 2; + else return 3; + break; + } + + return 1; + +// } else if (param == "rhythmWeighting") { +// return nearbyint(m_rhythmWeighting * 100.0); + } + + std::cerr << "WARNING: SimilarityPlugin::getParameter: unknown parameter \"" + << param << "\"" << std::endl; + return 0.0; +} + +void +SimilarityPlugin::setParameter(std::string param, float value) +{ + if (param == "featureType") { + + int v = int(value + 0.1); + + Type newType = m_type; + + switch (v) { + case 0: newType = TypeMFCC; m_rhythmWeighting = 0.0f; break; + case 1: newType = TypeMFCC; m_rhythmWeighting = 0.5f; break; + case 2: newType = TypeChroma; m_rhythmWeighting = 0.0f; break; + case 3: newType = TypeChroma; m_rhythmWeighting = 0.5f; break; + case 4: newType = TypeMFCC; m_rhythmWeighting = 1.f; break; + } + + if (newType != m_type) m_blockSize = 0; + + m_type = newType; + return; + +// } else if (param == "rhythmWeighting") { +// m_rhythmWeighting = value / 100; +// return; + } + + std::cerr << "WARNING: SimilarityPlugin::setParameter: unknown parameter \"" + << param << "\"" << std::endl; +} + +SimilarityPlugin::OutputList +SimilarityPlugin::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor similarity; + similarity.identifier = "distancematrix"; + similarity.name = "Distance Matrix"; + similarity.description = "Distance matrix for similarity metric. Smaller = more similar. Should be symmetrical."; + similarity.unit = ""; + similarity.hasFixedBinCount = true; + similarity.binCount = m_channels; + similarity.hasKnownExtents = false; + similarity.isQuantized = false; + similarity.sampleType = OutputDescriptor::FixedSampleRate; + similarity.sampleRate = 1; + + m_distanceMatrixOutput = list.size(); + list.push_back(similarity); + + OutputDescriptor simvec; + simvec.identifier = "distancevector"; + simvec.name = "Distance from First Channel"; + simvec.description = "Distance vector for similarity of each channel to the first channel. Smaller = more similar."; + simvec.unit = ""; + simvec.hasFixedBinCount = true; + simvec.binCount = m_channels; + simvec.hasKnownExtents = false; + simvec.isQuantized = false; + simvec.sampleType = OutputDescriptor::FixedSampleRate; + simvec.sampleRate = 1; + + m_distanceVectorOutput = list.size(); + list.push_back(simvec); + + OutputDescriptor sortvec; + sortvec.identifier = "sorteddistancevector"; + sortvec.name = "Ordered Distances from First Channel"; + sortvec.description = "Vector of the order of other channels in similarity to the first, followed by distance vector for similarity of each to the first. Smaller = more similar."; + sortvec.unit = ""; + sortvec.hasFixedBinCount = true; + sortvec.binCount = m_channels; + sortvec.hasKnownExtents = false; + sortvec.isQuantized = false; + sortvec.sampleType = OutputDescriptor::FixedSampleRate; + sortvec.sampleRate = 1; + + m_sortedVectorOutput = list.size(); + list.push_back(sortvec); + + OutputDescriptor means; + means.identifier = "means"; + means.name = "Feature Means"; + means.description = "Means of the feature bins. Feature time (sec) corresponds to input channel. Number of bins depends on selected feature type."; + means.unit = ""; + means.hasFixedBinCount = true; + means.binCount = m_featureColumnSize; + means.hasKnownExtents = false; + means.isQuantized = false; + means.sampleType = OutputDescriptor::FixedSampleRate; + means.sampleRate = 1; + + m_meansOutput = list.size(); + list.push_back(means); + + OutputDescriptor variances; + variances.identifier = "variances"; + variances.name = "Feature Variances"; + variances.description = "Variances of the feature bins. Feature time (sec) corresponds to input channel. Number of bins depends on selected feature type."; + variances.unit = ""; + variances.hasFixedBinCount = true; + variances.binCount = m_featureColumnSize; + variances.hasKnownExtents = false; + variances.isQuantized = false; + variances.sampleType = OutputDescriptor::FixedSampleRate; + variances.sampleRate = 1; + + m_variancesOutput = list.size(); + list.push_back(variances); + + OutputDescriptor beatspectrum; + beatspectrum.identifier = "beatspectrum"; + beatspectrum.name = "Beat Spectra"; + beatspectrum.description = "Rhythmic self-similarity vectors (beat spectra) for the input channels. Feature time (sec) corresponds to input channel. Not returned if rhythm weighting is zero."; + beatspectrum.unit = ""; + if (m_rhythmClipFrames > 0) { + beatspectrum.hasFixedBinCount = true; + beatspectrum.binCount = m_rhythmClipFrames / 2; + } else { + beatspectrum.hasFixedBinCount = false; + } + beatspectrum.hasKnownExtents = false; + beatspectrum.isQuantized = false; + beatspectrum.sampleType = OutputDescriptor::FixedSampleRate; + beatspectrum.sampleRate = 1; + + m_beatSpectraOutput = list.size(); + list.push_back(beatspectrum); + + return list; +} + +bool +SimilarityPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (channels < getMinChannelCount()) return false; + + // Using more than getMaxChannelCount is not actually a problem + // for us. Using "incorrect" step and block sizes would be fine + // for timbral or chroma similarity, but will break rhythmic + // similarity, so we'd better enforce these. + + if (stepSize != getPreferredStepSize()) { + std::cerr << "SimilarityPlugin::initialise: supplied step size " + << stepSize << " differs from required step size " + << getPreferredStepSize() << std::endl; + return false; + } + + if (blockSize != getPreferredBlockSize()) { + std::cerr << "SimilarityPlugin::initialise: supplied block size " + << blockSize << " differs from required block size " + << getPreferredBlockSize() << std::endl; + return false; + } + + m_blockSize = blockSize; + m_channels = channels; + + m_lastNonEmptyFrame = std::vector<int>(m_channels); + for (int i = 0; i < m_channels; ++i) m_lastNonEmptyFrame[i] = -1; + + m_emptyFrameCount = std::vector<int>(m_channels); + for (int i = 0; i < m_channels; ++i) m_emptyFrameCount[i] = 0; + + m_frameNo = 0; + + int decimationFactor = getDecimationFactor(); + if (decimationFactor > 1) { + m_decimator = new Decimator(m_blockSize, decimationFactor); + } + + if (m_type == TypeMFCC) { + + m_featureColumnSize = 20; + + MFCCConfig config(m_processRate); + config.fftsize = 2048; + config.nceps = m_featureColumnSize - 1; + config.want_c0 = true; + config.logpower = 1; + m_mfcc = new MFCC(config); + m_fftSize = m_mfcc->getfftlength(); + m_rhythmClipFrameSize = m_fftSize / 4; + +// std::cerr << "MFCC FS = " << config.FS << ", FFT size = " << m_fftSize<< std::endl; + + } else if (m_type == TypeChroma) { + + m_featureColumnSize = 12; + + // For simplicity, aim to have the chroma fft size equal to + // 2048, the same as the mfcc fft size (so the input block + // size does not depend on the feature type and we can use the + // same processing parameters for rhythm etc). This is also + // why getPreferredBlockSize can confidently return 2048 * the + // decimation factor. + + // The fft size for a chromagram is the filterbank Q value + // times the sample rate, divided by the minimum frequency, + // rounded up to the nearest power of two. + + double q = 1.0 / (pow(2.0, (1.0 / 12.0)) - 1.0); + double fmin = (q * m_processRate) / 2048.0; + + // Round fmin up to the nearest MIDI pitch multiple of 12. + // So long as fmin is greater than 12 to start with, this + // should not change the resulting fft size. + + int pmin = Pitch::getPitchForFrequency(float(fmin)); + pmin = ((pmin / 12) + 1) * 12; + fmin = Pitch::getFrequencyForPitch(pmin); + + float fmax = Pitch::getFrequencyForPitch(pmin + 36); + + ChromaConfig config; + config.FS = m_processRate; + config.min = fmin; + config.max = fmax; + config.BPO = 12; + config.CQThresh = 0.0054; + // We don't normalise the chromagram's columns individually; + // we normalise the mean at the end instead + config.normalise = MathUtilities::NormaliseNone; + m_chromagram = new Chromagram(config); + m_fftSize = m_chromagram->getFrameSize(); + + if (m_fftSize != 2048) { + std::cerr << "WARNING: SimilarityPlugin::initialise: Internal processing FFT size " << m_fftSize << " != expected size 2048 in chroma mode" << std::endl; + } + +// std::cerr << "fftsize = " << m_fftSize << std::endl; + + m_rhythmClipFrameSize = m_fftSize / 4; + +// std::cerr << "m_rhythmClipFrameSize = " << m_rhythmClipFrameSize << std::endl; +// std::cerr << "min = "<< config.min << ", max = " << config.max << std::endl; + + } else { + + std::cerr << "SimilarityPlugin::initialise: internal error: unknown type " << m_type << std::endl; + return false; + } + + if (needRhythm()) { + m_rhythmClipFrames = + int(ceil((m_rhythmClipDuration * m_processRate) + / m_rhythmClipFrameSize)); +// std::cerr << "SimilarityPlugin::initialise: rhythm clip requires " +// << m_rhythmClipFrames << " frames of size " +// << m_rhythmClipFrameSize << " at process rate " +// << m_processRate << " ( = " +// << (float(m_rhythmClipFrames * m_rhythmClipFrameSize) / m_processRate) << " sec )" +// << std::endl; + + MFCCConfig config(m_processRate); + config.fftsize = m_rhythmClipFrameSize; + config.nceps = m_rhythmColumnSize - 1; + config.want_c0 = true; + config.logpower = 1; + config.window = RectangularWindow; // because no overlap + m_rhythmfcc = new MFCC(config); + } + + for (int i = 0; i < m_channels; ++i) { + + m_values.push_back(FeatureMatrix()); + + if (needRhythm()) { + m_rhythmValues.push_back(FeatureColumnQueue()); + } + } + + m_done = false; + + return true; +} + +void +SimilarityPlugin::reset() +{ + for (int i = 0; i < m_values.size(); ++i) { + m_values[i].clear(); + } + + for (int i = 0; i < m_rhythmValues.size(); ++i) { + m_rhythmValues[i].clear(); + } + + for (int i = 0; i < m_lastNonEmptyFrame.size(); ++i) { + m_lastNonEmptyFrame[i] = -1; + } + + for (int i = 0; i < m_emptyFrameCount.size(); ++i) { + m_emptyFrameCount[i] = 0; + } + + m_done = false; +} + +SimilarityPlugin::FeatureSet +SimilarityPlugin::process(const float *const *inputBuffers, Vamp::RealTime /* timestamp */) +{ + if (m_done) { + return FeatureSet(); + } + + double *dblbuf = new double[m_blockSize]; + double *decbuf = dblbuf; + if (m_decimator) decbuf = new double[m_fftSize]; + + double *raw = new double[std::max(m_featureColumnSize, + m_rhythmColumnSize)]; + + float threshold = 1e-10; + + bool someRhythmFrameNeeded = false; + + for (size_t c = 0; c < m_channels; ++c) { + + bool empty = true; + + for (int i = 0; i < m_blockSize; ++i) { + float val = inputBuffers[c][i]; + if (fabs(val) > threshold) empty = false; + dblbuf[i] = val; + } + + if (empty) { + if (needRhythm() && ((m_frameNo % 2) == 0)) { + for (int i = 0; i < m_fftSize / m_rhythmClipFrameSize; ++i) { + if (m_rhythmValues[c].size() < m_rhythmClipFrames) { + FeatureColumn mf(m_rhythmColumnSize); + for (int i = 0; i < m_rhythmColumnSize; ++i) { + mf[i] = 0.0; + } + m_rhythmValues[c].push_back(mf); + } + } + } + m_emptyFrameCount[c]++; + continue; + } + + m_lastNonEmptyFrame[c] = m_frameNo; + + if (m_decimator) { + m_decimator->process(dblbuf, decbuf); + } + + if (needTimbre()) { + + FeatureColumn mf(m_featureColumnSize); + + if (m_type == TypeMFCC) { + m_mfcc->process(decbuf, raw); + for (int i = 0; i < m_featureColumnSize; ++i) { + mf[i] = raw[i]; + } + } else if (m_type == TypeChroma) { + double *chroma = m_chromagram->process(decbuf); + for (int i = 0; i < m_featureColumnSize; ++i) { + mf[i] = chroma[i]; + } + } + + m_values[c].push_back(mf); + } + +// std::cerr << "needRhythm = " << needRhythm() << ", frame = " << m_frameNo << std::endl; + + if (needRhythm() && ((m_frameNo % 2) == 0)) { + + // The incoming frames are overlapping; we only use every + // other one, because we don't want the overlap (it would + // screw up the rhythm) + + int frameOffset = 0; + + while (frameOffset + m_rhythmClipFrameSize <= m_fftSize) { + + bool needRhythmFrame = true; + + if (m_rhythmValues[c].size() >= m_rhythmClipFrames) { + + needRhythmFrame = false; + + // assumes hopsize = framesize/2 + float current = m_frameNo * (m_fftSize/2) + frameOffset; + current = current / m_processRate; + if (current - m_rhythmClipDuration < m_rhythmClipOrigin) { + needRhythmFrame = true; + m_rhythmValues[c].pop_front(); + } + +// if (needRhythmFrame) { +// std::cerr << "at current = " <<current << " (frame = " << m_frameNo << "), have " << m_rhythmValues[c].size() << ", need rhythm = " << needRhythmFrame << std::endl; +// } + + } + + if (needRhythmFrame) { + + someRhythmFrameNeeded = true; + + m_rhythmfcc->process(decbuf + frameOffset, raw); + + FeatureColumn mf(m_rhythmColumnSize); + for (int i = 0; i < m_rhythmColumnSize; ++i) { + mf[i] = raw[i]; + } + + m_rhythmValues[c].push_back(mf); + } + + frameOffset += m_rhythmClipFrameSize; + } + } + } + + if (!needTimbre() && !someRhythmFrameNeeded && ((m_frameNo % 2) == 0)) { +// std::cerr << "done!" << std::endl; + m_done = true; + } + + if (m_decimator) delete[] decbuf; + delete[] dblbuf; + delete[] raw; + + ++m_frameNo; + + return FeatureSet(); +} + +SimilarityPlugin::FeatureMatrix +SimilarityPlugin::calculateTimbral(FeatureSet &returnFeatures) +{ + FeatureMatrix m(m_channels); // means + FeatureMatrix v(m_channels); // variances + + for (int i = 0; i < m_channels; ++i) { + + FeatureColumn mean(m_featureColumnSize), variance(m_featureColumnSize); + + for (int j = 0; j < m_featureColumnSize; ++j) { + + mean[j] = 0.0; + variance[j] = 0.0; + int count; + + // We want to take values up to, but not including, the + // last non-empty frame (which may be partial) + + int sz = m_lastNonEmptyFrame[i] - m_emptyFrameCount[i]; + if (sz < 0) sz = 0; + if (sz >= m_values[i].size()) sz = m_values[i].size()-1; + + count = 0; + for (int k = 0; k < sz; ++k) { + double val = m_values[i][k][j]; + if (ISNAN(val) || ISINF(val)) continue; + mean[j] += val; + ++count; + } + if (count > 0) mean[j] /= count; + + count = 0; + for (int k = 0; k < sz; ++k) { + double val = ((m_values[i][k][j] - mean[j]) * + (m_values[i][k][j] - mean[j])); + if (ISNAN(val) || ISINF(val)) continue; + variance[j] += val; + ++count; + } + if (count > 0) variance[j] /= count; + } + + m[i] = mean; + v[i] = variance; + } + + FeatureMatrix distances(m_channels); + + if (m_type == TypeMFCC) { + + // "Despite the fact that MFCCs extracted from music are + // clearly not Gaussian, [14] showed, somewhat surprisingly, + // that a similarity function comparing single Gaussians + // modelling MFCCs for each track can perform as well as + // mixture models. A great advantage of using single + // Gaussians is that a simple closed form exists for the KL + // divergence." -- Mark Levy, "Lightweight measures for + // timbral similarity of musical audio" + // (http://www.elec.qmul.ac.uk/easaier/papers/mlevytimbralsimilarity.pdf) + + KLDivergence kld; + + for (int i = 0; i < m_channels; ++i) { + for (int j = 0; j < m_channels; ++j) { + double d = kld.distanceGaussian(m[i], v[i], m[j], v[j]); + distances[i].push_back(d); + } + } + + } else { + + // We use the KL divergence for distributions of discrete + // variables, as chroma are histograms already. Or at least, + // they will be when we've normalised them like this: + for (int i = 0; i < m_channels; ++i) { + MathUtilities::normalise(m[i], MathUtilities::NormaliseUnitSum); + } + + KLDivergence kld; + + for (int i = 0; i < m_channels; ++i) { + for (int j = 0; j < m_channels; ++j) { + double d = kld.distanceDistribution(m[i], m[j], true); + distances[i].push_back(d); + } + } + } + + Feature feature; + feature.hasTimestamp = true; + + char labelBuffer[100]; + + for (int i = 0; i < m_channels; ++i) { + + feature.timestamp = Vamp::RealTime(i, 0); + + sprintf(labelBuffer, "Means for channel %d", i+1); + feature.label = labelBuffer; + + feature.values.clear(); + for (int k = 0; k < m_featureColumnSize; ++k) { + feature.values.push_back(m[i][k]); + } + + returnFeatures[m_meansOutput].push_back(feature); + + sprintf(labelBuffer, "Variances for channel %d", i+1); + feature.label = labelBuffer; + + feature.values.clear(); + for (int k = 0; k < m_featureColumnSize; ++k) { + feature.values.push_back(v[i][k]); + } + + returnFeatures[m_variancesOutput].push_back(feature); + } + + return distances; +} + +SimilarityPlugin::FeatureMatrix +SimilarityPlugin::calculateRhythmic(FeatureSet &returnFeatures) +{ + if (!needRhythm()) return FeatureMatrix(); + +// std::cerr << "SimilarityPlugin::initialise: rhythm clip for channel 0 contains " +// << m_rhythmValues[0].size() << " frames of size " +// << m_rhythmClipFrameSize << " at process rate " +// << m_processRate << " ( = " +// << (float(m_rhythmValues[0].size() * m_rhythmClipFrameSize) / m_processRate) << " sec )" +// << std::endl; + + BeatSpectrum bscalc; + CosineDistance cd; + + // Our rhythm feature matrix is a deque of vectors for practical + // reasons, but BeatSpectrum::process wants a vector of vectors + // (which is what FeatureMatrix happens to be). + + FeatureMatrixSet bsinput(m_channels); + for (int i = 0; i < m_channels; ++i) { + for (int j = 0; j < m_rhythmValues[i].size(); ++j) { + bsinput[i].push_back(m_rhythmValues[i][j]); + } + } + + FeatureMatrix bs(m_channels); + for (int i = 0; i < m_channels; ++i) { + bs[i] = bscalc.process(bsinput[i]); + } + + FeatureMatrix distances(m_channels); + for (int i = 0; i < m_channels; ++i) { + for (int j = 0; j < m_channels; ++j) { + double d = cd.distance(bs[i], bs[j]); + distances[i].push_back(d); + } + } + + Feature feature; + feature.hasTimestamp = true; + + char labelBuffer[100]; + + for (int i = 0; i < m_channels; ++i) { + + feature.timestamp = Vamp::RealTime(i, 0); + + sprintf(labelBuffer, "Beat spectrum for channel %d", i+1); + feature.label = labelBuffer; + + feature.values.clear(); + for (int j = 0; j < bs[i].size(); ++j) { + feature.values.push_back(bs[i][j]); + } + + returnFeatures[m_beatSpectraOutput].push_back(feature); + } + + return distances; +} + +double +SimilarityPlugin::getDistance(const FeatureMatrix &timbral, + const FeatureMatrix &rhythmic, + int i, int j) +{ + double distance = 1.0; + if (needTimbre()) distance *= timbral[i][j]; + if (needRhythm()) distance *= rhythmic[i][j]; + return distance; +} + +SimilarityPlugin::FeatureSet +SimilarityPlugin::getRemainingFeatures() +{ + FeatureSet returnFeatures; + + // We want to return a matrix of the distances between channels, + // but Vamp doesn't have a matrix return type so we will actually + // return a series of vectors + + FeatureMatrix timbralDistances, rhythmicDistances; + + if (needTimbre()) { + timbralDistances = calculateTimbral(returnFeatures); + } + + if (needRhythm()) { + rhythmicDistances = calculateRhythmic(returnFeatures); + } + + // We give all features a timestamp, otherwise hosts will tend to + // stamp them at the end of the file, which is annoying + + Feature feature; + feature.hasTimestamp = true; + + Feature distanceVectorFeature; + distanceVectorFeature.label = "Distance from first channel"; + distanceVectorFeature.hasTimestamp = true; + distanceVectorFeature.timestamp = Vamp::RealTime::zeroTime; + + std::map<double, int> sorted; + + char labelBuffer[100]; + + for (int i = 0; i < m_channels; ++i) { + + feature.timestamp = Vamp::RealTime(i, 0); + + feature.values.clear(); + for (int j = 0; j < m_channels; ++j) { + double dist = getDistance(timbralDistances, rhythmicDistances, i, j); + feature.values.push_back(dist); + } + + sprintf(labelBuffer, "Distances from channel %d", i+1); + feature.label = labelBuffer; + + returnFeatures[m_distanceMatrixOutput].push_back(feature); + + double fromFirst = + getDistance(timbralDistances, rhythmicDistances, 0, i); + + distanceVectorFeature.values.push_back(fromFirst); + sorted[fromFirst] = i; + } + + returnFeatures[m_distanceVectorOutput].push_back(distanceVectorFeature); + + feature.label = "Order of channels by similarity to first channel"; + feature.values.clear(); + feature.timestamp = Vamp::RealTime(0, 0); + + for (std::map<double, int>::iterator i = sorted.begin(); + i != sorted.end(); ++i) { + feature.values.push_back(i->second + 1); + } + + returnFeatures[m_sortedVectorOutput].push_back(feature); + + feature.label = "Ordered distances of channels from first channel"; + feature.values.clear(); + feature.timestamp = Vamp::RealTime(1, 0); + + for (std::map<double, int>::iterator i = sorted.begin(); + i != sorted.end(); ++i) { + feature.values.push_back(i->first); + } + + returnFeatures[m_sortedVectorOutput].push_back(feature); + + return returnFeatures; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/SimilarityPlugin.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,123 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + * SimilarityPlugin.h + * + * Copyright 2008 Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. + */ + +#ifndef _SIMILARITY_PLUGIN_H_ +#define _SIMILARITY_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> +#include <vamp-sdk/RealTime.h> + +#include <vector> +#include <deque> + +class MFCC; +class Chromagram; +class Decimator; + +class SimilarityPlugin : public Vamp::Plugin +{ +public: + SimilarityPlugin(float inputSampleRate); + virtual ~SimilarityPlugin(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + std::string getIdentifier() const; + std::string getName() const; + std::string getDescription() const; + std::string getMaker() const; + int getPluginVersion() const; + std::string getCopyright() const; + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + InputDomain getInputDomain() const { return TimeDomain; } + + size_t getMinChannelCount() const; + size_t getMaxChannelCount() const; + + SimilarityPlugin::ParameterList getParameterDescriptors() const; + float getParameter(std::string param) const; + void setParameter(std::string param, float value); + + OutputList getOutputDescriptors() const; + + FeatureSet process(const float *const *inputBuffers, Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + int getDecimationFactor() const; + + enum Type { + TypeMFCC, + TypeChroma + }; + + void calculateBlockSize() const; + bool needRhythm() const { return m_rhythmWeighting > m_noRhythm; } + bool needTimbre() const { return m_rhythmWeighting < m_allRhythm; } + + Type m_type; + MFCC *m_mfcc; + MFCC *m_rhythmfcc; + Chromagram *m_chromagram; + Decimator *m_decimator; + int m_featureColumnSize; + float m_rhythmWeighting; + float m_rhythmClipDuration; + float m_rhythmClipOrigin; + int m_rhythmClipFrameSize; + int m_rhythmClipFrames; + int m_rhythmColumnSize; + mutable size_t m_blockSize; // before decimation + size_t m_fftSize; // after decimation + int m_channels; + int m_processRate; + int m_frameNo; + bool m_done; + + static const float m_noRhythm; + static const float m_allRhythm; + + std::vector<int> m_lastNonEmptyFrame; // per channel + std::vector<int> m_emptyFrameCount; // per channel + + mutable int m_distanceMatrixOutput; + mutable int m_distanceVectorOutput; + mutable int m_sortedVectorOutput; + mutable int m_meansOutput; + mutable int m_variancesOutput; + mutable int m_beatSpectraOutput; + + typedef std::vector<double> FeatureColumn; + typedef std::vector<FeatureColumn> FeatureMatrix; + typedef std::vector<FeatureMatrix> FeatureMatrixSet; + + typedef std::deque<FeatureColumn> FeatureColumnQueue; + typedef std::vector<FeatureColumnQueue> FeatureQueueSet; + + FeatureMatrixSet m_values; + FeatureQueueSet m_rhythmValues; + + FeatureMatrix calculateTimbral(FeatureSet &returnFeatures); + FeatureMatrix calculateRhythmic(FeatureSet &returnFeatures); + double getDistance(const FeatureMatrix &timbral, + const FeatureMatrix &rhythmic, + int i, int j); +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/SongParts.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,1866 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "SongParts.h" + +#include <base/Window.h> +#include <dsp/onsets/DetectionFunction.h> +#include <dsp/onsets/PeakPicking.h> +#include <dsp/transforms/FFT.h> +#include <dsp/tempotracking/TempoTrackV2.h> +#include <dsp/tempotracking/DownBeat.h> +#include <chromamethods.h> +#include <maths/MathUtilities.h> +#include <boost/numeric/ublas/matrix.hpp> +#include <boost/numeric/ublas/io.hpp> +#include <boost/math/distributions/normal.hpp> +#include "armadillo" +#include <fstream> +#include <sstream> +#include <cmath> +#include <vector> + +#include <vamp-sdk/Plugin.h> + +using namespace boost::numeric; +using namespace arma; +using std::string; +using std::vector; +using std::cerr; +using std::cout; +using std::endl; + + +#ifndef __GNUC__ +#include <alloca.h> +#endif + + +// Result Struct +typedef struct Part { + int n; + vector<unsigned> indices; + string letter; + unsigned value; + int level; + int nInd; +}Part; + + +/* ------------------------------------ */ +/* ----- BEAT DETECTOR CLASS ---------- */ +/* ------------------------------------ */ + +class BeatTrackerData +{ + /* --- ATTRIBUTES --- */ +public: + DFConfig dfConfig; + DetectionFunction *df; + DownBeat *downBeat; + vector<double> dfOutput; + Vamp::RealTime origin; + + + /* --- METHODS --- */ + + /* --- Constructor --- */ +public: + BeatTrackerData(float rate, const DFConfig &config) : dfConfig(config) { + + df = new DetectionFunction(config); + // decimation factor aims at resampling to c. 3KHz; must be power of 2 + int factor = MathUtilities::nextPowerOfTwo(rate / 3000); + // std::cerr << "BeatTrackerData: factor = " << factor << std::endl; + downBeat = new DownBeat(rate, factor, config.stepSize); + } + + /* --- Desctructor --- */ + ~BeatTrackerData() { + delete df; + delete downBeat; + } + + void reset() { + delete df; + df = new DetectionFunction(dfConfig); + dfOutput.clear(); + downBeat->resetAudioBuffer(); + origin = Vamp::RealTime::zeroTime; + } +}; + + +/* --------------------------------------- */ +/* ----- CHROMA EXTRACTOR CLASS ---------- */ +/* --------------------------------------- */ + +class ChromaData +{ + + /* --- ATTRIBUTES --- */ + +public: + int frameCount; + int nBPS; + Vamp::Plugin::FeatureList logSpectrum; + size_t blockSize; + int lengthOfNoteIndex; + vector<float> meanTunings; + vector<float> localTunings; + float whitening; + float preset; + float useNNLS; + vector<float> localTuning; + vector<float> kernelValue; + vector<int> kernelFftIndex; + vector<int> kernelNoteIndex; + float *dict; + bool tuneLocal; + float doNormalizeChroma; + float rollon; + float s; + vector<float> hw; + vector<float> sinvalues; + vector<float> cosvalues; + Window<float> window; + FFTReal fft; + size_t inputSampleRate; + + /* --- METHODS --- */ + + /* --- Constructor --- */ + +public: + ChromaData(float inputSampleRate, size_t block_size) : + frameCount(0), + nBPS(3), + logSpectrum(0), + blockSize(0), + lengthOfNoteIndex(0), + meanTunings(0), + localTunings(0), + whitening(1.0), + preset(0.0), + useNNLS(1.0), + localTuning(0.0), + kernelValue(0), + kernelFftIndex(0), + kernelNoteIndex(0), + dict(0), + tuneLocal(0.0), + doNormalizeChroma(0), + rollon(0.0), + s(0.7), + sinvalues(0), + cosvalues(0), + window(HanningWindow, block_size), + fft(block_size), + inputSampleRate(inputSampleRate) + { + // make the *note* dictionary matrix + dict = new float[nNote * 84]; + for (int i = 0; i < nNote * 84; ++i) dict[i] = 0.0; + blockSize = block_size; + } + + + /* --- Desctructor --- */ + + ~ChromaData() { + delete [] dict; + } + + /* --- Public Methods --- */ + + void reset() { + frameCount = 0; + logSpectrum.clear(); + for (int iBPS = 0; iBPS < 3; ++iBPS) { + meanTunings[iBPS] = 0; + localTunings[iBPS] = 0; + } + localTuning.clear(); + } + + void baseProcess(float *inputBuffers, Vamp::RealTime timestamp) + { + + frameCount++; + float *magnitude = new float[blockSize/2]; + double *fftReal = new double[blockSize]; + double *fftImag = new double[blockSize]; + + // FFTReal wants doubles, so we need to make a local copy of inputBuffers + double *inputBuffersDouble = new double[blockSize]; + for (size_t i = 0; i < blockSize; i++) inputBuffersDouble[i] = inputBuffers[i]; + + fft.process(false, inputBuffersDouble, fftReal, fftImag); + + float energysum = 0; + // make magnitude + float maxmag = -10000; + for (int iBin = 0; iBin < static_cast<int>(blockSize/2); iBin++) { + magnitude[iBin] = sqrt(fftReal[iBin] * fftReal[iBin] + + fftImag[iBin] * fftImag[iBin]); + if (magnitude[iBin]>blockSize*1.0) magnitude[iBin] = blockSize; + // a valid audio signal (between -1 and 1) should not be limited here. + if (maxmag < magnitude[iBin]) maxmag = magnitude[iBin]; + if (rollon > 0) { + energysum += pow(magnitude[iBin],2); + } + } + + float cumenergy = 0; + if (rollon > 0) { + for (int iBin = 2; iBin < static_cast<int>(blockSize/2); iBin++) { + cumenergy += pow(magnitude[iBin],2); + if (cumenergy < energysum * rollon / 100) magnitude[iBin-2] = 0; + else break; + } + } + + if (maxmag < 2) { + // cerr << "timestamp " << timestamp << ": very low magnitude, setting magnitude to all zeros" << endl; + for (int iBin = 0; iBin < static_cast<int>(blockSize/2); iBin++) { + magnitude[iBin] = 0; + } + } + + // cerr << magnitude[200] << endl; + + // note magnitude mapping using pre-calculated matrix + float *nm = new float[nNote]; // note magnitude + for (int iNote = 0; iNote < nNote; iNote++) { + nm[iNote] = 0; // initialise as 0 + } + int binCount = 0; + for (vector<float>::iterator it = kernelValue.begin(); it != kernelValue.end(); ++it) { + nm[kernelNoteIndex[binCount]] += magnitude[kernelFftIndex[binCount]] * kernelValue[binCount]; + binCount++; + } + + float one_over_N = 1.0/frameCount; + // update means of complex tuning variables + for (int iBPS = 0; iBPS < nBPS; ++iBPS) meanTunings[iBPS] *= float(frameCount-1)*one_over_N; + + for (int iTone = 0; iTone < round(nNote*0.62/nBPS)*nBPS+1; iTone = iTone + nBPS) { + for (int iBPS = 0; iBPS < nBPS; ++iBPS) meanTunings[iBPS] += nm[iTone + iBPS]*one_over_N; + float ratioOld = 0.997; + for (int iBPS = 0; iBPS < nBPS; ++iBPS) { + localTunings[iBPS] *= ratioOld; + localTunings[iBPS] += nm[iTone + iBPS] * (1 - ratioOld); + } + } + + float localTuningImag = 0; + float localTuningReal = 0; + for (int iBPS = 0; iBPS < nBPS; ++iBPS) { + localTuningReal += localTunings[iBPS] * cosvalues[iBPS]; + localTuningImag += localTunings[iBPS] * sinvalues[iBPS]; + } + + float normalisedtuning = atan2(localTuningImag, localTuningReal)/(2*M_PI); + localTuning.push_back(normalisedtuning); + + Vamp::Plugin::Feature f1; // logfreqspec + f1.hasTimestamp = true; + f1.timestamp = timestamp; + for (int iNote = 0; iNote < nNote; iNote++) { + f1.values.push_back(nm[iNote]); + } + + // deletes + delete[] inputBuffersDouble; + delete[] magnitude; + delete[] fftReal; + delete[] fftImag; + delete[] nm; + + logSpectrum.push_back(f1); // remember note magnitude + } + + bool initialise() + { + dictionaryMatrix(dict, s); + + // make things for tuning estimation + for (int iBPS = 0; iBPS < nBPS; ++iBPS) { + sinvalues.push_back(sin(2*M_PI*(iBPS*1.0/nBPS))); + cosvalues.push_back(cos(2*M_PI*(iBPS*1.0/nBPS))); + } + + + // make hamming window of length 1/2 octave + int hamwinlength = nBPS * 6 + 1; + float hamwinsum = 0; + for (int i = 0; i < hamwinlength; ++i) { + hw.push_back(0.54 - 0.46 * cos((2*M_PI*i)/(hamwinlength-1))); + hamwinsum += 0.54 - 0.46 * cos((2*M_PI*i)/(hamwinlength-1)); + } + for (int i = 0; i < hamwinlength; ++i) hw[i] = hw[i] / hamwinsum; + + + // initialise the tuning + for (int iBPS = 0; iBPS < nBPS; ++iBPS) { + meanTunings.push_back(0); + localTunings.push_back(0); + } + + blockSize = blockSize; + frameCount = 0; + int tempn = nNote * blockSize/2; + // cerr << "length of tempkernel : " << tempn << endl; + float *tempkernel; + + tempkernel = new float[tempn]; + + logFreqMatrix(inputSampleRate, blockSize, tempkernel); + kernelValue.clear(); + kernelFftIndex.clear(); + kernelNoteIndex.clear(); + int countNonzero = 0; + for (int iNote = 0; iNote < nNote; ++iNote) { + // I don't know if this is wise: manually making a sparse matrix + for (int iFFT = 0; iFFT < static_cast<int>(blockSize/2); ++iFFT) { + if (tempkernel[iFFT + blockSize/2 * iNote] > 0) { + kernelValue.push_back(tempkernel[iFFT + blockSize/2 * iNote]); + if (tempkernel[iFFT + blockSize/2 * iNote] > 0) { + countNonzero++; + } + kernelFftIndex.push_back(iFFT); + kernelNoteIndex.push_back(iNote); + } + } + } + delete [] tempkernel; + } +}; + + +/* --------------------------------- */ +/* ----- SONG PARTITIONER ---------- */ +/* --------------------------------- */ + + +/* --- ATTRIBUTES --- */ + +float SongPartitioner::m_stepSecs = 0.01161; // 512 samples at 44100 +size_t SongPartitioner::m_chromaFramesizeFactor = 16; // 16 times as long as beat tracker's +size_t SongPartitioner::m_chromaStepsizeFactor = 4; // 4 times as long as beat tracker's + + +/* --- METHODS --- */ + +/* --- Constructor --- */ +SongPartitioner::SongPartitioner(float inputSampleRate) : + Vamp::Plugin(inputSampleRate), + m_d(0), + m_bpb(4), + m_pluginFrameCount(0) +{ +} + + +/* --- Desctructor --- */ +SongPartitioner::~SongPartitioner() +{ + delete m_d; +} + + +/* --- Methods --- */ +string SongPartitioner::getIdentifier() const +{ + return "qm-songpartitioner"; +} + +string SongPartitioner::getName() const +{ + return "Song Partitioner"; +} + +string SongPartitioner::getDescription() const +{ + return "Estimate contiguous segments pertaining to song parts such as verse and chorus."; +} + +string SongPartitioner::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int SongPartitioner::getPluginVersion() const +{ + return 2; +} + +string SongPartitioner::getCopyright() const +{ + return "Plugin by Matthew Davies, Christian Landone, Chris Cannam, Matthias Mauch and Massimiliano Zanoni Copyright (c) 2006-2012 QMUL - All Rights Reserved"; +} + +SongPartitioner::ParameterList SongPartitioner::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + + desc.identifier = "bpb"; + desc.name = "Beats per Bar"; + desc.description = "The number of beats in each bar"; + desc.minValue = 2; + desc.maxValue = 16; + desc.defaultValue = 4; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + return list; +} + +float SongPartitioner::getParameter(std::string name) const +{ + if (name == "bpb") return m_bpb; + return 0.0; +} + +void SongPartitioner::setParameter(std::string name, float value) +{ + if (name == "bpb") m_bpb = lrintf(value); +} + + +// Return the StepSize for Chroma Extractor +size_t SongPartitioner::getPreferredStepSize() const +{ + size_t step = size_t(m_inputSampleRate * m_stepSecs + 0.0001); + if (step < 1) step = 1; + + return step; +} + +// Return the BlockSize for Chroma Extractor +size_t SongPartitioner::getPreferredBlockSize() const +{ + size_t theoretical = getPreferredStepSize() * 2; + theoretical *= m_chromaFramesizeFactor; + + return theoretical; +} + + +// Initialize the plugin and define Beat Tracker and Chroma Extractor Objects +bool SongPartitioner::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (m_d) { + delete m_d; + m_d = 0; + } + + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) { + std::cerr << "SongPartitioner::initialise: Unsupported channel count: " + << channels << std::endl; + return false; + } + + if (stepSize != getPreferredStepSize()) { + std::cerr << "ERROR: SongPartitioner::initialise: Unsupported step size for this sample rate: " + << stepSize << " (wanted " << (getPreferredStepSize()) << ")" << std::endl; + return false; + } + + if (blockSize != getPreferredBlockSize()) { + std::cerr << "WARNING: SongPartitioner::initialise: Sub-optimal block size for this sample rate: " + << blockSize << " (wanted " << getPreferredBlockSize() << ")" << std::endl; + } + + // Beat tracker and Chroma extractor has two different configuration parameters + + // Configuration Parameters for Beat Tracker + DFConfig dfConfig; + dfConfig.DFType = DF_COMPLEXSD; + dfConfig.stepSize = stepSize; + dfConfig.frameLength = blockSize / m_chromaFramesizeFactor; + dfConfig.dbRise = 3; + dfConfig.adaptiveWhitening = false; + dfConfig.whiteningRelaxCoeff = -1; + dfConfig.whiteningFloor = -1; + + // Initialise Beat Tracker + m_d = new BeatTrackerData(m_inputSampleRate, dfConfig); + m_d->downBeat->setBeatsPerBar(m_bpb); + + // Initialise Chroma Extractor + m_chromadata = new ChromaData(m_inputSampleRate, blockSize); + m_chromadata->initialise(); + + return true; +} + +void SongPartitioner::reset() +{ + if (m_d) m_d->reset(); + m_pluginFrameCount = 0; +} + +SongPartitioner::OutputList SongPartitioner::getOutputDescriptors() const +{ + OutputList list; + size_t outputCounter = 0; + + OutputDescriptor beat; + beat.identifier = "beats"; + beat.name = "Beats"; + beat.description = "Beat locations labelled with metrical position"; + beat.unit = ""; + beat.hasFixedBinCount = true; + beat.binCount = 0; + beat.sampleType = OutputDescriptor::VariableSampleRate; + beat.sampleRate = 1.0 / m_stepSecs; + m_beatOutputNumber = outputCounter++; + + OutputDescriptor bars; + bars.identifier = "bars"; + bars.name = "Bars"; + bars.description = "Bar locations"; + bars.unit = ""; + bars.hasFixedBinCount = true; + bars.binCount = 0; + bars.sampleType = OutputDescriptor::VariableSampleRate; + bars.sampleRate = 1.0 / m_stepSecs; + m_barsOutputNumber = outputCounter++; + + OutputDescriptor beatcounts; + beatcounts.identifier = "beatcounts"; + beatcounts.name = "Beat Count"; + beatcounts.description = "Beat counter function"; + beatcounts.unit = ""; + beatcounts.hasFixedBinCount = true; + beatcounts.binCount = 1; + beatcounts.sampleType = OutputDescriptor::VariableSampleRate; + beatcounts.sampleRate = 1.0 / m_stepSecs; + m_beatcountsOutputNumber = outputCounter++; + + OutputDescriptor beatsd; + beatsd.identifier = "beatsd"; + beatsd.name = "Beat Spectral Difference"; + beatsd.description = "Beat spectral difference function used for bar-line detection"; + beatsd.unit = ""; + beatsd.hasFixedBinCount = true; + beatsd.binCount = 1; + beatsd.sampleType = OutputDescriptor::VariableSampleRate; + beatsd.sampleRate = 1.0 / m_stepSecs; + m_beatsdOutputNumber = outputCounter++; + + OutputDescriptor logscalespec; + logscalespec.identifier = "logscalespec"; + logscalespec.name = "Log-Frequency Spectrum"; + logscalespec.description = "Spectrum with linear frequency on a log scale."; + logscalespec.unit = ""; + logscalespec.hasFixedBinCount = true; + logscalespec.binCount = nNote; + logscalespec.hasKnownExtents = false; + logscalespec.isQuantized = false; + logscalespec.sampleType = OutputDescriptor::FixedSampleRate; + logscalespec.hasDuration = false; + logscalespec.sampleRate = m_inputSampleRate/2048; + m_logscalespecOutputNumber = outputCounter++; + + OutputDescriptor bothchroma; + bothchroma.identifier = "bothchroma"; + bothchroma.name = "Chromagram and Bass Chromagram"; + bothchroma.description = "Tuning-adjusted chromagram and bass chromagram (stacked on top of each other) from NNLS approximate transcription."; + bothchroma.unit = ""; + bothchroma.hasFixedBinCount = true; + bothchroma.binCount = 24; + bothchroma.hasKnownExtents = false; + bothchroma.isQuantized = false; + bothchroma.sampleType = OutputDescriptor::FixedSampleRate; + bothchroma.hasDuration = false; + bothchroma.sampleRate = m_inputSampleRate/2048; + m_bothchromaOutputNumber = outputCounter++; + + OutputDescriptor qchromafw; + qchromafw.identifier = "qchromafw"; + qchromafw.name = "Pseudo-Quantised Chromagram and Bass Chromagram"; + qchromafw.description = "Pseudo-Quantised Chromagram and Bass Chromagram (frames between two beats are identical)."; + qchromafw.unit = ""; + qchromafw.hasFixedBinCount = true; + qchromafw.binCount = 24; + qchromafw.hasKnownExtents = false; + qchromafw.isQuantized = false; + qchromafw.sampleType = OutputDescriptor::FixedSampleRate; + qchromafw.hasDuration = false; + qchromafw.sampleRate = m_inputSampleRate/2048; + m_qchromafwOutputNumber = outputCounter++; + + OutputDescriptor qchroma; + qchroma.identifier = "qchroma"; + qchroma.name = "Quantised Chromagram and Bass Chromagram"; + qchroma.description = "Quantised Chromagram and Bass Chromagram."; + qchroma.unit = ""; + qchroma.hasFixedBinCount = true; + qchroma.binCount = 24; + qchroma.hasKnownExtents = false; + qchroma.isQuantized = false; + qchroma.sampleType = OutputDescriptor::FixedSampleRate; + qchroma.hasDuration = true; + m_qchromaOutputNumber = outputCounter++; + + OutputDescriptor segm; + segm.identifier = "segm"; + segm.name = "Segmentation"; + segm.description = "Segmentation"; + segm.unit = "segment-type"; + segm.hasFixedBinCount = true; + //segm.binCount = 24; + segm.binCount = 1; + segm.hasKnownExtents = true; + segm.minValue = 1; + segm.maxValue = 5; + segm.isQuantized = true; + segm.quantizeStep = 1; + segm.sampleType = OutputDescriptor::VariableSampleRate; + segm.hasDuration = true; + m_segmOutputNumber = outputCounter++; + + + /* + OutputList list; + OutputDescriptor segmentation; + segmentation.identifier = "segmentation"; + segmentation.name = "Segmentation"; + segmentation.description = "Segmentation"; + segmentation.unit = "segment-type"; + segmentation.hasFixedBinCount = true; + segmentation.binCount = 1; + segmentation.hasKnownExtents = true; + segmentation.minValue = 1; + segmentation.maxValue = nSegmentTypes; + segmentation.isQuantized = true; + segmentation.quantizeStep = 1; + segmentation.sampleType = OutputDescriptor::VariableSampleRate; + segmentation.sampleRate = m_inputSampleRate / getPreferredStepSize(); + list.push_back(segmentation); + return list; + */ + + + list.push_back(beat); + list.push_back(bars); + list.push_back(beatcounts); + list.push_back(beatsd); + list.push_back(logscalespec); + list.push_back(bothchroma); + list.push_back(qchromafw); + list.push_back(qchroma); + list.push_back(segm); + + return list; +} + +// Executed for each frame - called from the host + +// We use time domain input, because DownBeat requires it -- so we +// use the time-domain version of DetectionFunction::process which +// does its own FFT. It requires doubles as input, so we need to +// make a temporary copy + +// We only support a single input channel +SongPartitioner::FeatureSet SongPartitioner::process(const float *const *inputBuffers,Vamp::RealTime timestamp) +{ + if (!m_d) { + cerr << "ERROR: SongPartitioner::process: " + << "SongPartitioner has not been initialised" + << endl; + return FeatureSet(); + } + + const int fl = m_d->dfConfig.frameLength; +#ifndef __GNUC__ + double *dfinput = (double *)alloca(fl * sizeof(double)); +#else + double dfinput[fl]; +#endif + int sampleOffset = ((m_chromaFramesizeFactor-1) * fl) / 2; + + // Since chroma needs a much longer frame size, we only ever use the very + // beginning of the frame for beat tracking. + for (int i = 0; i < fl; ++i) dfinput[i] = inputBuffers[0][i]; + double output = m_d->df->process(dfinput); + + if (m_d->dfOutput.empty()) m_d->origin = timestamp; + +// std::cerr << "df[" << m_d->dfOutput.size() << "] is " << output << std::endl; + m_d->dfOutput.push_back(output); + + // Downsample and store the incoming audio block. + // We have an overlap on the incoming audio stream (step size is + // half block size) -- this function is configured to take only a + // step size's worth, so effectively ignoring the overlap. Note + // however that this means we omit the last blocksize - stepsize + // samples completely for the purposes of barline detection + // (hopefully not a problem) + m_d->downBeat->pushAudioBlock(inputBuffers[0]); + + // The following is not done every time, but only every m_chromaFramesizeFactor times, + // because the chroma does not need dense time frames. + + if (m_pluginFrameCount % m_chromaStepsizeFactor == 0) + { + + // Window the full time domain, data, FFT it and process chroma stuff. + + #ifndef __GNUC__ + float *windowedBuffers = (float *)alloca(m_chromadata->blockSize * sizeof(float)); + #else + float windowedBuffers[m_chromadata->blockSize]; + #endif + m_chromadata->window.cut(&inputBuffers[0][0], &windowedBuffers[0]); + + // adjust timestamp (we want the middle of the frame) + timestamp = timestamp + Vamp::RealTime::frame2RealTime(sampleOffset, lrintf(m_inputSampleRate)); + + m_chromadata->baseProcess(&windowedBuffers[0], timestamp); + + } + m_pluginFrameCount++; + + FeatureSet fs; + fs[m_logscalespecOutputNumber].push_back( + m_chromadata->logSpectrum.back()); + return fs; +} + +SongPartitioner::FeatureSet SongPartitioner::getRemainingFeatures() +{ + if (!m_d) { + cerr << "ERROR: SongPartitioner::getRemainingFeatures: " + << "SongPartitioner has not been initialised" + << endl; + return FeatureSet(); + } + + FeatureSet masterFeatureset = BeatTrack(); + FeatureList chromaList = ChromaFeatures(); + + for (size_t i = 0; i < chromaList.size(); ++i) + { + masterFeatureset[m_bothchromaOutputNumber].push_back(chromaList[i]); + } + + // quantised and pseudo-quantised (beat-wise) chroma + std::vector<FeatureList> quantisedChroma = BeatQuantiser(chromaList, masterFeatureset[m_beatOutputNumber]); + + masterFeatureset[m_qchromafwOutputNumber] = quantisedChroma[0]; + masterFeatureset[m_qchromaOutputNumber] = quantisedChroma[1]; + + // Segmentation + masterFeatureset[m_segmOutputNumber] = Segmenter(quantisedChroma[1]); + + return(masterFeatureset); +} + +/* ------ Beat Tracker ------ */ + +SongPartitioner::FeatureSet SongPartitioner::BeatTrack() +{ + vector<double> df; + vector<double> beatPeriod; + vector<double> tempi; + + for (size_t i = 2; i < m_d->dfOutput.size(); ++i) { // discard first two elts + df.push_back(m_d->dfOutput[i]); + beatPeriod.push_back(0.0); + } + if (df.empty()) return FeatureSet(); + + TempoTrackV2 tt(m_inputSampleRate, m_d->dfConfig.stepSize); + tt.calculateBeatPeriod(df, beatPeriod, tempi); + + vector<double> beats; + tt.calculateBeats(df, beatPeriod, beats); + + vector<int> downbeats; + size_t downLength = 0; + const float *downsampled = m_d->downBeat->getBufferedAudio(downLength); + m_d->downBeat->findDownBeats(downsampled, downLength, beats, downbeats); + + vector<double> beatsd; + m_d->downBeat->getBeatSD(beatsd); + + /*std::cout << "BeatTracker: found downbeats at: "; + for (int i = 0; i < downbeats.size(); ++i) std::cout << downbeats[i] << " " << std::endl;*/ + + FeatureSet returnFeatures; + + char label[20]; + + int dbi = 0; + int beat = 0; + int bar = 0; + + if (!downbeats.empty()) { + // get the right number for the first beat; this will be + // incremented before use (at top of the following loop) + int firstDown = downbeats[0]; + beat = m_bpb - firstDown - 1; + if (beat == m_bpb) beat = 0; + } + + for (size_t i = 0; i < beats.size(); ++i) { + + size_t frame = beats[i] * m_d->dfConfig.stepSize; + + if (dbi < downbeats.size() && i == downbeats[dbi]) { + beat = 0; + ++bar; + ++dbi; + } else { + ++beat; + } + + /* Ooutput Section */ + + // outputs are: + // + // 0 -> beats + // 1 -> bars + // 2 -> beat counter function + + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_d->origin + Vamp::RealTime::frame2RealTime (frame, lrintf(m_inputSampleRate)); + + sprintf(label, "%d", beat + 1); + feature.label = label; + returnFeatures[m_beatOutputNumber].push_back(feature); // labelled beats + + feature.values.push_back(beat + 1); + returnFeatures[m_beatcountsOutputNumber].push_back(feature); // beat function + + if (i > 0 && i <= beatsd.size()) { + feature.values.clear(); + feature.values.push_back(beatsd[i-1]); + feature.label = ""; + returnFeatures[m_beatsdOutputNumber].push_back(feature); // beat spectral difference + } + + if (beat == 0) { + feature.values.clear(); + sprintf(label, "%d", bar); + feature.label = label; + returnFeatures[m_barsOutputNumber].push_back(feature); // bars + } + } + + return returnFeatures; +} + + +/* ------ Chroma Extractor ------ */ + +SongPartitioner::FeatureList SongPartitioner::ChromaFeatures() +{ + + FeatureList returnFeatureList; + FeatureList tunedlogfreqspec; + + if (m_chromadata->logSpectrum.size() == 0) return returnFeatureList; + + /** Calculate Tuning + calculate tuning from (using the angle of the complex number defined by the + cumulative mean real and imag values) + **/ + float meanTuningImag = 0; + float meanTuningReal = 0; + for (int iBPS = 0; iBPS < nBPS; ++iBPS) { + meanTuningReal += m_chromadata->meanTunings[iBPS] * m_chromadata->cosvalues[iBPS]; + meanTuningImag += m_chromadata->meanTunings[iBPS] * m_chromadata->sinvalues[iBPS]; + } + float cumulativetuning = 440 * pow(2,atan2(meanTuningImag, meanTuningReal)/(24*M_PI)); + float normalisedtuning = atan2(meanTuningImag, meanTuningReal)/(2*M_PI); + int intShift = floor(normalisedtuning * 3); + float floatShift = normalisedtuning * 3 - intShift; // floatShift is a really bad name for this + + char buffer0 [50]; + + sprintf(buffer0, "estimated tuning: %0.1f Hz", cumulativetuning); + + /** Tune Log-Frequency Spectrogram + calculate a tuned log-frequency spectrogram (f2): use the tuning estimated above (kinda f0) to + perform linear interpolation on the existing log-frequency spectrogram (kinda f1). + **/ + cerr << endl << "[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... "; + + float tempValue = 0; + + int count = 0; + + for (FeatureList::iterator i = m_chromadata->logSpectrum.begin(); i != m_chromadata->logSpectrum.end(); ++i) + { + + Feature f1 = *i; + Feature f2; // tuned log-frequency spectrum + + f2.hasTimestamp = true; + f2.timestamp = f1.timestamp; + + f2.values.push_back(0.0); + f2.values.push_back(0.0); // set lower edge to zero + + if (m_chromadata->tuneLocal) { + intShift = floor(m_chromadata->localTuning[count] * 3); + floatShift = m_chromadata->localTuning[count] * 3 - intShift; + // floatShift is a really bad name for this + } + + for (int k = 2; k < (int)f1.values.size() - 3; ++k) + { // interpolate all inner bins + tempValue = f1.values[k + intShift] * (1-floatShift) + f1.values[k+intShift+1] * floatShift; + f2.values.push_back(tempValue); + } + + f2.values.push_back(0.0); + f2.values.push_back(0.0); + f2.values.push_back(0.0); // upper edge + + vector<float> runningmean = SpecialConvolution(f2.values,m_chromadata->hw); + vector<float> runningstd; + for (int i = 0; i < nNote; i++) { // first step: squared values into vector (variance) + runningstd.push_back((f2.values[i] - runningmean[i]) * (f2.values[i] - runningmean[i])); + } + runningstd = SpecialConvolution(runningstd,m_chromadata->hw); // second step convolve + for (int i = 0; i < nNote; i++) + { + + runningstd[i] = sqrt(runningstd[i]); + // square root to finally have running std + + if (runningstd[i] > 0) + { + f2.values[i] = (f2.values[i] - runningmean[i]) > 0 ? + (f2.values[i] - runningmean[i]) / pow(runningstd[i],m_chromadata->whitening) : 0; + } + + if (f2.values[i] < 0) { + + cerr << "ERROR: negative value in logfreq spectrum" << endl; + + } + } + tunedlogfreqspec.push_back(f2); + count++; + } + cerr << "done." << endl; + /** Semitone spectrum and chromagrams + Semitone-spaced log-frequency spectrum derived + from the tuned log-freq spectrum above. the spectrum + is inferred using a non-negative least squares algorithm. + Three different kinds of chromagram are calculated, "treble", "bass", and "both" (which means + bass and treble stacked onto each other). + **/ + if (m_chromadata->useNNLS == 0) { + cerr << "[NNLS Chroma Plugin] Mapping to semitone spectrum and chroma ... "; + } else { + cerr << "[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... "; + } + + vector<float> oldchroma = vector<float>(12,0); + vector<float> oldbasschroma = vector<float>(12,0); + count = 0; + + for (FeatureList::iterator it = tunedlogfreqspec.begin(); it != tunedlogfreqspec.end(); ++it) { + Feature logfreqsp = *it; // logfreq spectrum + Feature bothchroma; // treble and bass chromagram + + bothchroma.hasTimestamp = true; + bothchroma.timestamp = logfreqsp.timestamp; + + float b[nNote]; + + bool some_b_greater_zero = false; + float sumb = 0; + for (int i = 0; i < nNote; i++) { + b[i] = logfreqsp.values[i]; + sumb += b[i]; + if (b[i] > 0) { + some_b_greater_zero = true; + } + } + + // here's where the non-negative least squares algorithm calculates the note activation x + + vector<float> chroma = vector<float>(12, 0); + vector<float> basschroma = vector<float>(12, 0); + float currval; + int iSemitone = 0; + + if (some_b_greater_zero) { + if (m_chromadata->useNNLS == 0) { + for (int iNote = nBPS/2 + 2; iNote < nNote - nBPS/2; iNote += nBPS) { + currval = 0; + for (int iBPS = -nBPS/2; iBPS < nBPS/2+1; ++iBPS) { + currval += b[iNote + iBPS] * (1-abs(iBPS*1.0/(nBPS/2+1))); + } + chroma[iSemitone % 12] += currval * treblewindow[iSemitone]; + basschroma[iSemitone % 12] += currval * basswindow[iSemitone]; + iSemitone++; + } + + } else { + float x[84+1000]; + for (int i = 1; i < 1084; ++i) x[i] = 1.0; + vector<int> signifIndex; + int index=0; + sumb /= 84.0; + for (int iNote = nBPS/2 + 2; iNote < nNote - nBPS/2; iNote += nBPS) { + float currval = 0; + for (int iBPS = -nBPS/2; iBPS < nBPS/2+1; ++iBPS) { + currval += b[iNote + iBPS]; + } + if (currval > 0) signifIndex.push_back(index); + index++; + } + float rnorm; + float w[84+1000]; + float zz[84+1000]; + int indx[84+1000]; + int mode; + int dictsize = nNote*signifIndex.size(); + + float *curr_dict = new float[dictsize]; + for (int iNote = 0; iNote < (int)signifIndex.size(); ++iNote) { + for (int iBin = 0; iBin < nNote; iBin++) { + curr_dict[iNote * nNote + iBin] = + 1.0 * m_chromadata->dict[signifIndex[iNote] * nNote + iBin]; + } + } + nnls(curr_dict, nNote, nNote, signifIndex.size(), b, x, &rnorm, w, zz, indx, &mode); + delete [] curr_dict; + for (int iNote = 0; iNote < (int)signifIndex.size(); ++iNote) { + // cerr << mode << endl; + chroma[signifIndex[iNote] % 12] += x[iNote] * treblewindow[signifIndex[iNote]]; + basschroma[signifIndex[iNote] % 12] += x[iNote] * basswindow[signifIndex[iNote]]; + } + } + } + + chroma.insert(chroma.begin(), basschroma.begin(), basschroma.end()); + // just stack the both chromas + + bothchroma.values = chroma; + returnFeatureList.push_back(bothchroma); + count++; + } + cerr << "done." << endl; + + return returnFeatureList; +} + +/* ------ Beat Quantizer ------ */ + +std::vector<Vamp::Plugin::FeatureList> SongPartitioner::BeatQuantiser(Vamp::Plugin::FeatureList chromagram, Vamp::Plugin::FeatureList beats) +{ + std::vector<FeatureList> returnVector; + + FeatureList fwQchromagram; // frame-wise beat-quantised chroma + FeatureList bwQchromagram; // beat-wise beat-quantised chroma + + size_t nChromaFrame = chromagram.size(); + size_t nBeat = beats.size(); + + if (nBeat == 0 && nChromaFrame == 0) return returnVector; + + size_t nBin = chromagram[0].values.size(); + + vector<float> tempChroma = vector<float>(nBin); + + Vamp::RealTime beatTimestamp = Vamp::RealTime::zeroTime; + int currBeatCount = -1; // start before first beat + int framesInBeat = 0; + + for (size_t iChroma = 0; iChroma < nChromaFrame; ++iChroma) + { + Vamp::RealTime chromaTimestamp = chromagram[iChroma].timestamp; + if (chromaTimestamp > beats[currBeatCount+1].timestamp || + iChroma == nChromaFrame-1) + { + // new beat (or last chroma frame) + // 1. finish all the old beat processing + for (size_t i = 0; i < nBin; ++i) tempChroma[i] /= framesInBeat; // average + + Feature bwQchromaFrame; + bwQchromaFrame.hasTimestamp = true; + bwQchromaFrame.timestamp = beatTimestamp; + bwQchromaFrame.values = tempChroma; + bwQchromaFrame.duration = beats[currBeatCount+1].timestamp - beats[currBeatCount].timestamp; + bwQchromagram.push_back(bwQchromaFrame); + + for (int iFrame = -framesInBeat; iFrame < 0; ++iFrame) + { + Feature fwQchromaFrame; + fwQchromaFrame.hasTimestamp = true; + fwQchromaFrame.timestamp = chromagram[iChroma+iFrame].timestamp; + fwQchromaFrame.values = tempChroma; // all between two beats get the same + fwQchromagram.push_back(fwQchromaFrame); + } + + // 2. increments / resets for current (new) beat + currBeatCount++; + beatTimestamp = beats[currBeatCount].timestamp; + for (size_t i = 0; i < nBin; ++i) tempChroma[i] = 0; // average + framesInBeat = 0; + } + framesInBeat++; + for (size_t i = 0; i < nBin; ++i) tempChroma[i] += chromagram[iChroma].values[i]; + } + returnVector.push_back(fwQchromagram); + returnVector.push_back(bwQchromagram); +} + + + +/* -------------------------------- */ +/* ------ Support Functions ------ */ +/* -------------------------------- */ + +// one-dimesion median filter +arma::vec medfilt1(arma::vec v, int medfilt_length) +{ + int halfWin = medfilt_length/2; + + // result vector + arma::vec res = arma::zeros<arma::vec>(v.size()); + + // padding + arma::vec padV = arma::zeros<arma::vec>(v.size()+medfilt_length-1); + + for (unsigned i=medfilt_length/2; i < medfilt_length/2+v.size(); ++ i) + { + padV(i) = v(i-medfilt_length/2); + } + + // Median filter + arma::vec win = arma::zeros<arma::vec>(medfilt_length); + + for (unsigned i=0; i < v.size(); ++i) + { + win = padV.subvec(i,i+halfWin*2); + win = sort(win); + res(i) = win(halfWin); + } + + return res; +} + + +// Quantile +double quantile(arma::vec v, double p) +{ + arma::vec sortV = arma::sort(v); + int n = sortV.size(); + arma::vec x = arma::zeros<vec>(n+2); + arma::vec y = arma::zeros<vec>(n+2); + + x(0) = 0; + x(n+1) = 100; + + for (unsigned i=1; i<n+1; ++i) + x(i) = 100*(0.5+(i-1))/n; + + y(0) = sortV(0); + y.subvec(1,n) = sortV; + y(n+1) = sortV(n-1); + + arma::uvec x2index = find(x>=p*100); + + // Interpolation + double x1 = x(x2index(0)-1); + double x2 = x(x2index(0)); + double y1 = y(x2index(0)-1); + double y2 = y(x2index(0)); + + double res = (y2-y1)/(x2-x1)*(p*100-x1)+y1; + + return res; +} + +// Max Filtering +arma::mat maxfilt1(arma::mat inmat, int len) +{ + arma::mat outmat = inmat; + + for (int i=0; i<inmat.n_rows; ++i) + { + if (arma::sum(inmat.row(i)) > 0) + { + // Take a window of rows + int startWin; + int endWin; + + if (0 > i-len) + startWin = 0; + else + startWin = i-len; + + if (inmat.n_rows-1 < i+len-1) + endWin = inmat.n_rows-1; + else + endWin = i+len-1; + + outmat(i,span::all) = arma::max(inmat(span(startWin,endWin),span::all)); + } + } + + return outmat; + +} + +// Null Parts +Part nullpart(vector<Part> parts, arma::vec barline) +{ + arma::uvec nullindices = arma::ones<arma::uvec>(barline.size()); + for (unsigned iPart=0; iPart<parts.size(); ++iPart) + { + for (unsigned iIndex=0; iIndex<parts[0].indices.size(); ++iIndex) + { + for (unsigned i=0; i<parts[iPart].n; ++i) + { + unsigned ind = parts[iPart].indices[iIndex]+i; + nullindices(ind) = 0; + } + } + } + + Part newPart; + newPart.n = 1; + uvec q = find(nullindices > 0); + + for (unsigned i=0; i<q.size();++i) + newPart.indices.push_back(q(i)); + + newPart.letter = '-'; + newPart.value = 0; + newPart.level = 0; + + return newPart; +} + + +// Merge Nulls +void mergenulls(vector<Part> &parts) +{ + for (unsigned iPart=0; iPart<parts.size(); ++iPart) + { + + vector<Part> newVectorPart; + + if (parts[iPart].letter.compare("-")==0) + { + sort (parts[iPart].indices.begin(), parts[iPart].indices.end()); + unsigned newpartind = -1; + + vector<int> indices; + indices.push_back(-2); + + for (unsigned iIndex=0; iIndex<parts[iPart].indices.size(); ++iIndex) + indices.push_back(parts[iPart].indices[iIndex]); + + for (unsigned iInd=1; iInd < indices.size(); ++iInd) + { + if (indices[iInd] - indices[iInd-1] > 1) + { + newpartind++; + + Part newPart; + newPart.letter = 'n'; + std::stringstream out; + out << newpartind+1; + newPart.letter.append(out.str()); + newPart.value = 20+newpartind+1; + newPart.n = 1; + newPart.indices.push_back(indices[iInd]); + newPart.level = 0; + + newVectorPart.push_back(newPart); + } + else + { + newVectorPart[newpartind].n = newVectorPart[newpartind].n+1; + } + } + parts.erase (parts.end()); + + for (unsigned i=0; i<newVectorPart.size(); ++i) + parts.push_back(newVectorPart[i]); + } + } +} + +/* ------ Segmentation ------ */ + +vector<Part> songSegment(Vamp::Plugin::FeatureList quatisedChromagram) +{ + + + /* ------ Parameters ------ */ + double thresh_beat = 0.85; + double thresh_seg = 0.80; + int medfilt_length = 5; + int minlength = 28; + int maxlength = 128; + double quantilePerc = 0.1; + /* ------------------------ */ + + + // Collect Info + int nBeat = quatisedChromagram.size(); // Number of feature vector + int nFeatValues = quatisedChromagram[0].values.size(); // Number of values for each feature vector + + // ----- TEMP ------ + /*if (nBeat > 255) + nBeat = 255; + std::cout << "CUT THE ERROR BEAT -> " << nBeat << std::endl;*/ + // ----------------- + + arma::irowvec timeStamp = arma::zeros<arma::imat>(1,nBeat); // Vector of Time Stamps + + // Save time stamp as a Vector + if (quatisedChromagram[0].hasTimestamp) + { + for (unsigned i = 0; i < nBeat; ++ i) + timeStamp[i] = quatisedChromagram[i].timestamp.nsec; + } + + + // Build a ObservationTOFeatures Matrix + arma::mat featVal = arma::zeros<mat>(nBeat,nFeatValues/2); + + for (unsigned i = 0; i < nBeat; ++ i) + for (unsigned j = 0; j < nFeatValues/2; ++ j) + { + featVal(i,j) = (quatisedChromagram[i].values[j]+quatisedChromagram[i].values[j+12]) * 0.8; + } + + // Set to arbitrary value to feature vectors with low std + arma::mat a = stddev(featVal,1,1); + + // Feature Colleration Matrix + arma::mat simmat0 = 1-arma::cor(arma::trans(featVal)); + + + for (unsigned i = 0; i < nBeat; ++ i) + { + if (a(i)<0.000001) + { + featVal(i,1) = 1000; // arbitrary + + for (unsigned j = 0; j < nFeatValues/2; ++j) + { + simmat0(i,j) = 1; + simmat0(j,i) = 1; + } + } + } + + arma::mat simmat = 1-simmat0/2; + + // -------- To delate when the proble with the add of beat will be solved ------- + for (unsigned i = 0; i < nBeat; ++ i) + for (unsigned j = 0; j < nBeat; ++ j) + if (!std::isfinite(simmat(i,j))) + simmat(i,j)=0; + // ------------------------------------------------------------------------------ + + // Median Filtering applied to the Correlation Matrix + // The median filter is for each diagonal of the Matrix + arma::mat median_simmat = arma::zeros<arma::mat>(nBeat,nBeat); + + for (unsigned i = 0; i < nBeat; ++ i) + { + arma::vec temp = medfilt1(simmat.diag(i),medfilt_length); + median_simmat.diag(i) = temp; + median_simmat.diag(-i) = temp; + } + + for (unsigned i = 0; i < nBeat; ++ i) + for (unsigned j = 0; j < nBeat; ++ j) + if (!std::isfinite(median_simmat(i,j))) + median_simmat(i,j) = 0; + + // -------------- NOT CONVERTED ------------------------------------- + // if param.seg.standardise + // med_median_simmat = repmat(median(median_simmat),nBeat,1); + // std_median_simmat = repmat(std(median_simmat),nBeat,1); + // median_simmat = (median_simmat - med_median_simmat) ./ std_median_simmat; + // end + // -------------------------------------------------------- + + // Retrieve Bar Bounderies + arma::uvec dup = find(median_simmat > thresh_beat); + arma::mat potential_duplicates = arma::zeros<arma::mat>(nBeat,nBeat); + potential_duplicates.elem(dup) = arma::ones<arma::vec>(dup.size()); + potential_duplicates = trimatu(potential_duplicates); + + unsigned nPartlengths = round((maxlength-minlength)/4)+1; + arma::vec partlengths = zeros<arma::vec>(nPartlengths); + + for (unsigned i = 0; i < nPartlengths; ++ i) + partlengths(i) = (i*4)+ minlength; + + // initialise arrays + arma::cube simArray = zeros<arma::cube>(nBeat,nBeat,nPartlengths); + arma::cube decisionArray2 = zeros<arma::cube>(nBeat,nBeat,nPartlengths); + + int conta = 0; + + //for (unsigned iLength = 0; iLength < nPartlengths; ++ iLength) + for (unsigned iLength = 0; iLength < 20; ++ iLength) + { + unsigned len = partlengths(iLength); + unsigned nUsedBeat = nBeat - len + 1; // number of potential rep beginnings: they can't overlap at the end of the song + + for (unsigned iBeat = 0; iBeat < nUsedBeat; ++ iBeat) // looping over all columns (arbitrarily chosen columns) + { + arma::uvec help2 = find(potential_duplicates(span(0,nUsedBeat-1),iBeat)==1); + + for (unsigned i=0; i<help2.size(); ++i) + { + + // measure how well two length len segments go together + int kBeat = help2(i); + arma::vec distrib = median_simmat(span(iBeat,iBeat+len-1),span(kBeat,kBeat+len-1)).diag(0); + simArray(iBeat,kBeat,iLength) = quantile(distrib,quantilePerc); + } + } + + arma::mat tempM = simArray(span(0,nUsedBeat-1),span(0,nUsedBeat-1),span(iLength,iLength)); + simArray.slice(iLength)(span(0,nUsedBeat-1),span(0,nUsedBeat-1)) = tempM + arma::trans(tempM) - (eye<mat>(nUsedBeat,nUsedBeat)%tempM); + + // convolution + arma::vec K = arma::zeros<vec>(3); + K << 0.01 << 0.98 << 0.01; + + + for (unsigned i=0; i<simArray.n_rows; ++i) + { + arma::rowvec t = arma::conv((arma::rowvec)simArray.slice(iLength).row(i),K); + simArray.slice(iLength)(i,span::all) = t.subvec(1,t.size()-2); + } + + // take only over-average bars that do not overlap + + arma::mat temp = arma::zeros<mat>(simArray.n_rows, simArray.n_cols); + temp(span::all, span(0,nUsedBeat-1)) = simArray.slice(iLength)(span::all,span(0,nUsedBeat-1)); + + for (unsigned i=0; i<temp.n_rows; ++i) + for (unsigned j=0; j<nUsedBeat; ++j) + if (temp(i,j) < thresh_seg) + temp(i,j) = 0; + + decisionArray2.slice(iLength) = temp; + + arma::mat maxMat = maxfilt1(decisionArray2.slice(iLength),len-1); + + for (unsigned i=0; i<decisionArray2.n_rows; ++i) + for (unsigned j=0; j<decisionArray2.n_cols; ++j) + if (decisionArray2.slice(iLength)(i,j) < maxMat(i,j)) + decisionArray2.slice(iLength)(i,j) = 0; + + decisionArray2.slice(iLength) = decisionArray2.slice(iLength) % arma::trans(decisionArray2.slice(iLength)); + + for (unsigned i=0; i<simArray.n_rows; ++i) + for (unsigned j=0; j<simArray.n_cols; ++j) + if (simArray.slice(iLength)(i,j) < thresh_seg) + potential_duplicates(i,j) = 0; + } + + // Milk the data + + arma::mat bestval; + + for (unsigned iLength=0; iLength<nPartlengths; ++iLength) + { + arma::mat temp = arma::zeros<arma::mat>(decisionArray2.n_rows,decisionArray2.n_cols); + + for (unsigned rows=0; rows<decisionArray2.n_rows; ++rows) + for (unsigned cols=0; cols<decisionArray2.n_cols; ++cols) + if (decisionArray2.slice(iLength)(rows,cols) > 0) + temp(rows,cols) = 1; + + arma::vec currLogicSum = arma::sum(temp,1); + + for (unsigned iBeat=0; iBeat<nBeat; ++iBeat) + if (currLogicSum(iBeat) > 1) + { + arma::vec t = decisionArray2.slice(iLength)(span::all,iBeat); + double currSum = sum(t); + + unsigned count = 0; + for (unsigned i=0; i<t.size(); ++i) + if (t(i)>0) + count++; + + currSum = (currSum/count)/2; + + arma::rowvec t1; + t1 << (currLogicSum(iBeat)-1) * partlengths(iLength) << currSum << iLength << iBeat << currLogicSum(iBeat); + + bestval = join_cols(bestval,t1); + } + } + + // Definition of the resulting vector + vector<Part> parts; + + // make a table of all valid sets of parts + + char partletters[] = {'A','B','C','D','E','F','G', 'H','I','J','K','L','M','N','O','P','Q','R','S'}; + unsigned partvalues[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; + arma::vec valid_sets = arma::ones<arma::vec>(bestval.n_rows); + + if (!bestval.is_empty()) + { + + // In questo punto viene introdotto un errore alla 3 cifra decimale + + arma::colvec t = arma::zeros<arma::colvec>(bestval.n_rows); + for (unsigned i=0; i<bestval.n_rows; ++i) + { + t(i) = bestval(i,1)*2; + } + + double m = t.max(); + + bestval(span::all,1) = bestval(span::all,1) / m; + bestval(span::all,0) = bestval(span::all,0) + bestval(span::all,1); + + arma::mat bestval2; + for (unsigned i=0; i<bestval.n_cols; ++i) + if (i!=1) + bestval2 = join_rows(bestval2,bestval.col(i)); + + for (unsigned kSeg=0; kSeg<1; ++kSeg) + { + + arma::mat currbestvals = arma::zeros<arma::mat>(bestval2.n_rows, bestval2.n_cols); + for (unsigned i=0; i<bestval2.n_rows; ++i) + for (unsigned j=0; j<bestval2.n_cols; ++j) + if (valid_sets(i)) + currbestvals(i,j) = bestval2(i,j); + + arma::vec t1 = currbestvals.col(0); + double ma; + uword maIdx; + ma = t1.max(maIdx); + + // -------------- NOT CONVERTED ------------------------------------- + //if isempty(m) + // break + // end + // ------------------------------------------------------------------ + + double bestLength = partlengths(currbestvals(maIdx,1)); + arma::rowvec bestIndices = decisionArray2.slice(currbestvals(maIdx,1))(currbestvals(maIdx,2),span::all); + + arma::rowvec bestIndicesMap = arma::zeros<arma::rowvec>(bestIndices.size()); + for (unsigned i=0; i<bestIndices.size(); ++i) + if (bestIndices(i)>0) + bestIndicesMap(i) = 1; + + arma::rowvec mask = arma::zeros<arma::rowvec>(bestLength*2-1); + for (unsigned i=0; i<bestLength; ++i) + mask(i+bestLength-1) = 1; + + arma::rowvec t2 = arma::conv(bestIndicesMap,mask); + arma::rowvec island = t2.subvec(mask.size()/2,t2.size()-1-mask.size()/2); + + // Save results in the structure + Part newPart; + newPart.n = bestLength; + uvec q1 = find(bestIndices > 0); + + for (unsigned i=0; i<q1.size();++i) + newPart.indices.push_back(q1(i)); + + newPart.letter = partletters[kSeg]; + newPart.value = partvalues[kSeg]; + newPart.level = kSeg+1; + parts.push_back(newPart); + + uvec q2 = find(valid_sets==1); + + for (unsigned i=0; i<q2.size(); ++i) + { + unsigned iSet = q2(i); + unsigned s = partlengths(bestval2(iSet,1)); + + arma::rowvec mask1 = arma::zeros<arma::rowvec>(s*2-1); + for (unsigned i=0; i<s; ++i) + mask1(i+s-1) = 1; + + arma::rowvec Ind = decisionArray2.slice(bestval2(iSet,1))(bestval2(iSet,2),span::all); + arma::rowvec IndMap = arma::zeros<arma::rowvec>(Ind.size()); + for (unsigned i=0; i<Ind.size(); ++i) + if (Ind(i)>0) + IndMap(i) = 2; + + arma::rowvec t3 = arma::conv(IndMap,mask1); + arma::rowvec currislands = t3.subvec(mask1.size()/2,t3.size()-1-mask1.size()/2); + + arma::rowvec islandsdMult = currislands%island; + arma::uvec islandsIndex = find(islandsdMult > 0); + + if (islandsIndex.size() == currislands.size()) + valid_sets(iSet) = 0; + } + } + } + else + { + Part newPart; + newPart.n = nBeat; + newPart.indices.push_back(1); + newPart.letter = 'A'; + newPart.value = 1; + newPart.level = 1; + parts.push_back(newPart); + } + + + arma::vec bar = linspace(1,nBeat,nBeat); + Part np = nullpart(parts,bar); + parts.push_back(np); + + // -------------- NOT CONVERTED ------------------------------------- + // if param.seg.editor + // [pa, ta] = partarray(parts); + // parts = editorssearch(pa, ta, parts); + // parts = [parts, nullpart(parts,1:nBeat)]; + // end + // ------------------------------------------------------------------ + + + mergenulls(parts); + + + // -------------- NOT CONVERTED ------------------------------------- + // if param.seg.editor + // [pa, ta] = partarray(parts); + // parts = editorssearch(pa, ta, parts); + // parts = [parts, nullpart(parts,1:nBeat)]; + // end + // ------------------------------------------------------------------ + + return parts; +} + + + +void songSegmentChroma(Vamp::Plugin::FeatureList quatisedChromagram, vector<Part> &parts) +{ + // Collect Info + int nBeat = quatisedChromagram.size(); // Number of feature vector + int nFeatValues = quatisedChromagram[0].values.size(); // Number of values for each feature vector + + arma::mat synchTreble = arma::zeros<mat>(nBeat,nFeatValues/2); + + for (unsigned i = 0; i < nBeat; ++ i) + for (unsigned j = 0; j < nFeatValues/2; ++ j) + { + synchTreble(i,j) = quatisedChromagram[i].values[j]; + } + + arma::mat synchBass = arma::zeros<mat>(nBeat,nFeatValues/2); + + for (unsigned i = 0; i < nBeat; ++ i) + for (unsigned j = 0; j < nFeatValues/2; ++ j) + { + synchBass(i,j) = quatisedChromagram[i].values[j+12]; + } + + // Process + + arma::mat segTreble = arma::zeros<arma::mat>(quatisedChromagram.size(),quatisedChromagram[0].values.size()/2); + arma::mat segBass = arma::zeros<arma::mat>(quatisedChromagram.size(),quatisedChromagram[0].values.size()/2); + + for (unsigned iPart=0; iPart<parts.size(); ++iPart) + { + parts[iPart].nInd = parts[iPart].indices.size(); + + for (unsigned kOccur=0; kOccur<parts[iPart].nInd; ++kOccur) + { + int kStartIndex = parts[iPart].indices[kOccur]; + int kEndIndex = kStartIndex + parts[iPart].n-1; + + segTreble.rows(kStartIndex,kEndIndex) = segTreble.rows(kStartIndex,kEndIndex) + synchTreble.rows(kStartIndex,kEndIndex); + segBass.rows(kStartIndex,kEndIndex) = segBass.rows(kStartIndex,kEndIndex) + synchBass.rows(kStartIndex,kEndIndex); + } + } +} + + +// Segment Integration +vector<Part> songSegmentIntegration(vector<Part> &parts) +{ + // Break up parts (every part will have one instance) + vector<Part> newPartVector; + vector<int> partindices; + + for (unsigned iPart=0; iPart<parts.size(); ++iPart) + { + parts[iPart].nInd = parts[iPart].indices.size(); + for (unsigned iInstance=0; iInstance<parts[iPart].nInd; ++iInstance) + { + Part newPart; + newPart.n = parts[iPart].n; + newPart.letter = parts[iPart].letter; + newPart.value = parts[iPart].value; + newPart.level = parts[iPart].level; + newPart.indices.push_back(parts[iPart].indices[iInstance]); + newPart.nInd = 1; + partindices.push_back(parts[iPart].indices[iInstance]); + + newPartVector.push_back(newPart); + } + } + + + // Sort the parts in order of occurrence + sort (partindices.begin(), partindices.end()); + + for (unsigned i=0; i<partindices.size(); ++i) + { + bool found = false; + int in=0; + while (!found) + { + if (newPartVector[in].indices[0] == partindices[i]) + { + newPartVector.push_back(newPartVector[in]); + newPartVector.erase(newPartVector.begin()+in); + found = true; + } + else + in++; + } + } + + // Clear the vector + for (unsigned iNewpart=1; iNewpart < newPartVector.size(); ++iNewpart) + { + if (newPartVector[iNewpart].n < 12) + { + newPartVector[iNewpart-1].n = newPartVector[iNewpart-1].n + newPartVector[iNewpart].n; + newPartVector.erase(newPartVector.begin()+iNewpart); + } + } + + return newPartVector; +} + +// Segmenter +Vamp::Plugin::FeatureList SongPartitioner::Segmenter(Vamp::Plugin::FeatureList quatisedChromagram) +{ + /* --- Display Information --- */ + int numBeat = quatisedChromagram.size(); + int numFeats = quatisedChromagram[0].values.size(); + + vector<Part> parts; + vector<Part> finalParts; + + parts = songSegment(quatisedChromagram); + + songSegmentChroma(quatisedChromagram,parts); + finalParts = songSegmentIntegration(parts); + + + // TEMP ---- + /*for (unsigned i=0;i<finalParts.size(); ++i) + { + std::cout << "Parts n° " << i << std::endl; + std::cout << finalParts[i].n << std::endl; + std::cout << finalParts[i].letter << std::endl; + + for (unsigned j=0;j<finalParts[i].indices.size(); ++j) + std::cout << finalParts[i].indices[j] << std::endl; + std::cout << finalParts[i].level << std::endl; + }*/ + + + // --------- + + + // Output + + Vamp::Plugin::FeatureList results; + + + Feature seg; + + arma::vec indices; + unsigned idx=0; + vector<int> values; + vector<string> letters; + + for (unsigned iPart=0; iPart<finalParts.size()-1; ++iPart) + { + unsigned iInstance=0; + seg.hasTimestamp = true; + + int ind = finalParts[iPart].indices[iInstance]; + int ind1 = finalParts[iPart+1].indices[iInstance]; + + seg.timestamp = quatisedChromagram[ind].timestamp; + seg.hasDuration = true; + seg.duration = quatisedChromagram[ind1].timestamp-quatisedChromagram[ind].timestamp; + seg.values.clear(); + seg.values.push_back(finalParts[iPart].value); + seg.label = finalParts[iPart].letter; + + results.push_back(seg); + } + + int ind = finalParts[finalParts.size()-1].indices[0]; + seg.timestamp = quatisedChromagram[ind].timestamp; + seg.hasDuration = true; + seg.duration = quatisedChromagram[quatisedChromagram.size()-1].timestamp-quatisedChromagram[ind].timestamp; + seg.values.clear(); + seg.values.push_back(finalParts[finalParts.size()-1].value); + seg.label = finalParts[finalParts.size()-1].letter; + + results.push_back(seg); + + return results; +} + + + + + + + + + + + + + + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/SongParts.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,80 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _SONG_PARTS_PLUGIN_H_ +#define _SONG_PARTS_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> + +class BeatTrackerData; + +class ChromaData; + +class SongPartitioner : public Vamp::Plugin +{ +public: + SongPartitioner(float inputSampleRate); + virtual ~SongPartitioner(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const { return TimeDomain; } + + 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: + BeatTrackerData *m_d; + ChromaData *m_chromadata; + static float m_stepSecs; + static size_t m_chromaFramesizeFactor; + static size_t m_chromaStepsizeFactor; + int m_bpb; + int m_pluginFrameCount; + FeatureSet BeatTrack(); + FeatureList ChromaFeatures(); + std::vector<FeatureList> BeatQuantiser(FeatureList chromagram, FeatureList beats); + FeatureList Segmenter(FeatureList quatisedChromagram); + + mutable int m_beatOutputNumber; + mutable int m_barsOutputNumber; + mutable int m_beatcountsOutputNumber; + mutable int m_beatsdOutputNumber; + mutable int m_logscalespecOutputNumber; + mutable int m_bothchromaOutputNumber; + mutable int m_qchromafwOutputNumber; + mutable int m_qchromaOutputNumber; + mutable int m_segmOutputNumber; + +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/SongParts/BeatTrackerData.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,94 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +//#include "SongParts.h" + +#include "BeatTrackerData.h" + +//#include <base/Window.h> +#include <dsp/onsets/DetectionFunction.h> +//#include <dsp/onsets/PeakPicking.h> +//#include <dsp/transforms/FFT.h> +//#include <dsp/tempotracking/TempoTrackV2.h> +//#include <dsp/tempotracking/DownBeat.h> +//#include <chromamethods.h> +//#include <maths/MathUtilities.h> + +// #include <vamp-sdk/Plugin.h> + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + + +//#ifndef __GNUC__ +//#include <alloca.h> +//#endif + + +/* ------------------------------------ */ +/* ----- BEAT DETECTOR CLASS ---------- */ +/* ------------------------------------ */ + + +/* --- ATTRIBUTES --- */ +private: +DFConfig dfConfig; +DetectionFunction *df; +DownBeat *downBeat; +vector<double> dfOutput; +Vamp::RealTime origin; + + +/* --- METHODS --- */ + +/* --- Constructor --- */ +public: +BeatTrackerData(float rate, const DFConfig &config) : dfConfig(config) { + + df = new DetectionFunction(config); + // decimation factor aims at resampling to c. 3KHz; must be power of 2 + int factor = MathUtilities::nextPowerOfTwo(rate / 3000); + // std::cerr << "BeatTrackerData: factor = " << factor << std::endl; + downBeat = new DownBeat(rate, factor, config.stepSize); +} + +/* --- Desctructor --- */ +~BeatTrackerData() { +delete df; + delete downBeat; +} + +void reset() { + delete df; + df = new DetectionFunction(dfConfig); + dfOutput.clear(); + downBeat->resetAudioBuffer(); + origin = Vamp::RealTime::zeroTime; +} + +/* --- Getter Methods ---*/ +DFConfig getdfConfig(){ +return dfConfig; +} + + + + + + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/SongParts/BeatTrackerData.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,25 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + + +#include <dsp/onsets/DetectionFunction.h> + + +class BeatTrackerData +{ +public: + BeatTrackerData(float rate, const DFConfig &config); + virtual ~BeatTrackerData(); + void reset(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/TonalChangeDetect.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,443 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "TonalChangeDetect.h" + +#include <base/Pitch.h> +#include <dsp/chromagram/Chromagram.h> +#include <dsp/tonal/ChangeDetectionFunction.h> + +TonalChangeDetect::TonalChangeDetect(float fInputSampleRate) + : Vamp::Plugin(fInputSampleRate), + m_chromagram(0), + m_step(0), + m_block(0), + m_stepDelay(0), + m_origin(Vamp::RealTime::zeroTime), + m_haveOrigin(false) +{ + m_minMIDIPitch = 32; + m_maxMIDIPitch = 108; + m_tuningFrequency = 440; + m_iSmoothingWidth = 5; + + setupConfig(); +} + +TonalChangeDetect::~TonalChangeDetect() +{ +} + +bool TonalChangeDetect::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (m_chromagram) { + delete m_chromagram; + m_chromagram = 0; + } + + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) { + std::cerr << "TonalChangeDetect::initialise: Given channel count " << channels << " outside acceptable range (" << getMinChannelCount() << " to " << getMaxChannelCount() << ")" << std::endl; + return false; + } + + m_chromagram = new Chromagram(m_config); + m_step = m_chromagram->getHopSize(); + m_block = m_chromagram->getFrameSize(); + + if (stepSize != m_step) { + std::cerr << "TonalChangeDetect::initialise: Given step size " << stepSize << " differs from only acceptable value " << m_step << std::endl; + delete m_chromagram; + m_chromagram = 0; + return false; + } + if (blockSize != m_block) { + std::cerr << "TonalChangeDetect::initialise: Given step size " << stepSize << " differs from only acceptable value " << m_step << std::endl; + delete m_chromagram; + m_chromagram = 0; + return false; + } + + // m_stepDelay = (blockSize - stepSize) / 2; + // m_stepDelay = m_stepDelay / stepSize; + m_stepDelay = (blockSize - stepSize) / stepSize; //!!! why? seems about right to look at, but... + +// std::cerr << "TonalChangeDetect::initialise: step " << stepSize << ", block " +// << blockSize << ", delay " << m_stepDelay << std::endl; + + m_vaCurrentVector.resize(12, 0.0); + + return true; + +} + +std::string TonalChangeDetect::getIdentifier() const +{ + return "qm-tonalchange"; +} + +std::string TonalChangeDetect::getName() const +{ + return "Tonal Change"; +} + +std::string TonalChangeDetect::getDescription() const +{ + return "Detect and return the positions of harmonic changes such as chord boundaries"; +} + +std::string TonalChangeDetect::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int TonalChangeDetect::getPluginVersion() const +{ + return 2; +} + +std::string TonalChangeDetect::getCopyright() const +{ + return "Plugin by Martin Gasser and Christopher Harte. Copyright (c) 2006-2009 QMUL - All Rights Reserved"; +} + +TonalChangeDetect::ParameterList TonalChangeDetect::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + desc.identifier = "smoothingwidth"; + desc.name = "Gaussian smoothing"; + desc.description = "Window length for the internal smoothing operation, in chroma analysis frames"; + desc.unit = "frames"; + desc.minValue = 0; + desc.maxValue = 20; + desc.defaultValue = 5; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "minpitch"; + desc.name = "Chromagram minimum pitch"; + desc.unit = "MIDI units"; + desc.description = "Lowest pitch in MIDI units to be included in the chroma analysis"; + desc.minValue = 0; + desc.maxValue = 127; + desc.defaultValue = 32; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "maxpitch"; + desc.name = "Chromagram maximum pitch"; + desc.unit = "MIDI units"; + desc.description = "Highest pitch in MIDI units to be included in the chroma analysis"; + desc.minValue = 0; + desc.maxValue = 127; + desc.defaultValue = 108; + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "tuning"; + desc.name = "Chromagram tuning frequency"; + desc.unit = "Hz"; + desc.description = "Frequency of concert A in the music under analysis"; + desc.minValue = 420; + desc.maxValue = 460; + desc.defaultValue = 440; + desc.isQuantized = false; + list.push_back(desc); + + return list; +} + +float +TonalChangeDetect::getParameter(std::string param) const +{ + if (param == "smoothingwidth") { + return m_iSmoothingWidth; + } + if (param == "minpitch") { + return m_minMIDIPitch; + } + if (param == "maxpitch") { + return m_maxMIDIPitch; + } + if (param == "tuning") { + return m_tuningFrequency; + } + + std::cerr << "WARNING: ChromagramPlugin::getParameter: unknown parameter \"" + << param << "\"" << std::endl; + return 0.0; +} + +void +TonalChangeDetect::setParameter(std::string param, float value) +{ + if (param == "minpitch") { + m_minMIDIPitch = lrintf(value); + } else if (param == "maxpitch") { + m_maxMIDIPitch = lrintf(value); + } else if (param == "tuning") { + m_tuningFrequency = value; + } + else if (param == "smoothingwidth") { + m_iSmoothingWidth = int(value); + } else { + std::cerr << "WARNING: ChromagramPlugin::setParameter: unknown parameter \"" + << param << "\"" << std::endl; + } + + setupConfig(); +} + + +void TonalChangeDetect::setupConfig() +{ + m_config.FS = lrintf(m_inputSampleRate); + m_config.min = Pitch::getFrequencyForPitch + (m_minMIDIPitch, 0, m_tuningFrequency); + m_config.max = Pitch::getFrequencyForPitch + (m_maxMIDIPitch, 0, m_tuningFrequency); + m_config.BPO = 12; + m_config.CQThresh = 0.0054; + m_config.normalise = MathUtilities::NormaliseNone; + + m_step = 0; + m_block = 0; + + +} + +void +TonalChangeDetect::reset() +{ + if (m_chromagram) { + delete m_chromagram; + m_chromagram = new Chromagram(m_config); + } + while (!m_pending.empty()) m_pending.pop(); + + m_vaCurrentVector.clear(); + + m_origin = Vamp::RealTime::zeroTime; + m_haveOrigin = false; +} + +size_t +TonalChangeDetect::getPreferredStepSize() const +{ + if (!m_step) { + Chromagram chroma(m_config); + m_step = chroma.getHopSize(); + m_block = chroma.getFrameSize(); + } + + return m_step; +} + +size_t +TonalChangeDetect::getPreferredBlockSize() const +{ + if (!m_step) { + Chromagram chroma(m_config); + m_step = chroma.getHopSize(); + m_block = chroma.getFrameSize(); + } + + return m_block; +} + +TonalChangeDetect::OutputList TonalChangeDetect::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor hc; + hc.identifier = "tcstransform"; + hc.name = "Transform to 6D Tonal Content Space"; + hc.unit = ""; + hc.description = "Representation of content in a six-dimensional tonal space"; + hc.hasFixedBinCount = true; + hc.binCount = 6; + hc.hasKnownExtents = true; + hc.minValue = -1.0; + hc.maxValue = 1.0; + hc.isQuantized = false; + hc.sampleType = OutputDescriptor::OneSamplePerStep; + + OutputDescriptor d; + d.identifier = "tcfunction"; + d.name = "Tonal Change Detection Function"; + d.unit = ""; + d.description = "Estimate of the likelihood of a tonal change occurring within each spectral frame"; + d.minValue = 0; + d.minValue = 2; + d.hasFixedBinCount = true; + d.binCount = 1; + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::VariableSampleRate; + double dStepSecs = double(getPreferredStepSize()) / m_inputSampleRate; + d.sampleRate = 1.0f / dStepSecs; + + OutputDescriptor changes; + changes.identifier = "changepositions"; + changes.name = "Tonal Change Positions"; + changes.unit = ""; + changes.description = "Estimated locations of tonal changes"; + changes.hasFixedBinCount = true; + changes.binCount = 0; + changes.hasKnownExtents = false; + changes.isQuantized = false; + changes.sampleType = OutputDescriptor::VariableSampleRate; + changes.sampleRate = 1.0 / dStepSecs; + + list.push_back(hc); + list.push_back(d); + list.push_back(changes); + + return list; +} + +TonalChangeDetect::FeatureSet +TonalChangeDetect::process(const float *const *inputBuffers, + Vamp::RealTime timestamp) +{ + if (!m_chromagram) { + cerr << "ERROR: TonalChangeDetect::process: " + << "Chromagram has not been initialised" + << endl; + return FeatureSet(); + } + + if (!m_haveOrigin) m_origin = timestamp; + + // convert float* to double* + double *tempBuffer = new double[m_block]; + for (size_t i = 0; i < m_block; ++i) { + tempBuffer[i] = inputBuffers[0][i]; + } + + double *output = m_chromagram->process(tempBuffer); + delete[] tempBuffer; + + for (size_t i = 0; i < 12; i++) + { + m_vaCurrentVector[i] = output[i]; + } + + + FeatureSet returnFeatures; + + if (m_stepDelay == 0) { + m_vaCurrentVector.normalizeL1(); + TCSVector tcsVector = m_TonalEstimator.transform2TCS(m_vaCurrentVector); + m_TCSGram.addTCSVector(tcsVector); + + Feature feature; + feature.hasTimestamp = false; + for (int i = 0; i < 6; i++) + { feature.values.push_back(static_cast<float>(tcsVector[i])); } + feature.label = ""; + returnFeatures[0].push_back(feature); + + return returnFeatures; + } + + if (m_pending.size() == m_stepDelay) { + + ChromaVector v = m_pending.front(); + v.normalizeL1(); + TCSVector tcsVector = m_TonalEstimator.transform2TCS(v); + m_TCSGram.addTCSVector(tcsVector); + + Feature feature; + feature.hasTimestamp = false; + for (int i = 0; i < 6; i++) + { feature.values.push_back(static_cast<float>(tcsVector[i])); } + feature.label = ""; + returnFeatures[0].push_back(feature); + m_pending.pop(); + + } else { + returnFeatures[0].push_back(Feature()); + m_TCSGram.addTCSVector(TCSVector()); + } + + m_pending.push(m_vaCurrentVector); + + + return returnFeatures; +} + +TonalChangeDetect::FeatureSet TonalChangeDetect::getRemainingFeatures() +{ + FeatureSet returnFeatures; + + while (!m_pending.empty()) { + ChromaVector v = m_pending.front(); + v.normalizeL1(); + TCSVector tcsVector = m_TonalEstimator.transform2TCS(v); + m_TCSGram.addTCSVector(tcsVector); + + Feature feature; + feature.hasTimestamp = false; + for (int i = 0; i < 6; i++) + { feature.values.push_back(static_cast<float>(tcsVector[i])); } + feature.label = ""; + returnFeatures[0].push_back(feature); + m_pending.pop(); + } + + ChangeDFConfig dfc; + dfc.smoothingWidth = double(m_iSmoothingWidth); + ChangeDetectionFunction df(dfc); + ChangeDistance d = df.process(m_TCSGram); + + + + for (int i = 0; i < d.size(); i++) + { + double dCurrent = d[i]; + double dPrevious = d[i > 0 ? i - 1 : i]; + double dNext = d[i < d.size()-1 ? i + 1 : i]; + + Feature feature; + feature.label = ""; + feature.hasTimestamp = true; + feature.timestamp = m_origin + + Vamp::RealTime::frame2RealTime(i*m_step, m_inputSampleRate); + feature.values.push_back(dCurrent); + returnFeatures[1].push_back(feature); + + + if (dCurrent > dPrevious && dCurrent > dNext) + { + Feature featurePeak; + featurePeak.label = ""; + featurePeak.hasTimestamp = true; + featurePeak.timestamp = m_origin + + Vamp::RealTime::frame2RealTime(i*m_step, m_inputSampleRate); + returnFeatures[2].push_back(featurePeak); + } + + } + + + return returnFeatures; + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/TonalChangeDetect.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,84 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _TONALCHANGEDETECT_ +#define _TONALCHANGEDETECT_ + +#include <vamp-sdk/Plugin.h> + +#include <dsp/chromagram/Chromagram.h> +#include <dsp/tonal/TonalEstimator.h> +#include <dsp/tonal/TCSgram.h> + +#include <queue> +#include <vector> +#include <valarray> + +class TonalChangeDetect : public Vamp::Plugin +{ +public: + TonalChangeDetect(float fInputSampleRate); + virtual ~TonalChangeDetect(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const { return TimeDomain; } + + 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(); + +private: + void setupConfig(); + + ChromaConfig m_config; + Chromagram *m_chromagram; + TonalEstimator m_TonalEstimator; + mutable size_t m_step; + mutable size_t m_block; + size_t m_stepDelay; + std::queue<ChromaVector> m_pending; + ChromaVector m_vaCurrentVector; + TCSGram m_TCSGram; + + int m_iSmoothingWidth; // smoothing window size + int m_minMIDIPitch; // chromagram parameters + int m_maxMIDIPitch; + float m_tuningFrequency; + + Vamp::RealTime m_origin; + bool m_haveOrigin; +}; + + +#endif // _TONALCHANGEDETECT_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/Transcription.cpp Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,2117 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + QM Vamp Plugin Set + + Centre for Digital Music, Queen Mary, University of London. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +/*transcription vamp plugin: Ruohua Zhou, Josh Reiss, josh.reiss@elec.qmul.ac.uk */ + +#include "Transcription.h" +#include <vamp-sdk/PluginAdapter.h> +#include <math.h> +#include <stdlib.h> + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + +const double CNum[8] = { + 3.025328153863e-005,0.0002117729707704,0.0006353189123113, 0.001058864853852, + 0.001058864853852,0.0006353189123113,0.0002117729707704,3.025328153863e-005 +}; + +const double CDen[8] = { + 1, -4.647847898799, 9.540784706769, -11.14354542746, + 7.967285533211, -3.477244449085, 0.8559660579522, -0.09152610255505 +}; + +const int A[10] = {0, 120, 190, 240, 279, 310, 337, 360, 380, 399}; + + + +const double EualCurve960[960] = { + 83.750025,83.532690,83.315770,83.099260,82.883159,82.667463,82.452170,82.237276,82.022779,81.808675, + 81.594963,81.381639,81.168699,80.956142,80.743964,80.532163,80.320735,80.109677,79.898987,79.688663,79.478700,79.269096,79.059848,78.850953, + 78.642408,78.434211,78.226359,78.018848,77.811676,77.604839,77.398336,77.192162,76.986316,76.780794,76.575593,76.370710,76.166143,75.961889, + 75.757945,75.554307,75.350973,75.147940,74.945205,74.742766,74.540618,74.338761,74.137189,73.935902,73.734895,73.534166,73.333712,73.133529, + 72.933616,72.733970,72.534586,72.335463,72.136598,71.937987,71.739628,71.541517,71.343653,71.146032,70.948650,70.751506,70.554597,70.357919, + 70.161469,69.965245,69.769244,69.573462,69.377898,69.182548,68.987408,68.792477,68.597752,68.403228,68.208905,68.014781,67.820873,67.627197, + 67.433772,67.240617,67.047749,66.855187,66.662949,66.471053,66.279516,66.088358,65.897597,65.707250,65.517336,65.327873,65.138879,64.950373, + 64.762372,64.574894,64.387959,64.201583,64.015785,63.830584,63.645997,63.462043,63.278739,63.096105,62.914158,62.732915,62.552397,62.372620, + 62.193602,62.015363,61.837920,61.661291,61.485494,61.310549,61.136471,60.963274,60.790941,60.619447,60.448770,60.278885,60.109770,59.941401, + 59.773755,59.606807,59.440536,59.274916,59.109924,58.945538,58.781733,58.618486,58.455773,58.293572,58.131858,57.970608,57.809799,57.649407, + 57.489408,57.329780,57.170498,57.011539,56.852880,56.694496,56.536366,56.378464,56.220768,56.063255,55.905900,55.748680,55.591571,55.434551, + 55.277595,55.120681,54.963784,54.806886,54.649983,54.493077,54.336169,54.179261,54.022353,53.865448,53.708546,53.551650,53.394759,53.237877, + 53.081003,52.924139,52.767287,52.610448,52.453624,52.296815,52.140023,51.983250,51.826496,51.669763,51.513053,51.356366,51.199705,51.043070, + 50.886463,50.729885,50.573337,50.416821,50.260338,50.103890,49.947478,49.791103,49.634766,49.478469,49.322214,49.166001,49.009832,48.853710, + 48.697648,48.541659,48.385757,48.229958,48.074273,47.918719,47.763308,47.608055,47.452974,47.298080,47.143385,46.988904,46.834652,46.680642, + 46.526889,46.373405,46.220207,46.067307,45.914720,45.762460,45.610540,45.458976,45.307780,45.156968,45.006553,44.856549,44.706971,44.557832, + 44.409146,44.260928,44.113192,43.965951,43.819220,43.673013,43.527344,43.382227,43.237676,43.093703,42.950305,42.807478,42.665218,42.523520, + 42.382381,42.241794,42.101757,41.962264,41.823311,41.684894,41.547008,41.409648,41.272811,41.136491,41.000685,40.865387,40.730594,40.596301, + 40.462503,40.329195,40.196375,40.064036,39.932175,39.800787,39.669867,39.539412,39.409417,39.279876,39.150787,39.022143,38.893942,38.766178, + 38.638846,38.511944,38.385465,38.259405,38.133761,38.008525,37.883679,37.759203,37.635076,37.511278,37.387789,37.264588,37.141656,37.018971, + 36.896513,36.774262,36.652197,36.530298,36.408545,36.286918,36.165395,36.043957,35.922583,35.801253,35.679947,35.558643,35.437322,35.315964, + 35.194547,35.073052,34.951458,34.829745,34.707892,34.585879,34.463686,34.341293,34.218678,34.095822,33.972704,33.849303,33.725600,33.601574, + 33.477205,33.352481,33.227425,33.102069,32.976445,32.850585,32.724520,32.598284,32.471906,32.345420,32.218858,32.092250,31.965629,31.839028, + 31.712477,31.586009,31.459655,31.333448,31.207419,31.081601,30.956024,30.830722,30.705725,30.581067,30.456777,30.332890,30.209436,30.086447, + 29.963955,29.841993,29.720591,29.599783,29.479599,29.360071,29.241233,29.123114,29.005748,28.889166,28.773400,28.658474,28.544378,28.431095, + 28.318607,28.206897,28.095947,27.985740,27.876257,27.767481,27.659396,27.551982,27.445224,27.339102,27.233599,27.128699,27.024383,26.920633, + 26.817433,26.714764,26.612609,26.510951,26.409772,26.309053,26.208779,26.108930,26.009491,25.910442,25.811766,25.713446,25.615465,25.517804, + 25.420446,25.323374,25.226570,25.130016,25.033695,24.937589,24.841681,24.745955,24.650409,24.555043,24.459856,24.364847,24.270016,24.175363, + 24.080887,23.986588,23.892466,23.798520,23.704751,23.611156,23.517737,23.424492,23.331422,23.238526,23.145803,23.053253,22.960877,22.868672, + 22.776640,22.684779,22.593090,22.501572,22.410224,22.319046,22.228038,22.137200,22.046530,21.956029,21.865697,21.775532,21.685535,21.595704, + 21.506041,21.416544,21.327213,21.238047,21.149047,21.060211,20.971540,20.883034,20.794691,20.706512,20.618496,20.530642,20.442952,20.355423, + 20.268057,20.180852,20.093808,20.006925,19.920202,19.833640,19.747237,19.660994,19.574910,19.488985,19.403218,19.317610,19.232159,19.146866, + 19.061729,18.976750,18.891927,18.807260,18.722749,18.638393,18.554193,18.470147,18.386255,18.302518,18.218934,18.135504,18.052227,17.969105, + 17.886151,17.803379,17.720805,17.638444,17.556310,17.474419,17.392786,17.311425,17.230351,17.149581,17.069127,16.989007,16.909233,16.829822, + 16.750789,16.672148,16.593914,16.516103,16.438729,16.361808,16.285354,16.209382,16.133907,16.058945,15.984510,15.910617,15.837282,15.764518, + 15.692342,15.620768,15.549811,15.479486,15.409809,15.340793,15.272455,15.204808,15.137869,15.071646,15.006129,14.941300,14.877144,14.813643, + 14.750781,14.688540,14.626906,14.565860,14.505386,14.445467,14.386088,14.327231,14.268879,14.211016,14.153626,14.096691,14.040195,13.984121, + 13.928453,13.873174,13.818267,13.763716,13.709504,13.655615,13.602031,13.548736,13.495714,13.442948,13.390420,13.338115,13.286016,13.234107, + 13.182369,13.130788,13.079346,13.028026,12.976813,12.925693,12.874671,12.823756,12.772958,12.722285,12.671746,12.621351,12.571107,12.521025, + 12.471113,12.421380,12.371835,12.322488,12.273346,12.224419,12.175717,12.127248,12.079020,12.031044,11.983328,11.935880,11.888711,11.841828, + 11.795242,11.748960,11.702993,11.657348,11.612035,11.567063,11.522441,11.478178,11.434282,11.390764,11.347631,11.304893,11.262558,11.220637, + 11.179137,11.138068,11.097437,11.057252,11.017521,10.978252,10.939452,10.901129,10.863290,10.825944,10.789098,10.752760,10.716937,10.681638, + 10.646869,10.612640,10.578956,10.545827,10.513259,10.481261,10.449840,10.419004,10.388760,10.359117,10.330082,10.301663,10.273867,10.246702, + 10.220176,10.194296,10.169071,10.144508,10.120615,10.097399,10.074868,10.053030,10.031892,10.011463,9.991749,9.972762,9.954523,9.937056,9.920385, + 9.904534,9.889527,9.875389,9.862144,9.849815,9.838428,9.828005,9.818572,9.810152,9.802770,9.796449,9.791214,9.787089,9.784099,9.782266,9.781616, + 9.782172,9.783959,9.787001,9.791322,9.796946,9.803897,9.812200,9.821878,9.832956,9.845457,9.859407,9.874829,9.891747,9.910185,9.930168,9.951720, + 9.974864,9.999625,10.026008,10.053933,10.083304,10.114023,10.145991,10.179112,10.213287,10.248419,10.284410,10.321161,10.358576,10.396556,10.435004, + 10.473821,10.512911,10.552175,10.591516,10.630835,10.670035,10.709018,10.747686,10.785942,10.823688,10.860826,10.897258,10.932886,10.967613,11.001341, + 11.033972,11.065408,11.095552,11.124305,11.151570,11.177249,11.201245,11.223459,11.243793,11.262151,11.278450,11.292676,11.304827,11.314906,11.322913, + 11.328848,11.332713,11.334508,11.334233,11.331889,11.327477,11.320998,11.312453,11.301841,11.289164,11.274422,11.257616,11.238747,11.217816,11.194822, + 11.169767,11.142652,11.113476,11.082241,11.048948,11.013597,10.976189,10.936724,10.895203,10.851627,10.805996,10.758312,10.708574,10.656784,10.602942, + 10.547049,10.489106,10.429113,10.367082,10.303073,10.237155,10.169399,10.099876,10.028655,9.955807,9.881403,9.805512,9.728206,9.649554,9.569627,9.488495, + 9.406228,9.322897,9.238573,9.153325,9.067225,8.980341,8.892745,8.804508,8.715698,8.626388,8.536646,8.446544,8.356152,8.265539,8.174778,8.083937,7.993087, + 7.902299,7.811643,7.721190,7.631008,7.541170,7.451746,7.362804,7.274417,7.186644,7.099504,7.013003,6.927151,6.841956,6.757424,6.673565,6.590385,6.507894, + 6.426099,6.345008,6.264629,6.184970,6.106039,6.027843,5.950392,5.873692,5.797752,5.722579,5.648183,5.574570,5.501748,5.429727,5.358512,5.288114,5.218538, + 5.149794,5.081890,5.014832,4.948630,4.883292,4.818824,4.755236,4.692535,4.630729,4.569826,4.509834,4.450761,4.392616,4.335415,4.279172,4.223905,4.169630, + 4.116362,4.064118,4.012914,3.962766,3.913691,3.865703,3.818820,3.773058,3.728432,3.684960,3.642656,3.601538,3.561621,3.522921,3.485455,3.449239,3.414289, + 3.380620,3.348250,3.317194,3.287469,3.259090,3.232074,3.206437,3.182194,3.159363,3.137959,3.117999,3.099498,3.082473,3.066939,3.052914,3.040413,3.029451, + 3.020039,3.012186,3.005904,3.001201,2.998087,2.996571,2.996665,2.998377,3.001718,3.006696,3.013323,3.021607,3.031559,3.043187,3.056503,3.071516,3.088235, + 3.106671,3.126833,3.148731,3.172374,3.197773,3.224938,3.253877,3.284601,3.317120,3.351444,3.387581,3.425543,3.465339,3.506978,3.550470,3.595826,3.643054, + 3.692166,3.743169,3.796075,3.850896,3.907655,3.966377,4.027088,4.089815,4.154581,4.221415,4.290340,4.361382,4.434569,4.509924,4.587474,4.667245,4.749261, + 4.833550,4.920136,5.009046,5.100305,5.193938,5.289972,5.388432,5.489343,5.592732,5.698625,5.807046,5.918022,6.031578,6.147741,6.266535,6.387986,6.512121, + 6.638964,6.768542,6.900880,7.036004,7.173939,7.314712,7.458348,7.604856,7.754175,7.906227,8.060936,8.218223,8.378012,8.540225,8.704784,8.871612,9.040631, + 9.211765,9.384934,9.560063,9.737073,9.915888,10.096429,10.278619,10.462380,10.647636,10.834309,11.022321,11.211594,11.402052,11.593616,11.786210,11.979755, + 12.174175,12.369392,12.565329,12.761907,12.959049,13.156679,13.354718,13.553089,13.751715,13.950518,14.149420,14.348345,14.547211,14.745925,14.944391, + 15.142512,15.340191,15.537333,15.733840,15.929615,16.124564 +}; +void Transcribe(int Len,int inputLen,double *SoundIn,double *out,double *outArray2,double *outArray3,double SampleRate); + +Transcription::Transcription(float inputSampleRate) : + Plugin(inputSampleRate), + m_stepSize(0) +{ + m_SoundIn=0; + m_SampleN=0; + m_AllocN = 0; + m_Excess = false; +} + +Transcription::~Transcription() +{ + free(m_SoundIn); +} + +string +Transcription::getIdentifier() const +{ + return "qm-transcription"; +} + +string +Transcription::getName() const +{ + return "Polyphonic Transcription"; +} + +string +Transcription::getDescription() const +{ + return "Transcribe the input audio to estimated notes"; +} + +string +Transcription::getMaker() const +{ + return "Queen Mary, University of London"; +} + +int +Transcription::getPluginVersion() const +{ + return 1; +} + +string +Transcription::getCopyright() const +{ + return "Plugin by Dr. Ruohua Zhou. Copyright (c) 2008-2009 QMUL - All Rights Reserved"; +} + +size_t +Transcription::getPreferredStepSize() const +{ + return 441; +} + +size_t +Transcription::getPreferredBlockSize() const +{ + return 441; +} + +bool +Transcription::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) return false; + + if (m_inputSampleRate < 4410 || m_inputSampleRate > 441000) return false; + + m_stepSize = std::min(stepSize, blockSize); + m_blockSize=blockSize; + + m_SampleN = 0; + + return true; +} + +void +Transcription::reset() +{ + free(m_SoundIn); + m_SoundIn = 0; + m_SampleN = 0; + m_AllocN = 0; + m_Excess = false; + m_Base = Vamp::RealTime(); +} + +Transcription::OutputList +Transcription::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor zc; + zc.identifier = "transcription"; + zc.name = "Transcription"; + zc.description = "Estimated note pitch (MIDI note number from 0 to 127)"; + zc.unit = "MIDI units"; + zc.hasFixedBinCount = true; + zc.binCount = 1; + zc.hasKnownExtents = true; + zc.minValue = 0; + zc.maxValue = 127; + zc.isQuantized = true; + zc.quantizeStep = 1.0; + zc.hasDuration = true; + zc.sampleType = OutputDescriptor::VariableSampleRate; + +/* no -- this is the result of a confusion between bin indices and values + { + + zc.binNames.push_back("A0");// MIDI Note 21 + zc.binNames.push_back("A0#"); + zc.binNames.push_back("B0"); + zc.binNames.push_back("C1"); + zc.binNames.push_back("C1#"); + zc.binNames.push_back("D1"); + zc.binNames.push_back("D1#"); + zc.binNames.push_back("E1"); + zc.binNames.push_back("F1"); + zc.binNames.push_back("F1#"); + zc.binNames.push_back("G1"); + zc.binNames.push_back("G1#"); + + zc.binNames.push_back("A1");// MIDI Note 33 + zc.binNames.push_back("A1#"); + zc.binNames.push_back("B1"); + zc.binNames.push_back("C2"); + zc.binNames.push_back("C2#"); + zc.binNames.push_back("D2"); + zc.binNames.push_back("D2#"); + zc.binNames.push_back("E2"); + zc.binNames.push_back("F2"); + zc.binNames.push_back("F2#"); + zc.binNames.push_back("G2"); + zc.binNames.push_back("G2#"); + + zc.binNames.push_back("A2");// MIDI Note 45 + zc.binNames.push_back("A2#"); + zc.binNames.push_back("B3"); + zc.binNames.push_back("C3"); + zc.binNames.push_back("C3#"); + zc.binNames.push_back("D3"); + zc.binNames.push_back("D3#"); + zc.binNames.push_back("E3"); + zc.binNames.push_back("F3"); + zc.binNames.push_back("F3#"); + zc.binNames.push_back("G3"); + zc.binNames.push_back("G3#"); + + zc.binNames.push_back("A3");// MIDI Note 57 + zc.binNames.push_back("A3#"); + zc.binNames.push_back("B0"); + zc.binNames.push_back("C4"); + zc.binNames.push_back("C4#"); + zc.binNames.push_back("D4"); + zc.binNames.push_back("D4#"); + zc.binNames.push_back("E4"); + zc.binNames.push_back("F4"); + zc.binNames.push_back("F4#"); + zc.binNames.push_back("G4"); + zc.binNames.push_back("G4#"); + + zc.binNames.push_back("A4");// MIDI Note 69 + zc.binNames.push_back("A4#"); + zc.binNames.push_back("B0"); + zc.binNames.push_back("C5"); + zc.binNames.push_back("C5#"); + zc.binNames.push_back("D5"); + zc.binNames.push_back("D5#"); + zc.binNames.push_back("E5"); + zc.binNames.push_back("F5"); + zc.binNames.push_back("F5#"); + zc.binNames.push_back("G5"); + zc.binNames.push_back("G5#"); + + zc.binNames.push_back("A5");// MIDI Note 85 + zc.binNames.push_back("A5#"); + zc.binNames.push_back("B0"); + zc.binNames.push_back("C6"); + zc.binNames.push_back("C6#"); + zc.binNames.push_back("D6"); + zc.binNames.push_back("D6#"); + zc.binNames.push_back("E6"); + zc.binNames.push_back("F6"); + zc.binNames.push_back("F6#"); + zc.binNames.push_back("G6"); + zc.binNames.push_back("G6#"); + + zc.binNames.push_back("A6");// MIDI Note 93 + zc.binNames.push_back("A6#"); + zc.binNames.push_back("B0"); + zc.binNames.push_back("C7"); + zc.binNames.push_back("C7#"); + zc.binNames.push_back("D7"); + zc.binNames.push_back("D7#"); + zc.binNames.push_back("E7"); + zc.binNames.push_back("F7"); + zc.binNames.push_back("F7#"); + zc.binNames.push_back("G7"); + zc.binNames.push_back("G7#"); + + zc.binNames.push_back("A7");// MIDI Note 105 + zc.binNames.push_back("A7#"); + zc.binNames.push_back("B0"); + zc.binNames.push_back("C8"); + } +*/ + + list.push_back(zc); + +/* zc.identifier = "Transcriptions"; + zc.name = "Polyphonic Transcription"; + zc.description = "Polyphonic Music Transcription"; + zc.unit = ""; + zc.hasFixedBinCount = true; + zc.binCount = 0; + zc.sampleType = OutputDescriptor::VariableSampleRate; + zc.sampleRate = m_inputSampleRate; + list.push_back(zc);*/ + + return list; +} + +Transcription::FeatureSet +Transcription::process(const float *const *inputBuffers, + Vamp::RealTime timestamp) +{ + if (m_stepSize == 0) { + cerr << "ERROR: Transcription::process: " + << "Transcription has not been initialised" + << endl; + return FeatureSet(); + } + + if (m_SampleN == 0) { + m_Base = timestamp; + } + + if (m_Excess) return FeatureSet(); + + for (size_t i = 0; i < m_blockSize;i++) { + + if (m_SampleN >= m_AllocN) { + size_t newsize = m_AllocN * 2; + if (newsize < 10000) newsize = 10000; + double *newbuf = (double *)realloc(m_SoundIn, newsize * sizeof(double)); + if (!newbuf) { + m_Excess = true; + break; + } + m_SoundIn = newbuf; + m_AllocN = newsize; + } + + m_SoundIn[m_SampleN]=inputBuffers[0][i]; + m_SampleN=m_SampleN+1; + } + + return FeatureSet(); +} + +Transcription::FeatureSet +Transcription::getRemainingFeatures() +{ + FeatureSet returnFeatures; + + double * OutArray; + double *OutArray2; + double *hello1; + double *hello2; + int Msec; + size_t i; + size_t j; + size_t n; + size_t count; + + Msec=(int)(100*m_SampleN/m_inputSampleRate); + + if (Msec < 100) return returnFeatures; + + OutArray=(double *)malloc(3*3000*sizeof(double)); + OutArray2=(double *)malloc(88*Msec*sizeof(double)); + hello1=(double *)malloc(112*Msec*sizeof(double)); + hello2=(double *)malloc(112*Msec*sizeof(double)); + + for (j = 0; j <Msec; j++) { + + for(n=0;n<88;n++) + { + + OutArray2[j*88+n]=0; + } + + } + + + Transcribe(Msec,m_SampleN,m_SoundIn,hello1,hello2,OutArray,m_inputSampleRate); + int start; + int endd; + + + /* for (i = 0; i < 3000; i++) { + + if((OutArray[3*i]>0)&&(OutArray[3*i]<88)) + { + start=OutArray[3*i+1];endd=OutArray[3*i+2]; + for(j=start;j<(start+0.05);j=j+0.01) + { + + Feature feature; + Vamp::RealTime ts; + + feature.hasTimestamp = true; + + feature.timestamp =ts.fromSeconds(j); + feature.values.push_back(OutArray[3*i]+21); + returnFeatures[0].push_back(feature); + + } + + + + } + else + { + + break; + } + + + } + + */ + + + for (i = 0; i < 3000; i++) { + + if((OutArray[3*i]>0)&&(OutArray[3*i]<88)) + { + start=100*OutArray[3*i+1]; + endd=100*OutArray[3*i+2]-5; + for(j=start;j<endd;j++) + { + n=OutArray[3*i]; + OutArray2[j*88+n]=OutArray[3*i]; + } + + } + else + { + + break; + } + + + } + + double starts[88]; + for (n = 0; n < 88; ++n) starts[n] = -1.0; + + int nn; + for (j = 0; j <Msec; j++) { + + + for(n=0;n<88;n++) + { + if(OutArray2[j*88+n]>0) + { + + if (starts[n] < 0.) + { + starts[n] = j * 0.01; + } + } + else + { + if (starts[n] > 0.) + { + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_Base + Vamp::RealTime::fromSeconds(starts[n]); + feature.hasDuration = true; + feature.duration = Vamp::RealTime::fromSeconds(j * 0.01 - starts[n]); + feature.values.push_back(n+20); + returnFeatures[0].push_back(feature); + + starts[n] = -1.0; + } + } + } + } + + + for(n=0;n<88;n++) + { + if (starts[n] > 0.) + { + Feature feature; + feature.hasTimestamp = true; + feature.timestamp = m_Base + Vamp::RealTime::fromSeconds(starts[n]); + feature.hasDuration = true; + feature.duration = Vamp::RealTime::fromSeconds(j * 0.01 - starts[n]); + feature.values.push_back(n+20); + returnFeatures[0].push_back(feature); + + starts[n] = -1.0; + } + } + + free(OutArray2); + free(OutArray); + + free(hello1); + free(hello2); + + return returnFeatures; + +} + + + + + +void sofacomplexMex(double *y, double *z, int ncols,double StartNote,double NoteInterval1,double NoteNum,double C,double D,double SR) +{ + int mseconds,i,j,el,count,count2; + double Snote,NoteInterval,NoteN, BasicR; + double *signs; + double *rwork,*buffer; + double freq,R,gain,gainI,gainII,coefI,coefM; + double output,input,outputI,outputM; + double *x; + double *sum,*sum2; + double power; + double temp; + + + //SR=44100; + Snote=StartNote; + NoteInterval=NoteInterval1; + NoteN=NoteNum; + + signs=(double*)malloc((int)NoteN*5*sizeof(double)); + + for (i = 0; i <NoteN; i++) { + + freq=exp((log(2.0))*(Snote+i*NoteInterval-69)/12)*440; + R=exp(-(D+C*freq*2*3.1415926)/(SR*3.1415926)); + gain=(1*(sqrt(1+R*R-2*R*cos(2*freq*2*3.1415926/SR)))-1*R*(sqrt(1+R*R-2*R*cos(2*freq*2*3.1415926/SR))))/sin(freq*2*3.1415926/SR); + gainI=-2*R*cos(freq*2*3.1415926/SR); + gainII =R*R ; + coefI=cos(freq*2*3.1415926/SR); + coefM=sin(freq*2*3.1415926/SR); + + signs[i*5+0]=gain*gain; + signs[i*5+1]=gainI; + signs[i*5+2]=gainII; + signs[i*5+3]=coefI; + signs[i*5+4]=coefM; + + } + + x=(double*)malloc((int)NoteN*2*sizeof(double)); + rwork=(double*)malloc((int)NoteN*sizeof(double)); + sum=(double*)malloc((int)NoteN*sizeof(double)); + sum2=(double*)malloc((int)NoteN*sizeof(double)); + mseconds=(int)(100*ncols/SR); + power=0; + for (i=0;i<mseconds*(int)(SR/100);i++) + { + power=power+y[i]*y[i]; + } + power=sqrt(power); + for(i=0;i<NoteN*2;i++) + x[i]=0; + for (i=0;i<NoteN;i++) + { + sum[i]=0; + sum2[i]=0; + }; + count=0; + count2=0; + for (i=0;i<(mseconds*(int)(SR/100));i++) + { + count=count+1; + input=y[i]; + for(el=0;el<NoteN;el++) + { + output=(input-signs[5*el+1]*x[2*el+0]-signs[5*el+2]*x[2*el+1]); + outputI=output-signs[5*el+3]*x[2*el+0]; + outputM=signs[5*el+4]*x[2*el+0]; + sum[el]=sum[el]+signs[5*el+0]*(outputI*outputI+ outputM*outputM); + rwork[el]=output; + x[el+el+1]=x[el+el+0]; + x[el+el+0]=rwork[el]; + + } + if(count==(int)(SR/100)) + { + for(el=0;el<NoteN;el++) + { + *(z+count2*(int)NoteN+el)=1000000*(sum[el]+sum2[el])/(2*(int)(SR/100))+0.00001; + sum2[el]=sum[el]; + sum[el]=0; + } + count2=count2+1; + count=0; + } + + } + for (i=0;i<NoteN;i++) + { + sum[i]=0; + sum2[i]=0; + }; + for (el=0;el<NoteN;el++) + { + for (i=0;i<mseconds;i++) + { + sum[el]=sum[el]+*(z+i*(int)NoteN+el); + } + + } + + free(x); + free(rwork); + free(sum); + free(sum2); + free(signs); + +} + +void FindMaxN( double *InputArray, int InputLen,int MaxOrder) +{ + int i,j,MaxIndex = 0; + double MaxValue; + double *In2; + + In2=(double*)malloc(InputLen*sizeof(double)); + for (i=0;i<InputLen;i++) + { + In2[i]=InputArray[i]; + InputArray[i]=0; + } + for (i=0;i<MaxOrder;i++) + { + MaxValue=0; + for (j=0;j<InputLen;j++) + { + if(In2[j]>MaxValue) + { + MaxValue=In2[j]; + MaxIndex=j; + } + } + InputArray[MaxIndex]=In2[MaxIndex]; + In2[MaxIndex]=0; + } + + free(In2); +} + +double SumF(double *InputArray,int Start, int End) +{ + double Value; + int i; + Value=0; + for (i=Start;i<(End+1);i++) + { + Value=Value+InputArray[i]; + } + + return Value; + +} + +int round10(int x) +{ + int I,I2; + I=((int)(x/10)); + I2=x-I*10; + + if(I2>5) + return (I+1); + else + return I; + +} + + +void ConToPitch1250(double *In, int InLen) +{ + int i,j,k, nn,col; + double *Out; + const int A[12]={0, 120, 190, 240, 279, 310, 337, 360, 380, 399, 415, 430}; + Out=(double*)malloc(InLen*sizeof(double)); + + + col=InLen; + + for (i=0;i<col;i++) + { + Out[i]=0; + } + + for (i=0;i<col;i++) + { + k=0; + nn=5; + for (j=0;j<nn;j++) + { + if((i+A[j])<col) + { + k=k+1; + Out[i]=Out[i]+In[i+A[j]]; + } + + if((i+A[j])>(col-1)) + { + k=k+1; + Out[i]=Out[i]+In[col-1]; + } + } + if(k>0) + { + Out[i]=Out[i]/k; + } + } + for (i=0;i<col;i++) + { + In[i]=Out[i]; + } + + + free(Out); +} + +void Norm1(double *In, int InLen) +{ + double MaxValue; + int i; + double *Out; + Out=(double*)malloc(InLen*sizeof(double)); + + MaxValue=In[0]; + for (i=1;i<InLen;i++) + { + if(In[i]>MaxValue) + MaxValue=In[i]; + } + + for (i=0;i<InLen;i++) + { + Out[i]=In[i]-MaxValue; + } + + for (i=0;i<InLen;i++) + { + In[i]=Out[i]; + } + + free(Out); +} + +void Smooth(double *In, int InLen,int smoothLen) +{ + double sum; + int i,j,nn,n,count; + double *Out; + Out=(double*)malloc(InLen*sizeof(double)); + nn=InLen; + n=(smoothLen-1)/2; + for (i=0;i<nn;i++) + { + sum=0; + count=0; + for (j=0;j<(n+1);j++) + { + if ((i-j)>-1) + { + sum=sum+In[i-j]; + count=count+1; + } + } + + for (j=1;j<(n+1);j++) + { + if ((i+j)<nn) + { + sum=sum+In[i+j]; + count=count+1; + } + } + Out[i]=sum/count; + } + for (i=0;i<InLen;i++) + In[i]=Out[i]; + + free(Out); +} + + +void FindPeaks(double *In, int InLen,double *Out1,double *Out2, int db, int db2, int db3) +{ + int i,lastout; + for (i=0;i<InLen;i++) + { + Out1[i]=0; + Out2[1]=0; + } + + for (i=20;i<(InLen-20-1);i++) + { + if( /**/ ((In[i]>(db2+In[i-6]))||(In[i]>(db2+In[i+6])) + ||(In[i]>(db3+In[i+20]))||(In[i]>(db3+In[i-20]))) + /*&&(In[i]>db)*/&&(In[i]>In[i+3])&&(In[i]>In[i-3]) + &&(In[i]>In[i+2])&&(In[i]>In[i-2]) + &&(In[i]>In[i+1])&&(In[i]>In[i-1])) + { + Out1[i]=In[i]; + Out2[i]=1; + } + + } + + lastout=1; + for(i=0;i<InLen;i++) + { + + if(Out2[i]==1) + { + if((i-lastout)<5) + { + if(Out1[i]>Out1[lastout]) + { + Out2[lastout]=0; + Out1[lastout]=0; + lastout=i; + } + else + { + Out2[i]=0; + Out1[i]=0; + } + + } + else + { + lastout=i; + } + } + + } + +} + + +void ConFrom1050To960(double *In, double *out, int InputLen) +{ + int i,j; + + for(i=0;i<960;i++) + { + for (j=0;j<InputLen;j++) + { + out[i+j*960]=In[i+j*1050]; + + } + } + + +} + +void Move( double *InputArray, int InputLen,int m) +{ + int i; + double *OutArray; + + OutArray=(double *)malloc(InputLen*sizeof(double)); + for (i=0;i<InputLen;i++) + OutArray[i]=0; + + for (i=0;i<InputLen;i++) + { if(((i+m)>-1)&&((i+m)<InputLen)) + OutArray[i+m]=InputArray[i]; + } + + for (i=0;i<InputLen;i++) + { + InputArray[i]=OutArray[i]; + } + + free(OutArray); +} + + +double SumArray( double *InputArray, int InputHLen, int InputVLen) +{ + int i; + int j; + double sum; + int count; + count=0; + sum=0; + for (j=0;j<InputHLen;j++) + { + for (i=0;i<InputVLen;i++) + { + count=count+1; + sum=sum+InputArray[i+j*InputVLen]; + + } + } + return sum; +} + +double Sum( double *InputArray, int InputHLen) +{ + int i; + double sum; + int count; + count=0; + sum=0; + for (i=0;i<InputHLen;i++) + { + count=count+1; + sum=sum+InputArray[i]; + + } + return sum; +} + +void MeanV2( double *InputArray, int InputHLen, int InputVLen, double *OutArray) +{ + int i; + int j; + double sum; + for (i=0;i<InputVLen;i++) + { + sum=0; + for (j=0;j<InputHLen;j++) + { + + sum=sum+InputArray[i+j*InputVLen]; + + } + OutArray[i]=sum/InputHLen; + } + +} + +void SumV( double *InputArray, int InputHLen, int InputVLen, double *OutArray) +{ + int i; + int j; + double sum; + + for (j=0;j<InputHLen;j++) + { + sum=0; + for (i=0;i<InputVLen;i++) + { + + sum=sum+InputArray[i+j*InputVLen]; + + } + OutArray[j]=sum; + } + +} + + + +void SumV2( double *InputArray, int InputHLen, int InputVLen, double *OutArray) +{ + int i; + int j; + double sum; + for (i=0;i<InputVLen;i++) + { + sum=0; + for (j=0;j<InputHLen;j++) + { + + sum=sum+InputArray[i+j*InputVLen]; + + } + OutArray[i]=sum; + } + +} + +void MaxV( double *InputArray, int InputHLen, int InputVLen, double *OutArray) +{ + int i; + int j; + double MaxVal; + + for (j=0;j<InputHLen;j++) + { + MaxVal=InputArray[j*InputVLen]; + for (i=0;i<InputVLen;i++) + { + if(InputArray[i+j*InputVLen]>MaxVal) + { + MaxVal=InputArray[i+j*InputVLen]; + } + + } + OutArray[j]=MaxVal; + } + +} + +void MaxV2( double *InputArray, int InputHLen, int InputVLen, double *OutArray) +{ + int i; + int j; + double MaxVal; + for (i=0;i<InputVLen;i++) + { + MaxVal=InputArray[i]; + for (j=0;j<InputHLen;j++) + { + if(InputArray[i+j*InputVLen]>MaxVal) + { + MaxVal=InputArray[i+j*InputVLen]; + } + + } + OutArray[i]=MaxVal; + } + +} + + + +void MinArray( double *InputArray, int InputHLen, int InputVLen, double MinValue) +{ + int i; + int j; + + for (i=0;i<InputVLen;i++) + { + for (j=0;j<InputHLen;j++) + { + if(InputArray[i+j*InputVLen]<MinValue) + InputArray[i+j*InputVLen]=MinValue; + + } + + } + +} + + +void MaxArray( double *InputArray, int InputHLen, int InputVLen, double MaxValue) +{ + int i; + int j; + + for (i=0;i<InputVLen;i++) + { + for (j=0;j<InputHLen;j++) + { + if(InputArray[i+j*InputVLen]>MaxValue) + InputArray[i+j*InputVLen]=MaxValue; + + } + + } + +} + +double GetMaxValue( double *InputArray, int InputHLen, int InputVLen) +{ + int i; + int j; + + double MaxValue; + MaxValue=InputArray[0]; + for (i=0;i<InputVLen;i++) + { + for (j=0;j<InputHLen;j++) + { + if(InputArray[i*InputHLen+j]>MaxValue) + MaxValue=InputArray[i*InputHLen+j]; + + } + + } + + return MaxValue; +} + +void RemoveNoise( double *InputArray, int InputHLen, int InputVLen) +{ + int i; + int j; + + for (i=0;i<InputVLen;i++) + { + for (j=0;j<InputHLen;j++) + { + + InputArray[i+j*InputVLen]=InputArray[i+j*InputVLen]-EualCurve960[i]; + + } + + } + +} +double MeanArray( double *InputArray, int InputHLen, int InputVLen) +{ + int i; + int j; + double sum; + int count; + count=0; + sum=0; + for (j=0;j<InputHLen;j++) + { + for (i=0;i<InputVLen;i++) + { + count=count+1; + sum=sum+InputArray[i+j*InputVLen]; + + } + } + return sum/count; +} +void Mydiff( double *InputArray, int InputHLen, int InputVLen,int n) +{ + int i; + int j; + double * OutArray; + + OutArray=(double*)malloc(InputHLen*InputVLen*sizeof(double)); + + for (i=0;i<InputVLen;i++) + { + for (j=n;j<InputHLen;j++) + { + OutArray[i+j*InputVLen]=InputArray[i+j*InputVLen]-InputArray[i+(j-n)*InputVLen]; + + } + } + + for (i=0;i<InputVLen;i++) + { + for (j=n;j<InputHLen;j++) + { + InputArray[i+j*InputVLen]=OutArray[i+j*InputVLen]; + + } + } + + for (i=0;i<InputVLen;i++) + { + for (j=0;j<n;j++) + { + InputArray[i+j*InputVLen]=0; + + } + } + + free(OutArray); +} + +void PeakDetect(double *In, int InLen) +{ + int i,j; + double *Out1; + + Out1=(double*)malloc(InLen*sizeof(double)); + for (i=0;i<InLen;i++) + { + Out1[i]=0; + } + + + + for (i=2;i<(InLen-3);i++) + { + if( (In[i]>In[i+2])&&(In[i]>In[i-2]) + &&(In[i]>In[i+1])&&(In[i]>In[i-1])) + { + Out1[i]=In[i]; + } + + } + + for(i=0;i<InLen;i++) + { + + In[i]=Out1[i]; + } + + free(Out1); +} +void MeanV( double *InputArray, int InputHLen, int InputVLen, double *OutArray) +{ + int i; + int j; + double sum; + + for (j=0;j<InputHLen;j++) + { + sum=0; + for (i=0;i<InputVLen;i++) + { + + sum=sum+InputArray[i+j*InputVLen]; + + } + OutArray[j]=sum/InputVLen; + } + +} +void Edetect(double *InputArray, int InputHLen, int InputVLen, double MinT, double db1,double *OutOne) +{ + int i; + int j; + double MaxValue; + +// printf(" Starting Energy Onset Detection.. %f\n",db1); + RemoveNoise(InputArray, InputHLen, InputVLen); + + + MaxValue=GetMaxValue(InputArray,InputHLen,InputVLen); + + for (i=0;i<InputVLen;i++) + { + for (j=0;j<InputHLen;j++) + { + InputArray[i*InputHLen+j]=InputArray[i*InputHLen+j]-MaxValue; + + } + + } + + MinArray(InputArray, InputHLen, InputVLen, -100); + Mydiff(InputArray, InputHLen, InputVLen,3); + MinArray(InputArray, InputHLen, InputVLen, MinT); + + for (i=0;i<InputVLen;i++) + { + for (j=0;j<InputHLen;j++) + { + InputArray[i*InputHLen+j]=InputArray[i*InputHLen+j]-MinT; + + } + + } + + MeanV(InputArray,InputHLen,InputVLen,OutOne); + Smooth(OutOne, InputHLen,3); + Smooth(OutOne, InputHLen,3); + Move(OutOne,InputHLen,-2); + PeakDetect(OutOne,InputHLen); + MinArray(OutOne, InputHLen,1, db1); + + for (j=0;j<InputHLen;j++) + { + OutOne[j]=OutOne[j]-db1; + + } +} + + + +void OnsetDetection2(double *In,int InputLen,double *OutOne,double a,double b) +{ + int mseconds; + double *Input; + + + mseconds=InputLen; + + Input=(double *)malloc(mseconds*960*sizeof(double)); + + ConFrom1050To960(In,Input,InputLen); + + + + + if(a>0) + { + Edetect(Input,mseconds,960, a,b,OutOne); + } + + + free(Input); + +} + +void PitchEstimation(double *In, int InLen, double *OutArray,double *OutArray2) +{ + double *xx,*x,*y,*y1,*PeakPitch1, *PeakPitch2,*PeakInput1, *PeakInput2; + double *out,*outValue; + double *output,*output1; + double notefloat,hh0,hh1,hh28; + double outM12[12]; + int *outc; + int *yI; + double temp; + int i,j,sumI; + int Len; + int NN,NN2; + int count; + double Th; + + Len=1050; + xx=(double*)malloc(Len*sizeof(double)); + x=(double*)malloc(Len*sizeof(double)); + y=(double*)malloc(Len*sizeof(double)); + y1=(double*)malloc(Len*sizeof(double)); + PeakPitch1=(double*)malloc(Len*sizeof(double)); + PeakPitch2=(double*)malloc(Len*sizeof(double)); + PeakInput1=(double*)malloc(Len*sizeof(double)); + PeakInput2=(double*)malloc(Len*sizeof(double)); + out=(double*)malloc(Len*sizeof(double)); + outValue=(double*)malloc(Len*sizeof(double)); + output=(double*)malloc(112*sizeof(double)); + output1=(double*)malloc(112*sizeof(double)); + outc=(int*)malloc(112*sizeof(int)); +// yI=(double*)malloc(12*sizeof(double)); + + + for (i=0;i<Len;i++) + { + x[i]=In[i]; + } + + for (i=0;i<Len;i++) + { + y1[i]=x[i]; + } + + ConToPitch1250(y1,Len); + + for (i=0;i<Len;i++) + { + y[i]=y1[i]; + } + + Smooth(y,Len,30); + + for (i=0;i<Len;i++) + { + y1[i]=y1[i]-y[i]; + } + + for (i=0;i<Len;i++) + { + y1[i]=y1[i]+20; + } + + temp=0; + for (i=0;i<Len;i++) + { + temp=temp+x[i]; + } + temp=temp/Len; + for (i=0;i<Len;i++) + { + y[i]=x[i]-temp; + } + + + for (i=0;i<Len;i++) + { + PeakPitch2[i]=0; + PeakPitch1[i]=0; + PeakInput1[i]=0; + PeakInput2[i]=0; + } + FindPeaks(y1, Len,PeakPitch1,PeakPitch2, 0, -1000, -1000); + FindPeaks(y, Len,PeakInput1,PeakInput2, 0, 6, 15); + + + + sumI=0; + for (i=0;i<Len;i++) + { + sumI=sumI+PeakPitch2[i]; + } + + + if (sumI>12) + { + FindMaxN(PeakPitch1,Len,12); + + for (i=0;i<Len;i++) + { + if(PeakPitch1[i]==0) + { + PeakPitch2[i]=0; + } + } + + } + + for (i=0;i<Len;i++) + { + out[i]=0; + outValue[i]=0; + } + + for (i=0;i<(Len-300);i++) + { + if(PeakPitch2[i]==1) + + { + if ( + ((SumF(PeakInput2,i-4,i+4)>0)&&(SumF(PeakInput2,i+120-4,i+120+4)>0)) + ||((SumF(PeakInput2,i-4,i+4)>0)&&(SumF(PeakInput2,i+190-4,i+190+4)>0)) + ||((SumF(PeakInput2,i+190-4,i+190+4)>0)&&(SumF(PeakInput2,i+120-4,i+120+4)>0)) + ) + { + out[i]=1; + outValue[i]=y1[i]; + + } + } + } + + for (i=0;i<112;i++) + { + output[i]=0; + outc[i]=0; + } + + + + for (i=0;i<Len;i++) + { + if(out[i]==1) + { + output[20+round10(i+1)-1]=1; + outc[20+round10(i+1)-1]=i; + } + } + + + for (i=0;i<112;i++) + { + output1[i]=output[i]; + } + + + + for (i=20;i<(112-28);i++) + { + if((output[i]>0)&&(SumF(PeakInput2,outc[i]-5,outc[i]+5)==0)) + { + output1[i]=0; + } + } + + + for (i=0;i<112;i++) + { + OutArray[i]=0; + OutArray2[i]=0; + + } + + Th=30; + for(i=20;i<105;i++) + { + if(output1[i]==1) + { + OutArray[i]=outc[i]+200+2; + OutArray2[i]=y[outc[i]]; + + } + + } + + free(xx); // xx=(double*)malloc(Len*sizeof(double)); + free(x); // x=(double*)malloc(Len*sizeof(double)); + free(y); // y=(double*)malloc(Len*sizeof(double)); + free(y1); // y1=(double*)malloc(Len*sizeof(double)); + free(PeakPitch1); //=(double*)malloc(Len*sizeof(double)); + free(PeakPitch2); //=(double*)malloc(Len*sizeof(double)); + free(PeakInput1); //=(double*)malloc(Len*sizeof(double)); + free(PeakInput2); //=(double*)malloc(Len*sizeof(double)); + free(out); //=(double*)malloc(Len*sizeof(double)); + free(outValue); //=(double*)malloc(Len*sizeof(double)); + free(output); //=(double*)malloc(112*sizeof(double)); + free(output1); //=(double*)malloc(112*sizeof(double)); + free(outc); //=(double*)malloc(112*sizeof(int)); +//free(yI); //=(double*)malloc(12*sizeof(int)); +// printf(" end free \n"); +} + +void DoMultiPitch(double *In, int RLen,int CLen, double *Out1, double *Out2) +{ + + int i, j; + double *sum1,*mean1; + double MaxV; + double *OutArray1, *OutArray2,*tempArray; + + OutArray1=(double *)malloc(112*sizeof(double)); + OutArray2=(double *)malloc(112*sizeof(double)); + tempArray=(double *)malloc(RLen*sizeof(double)); + + sum1=(double*)malloc(CLen*sizeof(double)); + mean1=(double*)malloc(CLen*sizeof(double)); + + for (j=0;j<CLen;j++) + { + sum1[j]=0; + for (i=0;i<RLen;i++) + { + sum1[j]=sum1[j]+In[j*RLen+i]; + } + + mean1[j]=sum1[j]/CLen; + } + MaxV=mean1[0]; + for (j=0;j<CLen;j++) + { + if(mean1[j]>MaxV) + { + MaxV=mean1[j]; + } + } + + for (j=0;j<CLen;j++) + { + mean1[j]=mean1[j]-MaxV; + } + + + for (j=0;j<CLen;j++) + { + + for (i=0;i<112;i++) + { + + OutArray1[i]=0; + OutArray2[i]=0;; + + } + MaxV=In[j*RLen]; + for(i=0;i<RLen;i++) + { + tempArray[i]=In[j*RLen+i]; + if(tempArray[i]>MaxV) + MaxV=tempArray[i]; + } + + if(mean1[j]>-55) + { + + PitchEstimation(tempArray,RLen,OutArray1,OutArray2); + + for(i=0;i<112;i++) + { + if(OutArray1[i]>0) + { + if((MaxV-tempArray[(int)OutArray1[i]-201-1])>40) + { + OutArray1[i]=0; + OutArray2[i]=0; + } + + } + } + + } + + for (i=0;i<112;i++) + { + + Out1[j*112+i]=OutArray1[i]; + Out2[j*112+i]=OutArray2[i]; + + } + + } + + free(OutArray1); + free(OutArray2); + free(tempArray); + free(sum1); + free(mean1); +} + + +int OnsetToArray(double *In, int Len, double *OutStart,double *OutEnd) +{ + int count,i; + + count=0; + + for (i=0;i<Len;i++) + { + if(In[i]>0) + { + OutStart[count]=i+1; + if(count>0) + { + OutEnd[count-1]=i+1; + } + count=count+1; + } + } + if (count>0) + { + OutEnd[count-1]=Len; + } + return count; + +} +void dbfunction( double *InputArray, int InputHLen, int InputVLen,double *OutArray) +{ + int i; + int j; + double temp; + + for (i=0;i<InputVLen;i++) + { + for (j=0;j<InputHLen;j++) + { + OutArray[i*InputHLen+j]=20*log10(InputArray[i*InputHLen+j]); + + } + + } +} + +void Transcribe(int Len,int inputLen,double *SoundIn,double *out,double *outArray2,double *outArray3,double SampleRate) +{ + int OnsetN; + int i,j,k; + int count; + int index; + double *OutStart,*OutEnd; + int start,endd,startb=1,start2,endd2; + double *A1,*A2,*A3,*A4,*A5,*A6,*D,*D2; + double *A6A; + double *out2, *PitchOut1,*PitchOut2,*PitchOut3; + double sum,maxV,maxVal; + double *tempArray; + double temp; + double p; + double M1,M2; + double *In; + int Len2; + double *dbs,*ss,*dbs1,*jj; + int TempInt; + + + A1=(double *)malloc(112*sizeof(double)); + A2=(double *)malloc(112*sizeof(double)); + A3=(double *)malloc(112*sizeof(double)); + A4=(double *)malloc(112*sizeof(double)); + A5=(double *)malloc(112*sizeof(double)); + A6=(double *)malloc(112*sizeof(double)); + D=(double *)malloc(112*sizeof(double)); + D2=(double *)malloc(112*sizeof(double)); + PitchOut1=(double *)malloc(112*Len*sizeof(double)); + PitchOut2=(double *)malloc(112*Len*sizeof(double)); + PitchOut3=(double *)malloc(112*Len*sizeof(double)); + OutStart=(double *)malloc(Len*sizeof(double)); + OutEnd=(double *)malloc(Len*sizeof(double)); + tempArray=(double *)malloc(sizeof(double)*Len); + In=(double *)malloc(sizeof(double)*Len); + dbs=(double *)malloc(1050*sizeof(double)*Len); + dbs1=(double *)malloc(210*sizeof(double)*Len); + ss=(double *)malloc(210*sizeof(double)*Len); + jj=(double *)malloc(1050*sizeof(double)); + + + + + for(k=0;k<1050;k++) + { + + jj[k]=k/5.0; + + } + + sofacomplexMex(SoundIn,ss,inputLen,20,0.5,210,0.03,20,SampleRate); + dbfunction(ss, Len, 210,dbs1); + + for(i=0;i<Len;i++) + { + for(k=0;k<1045;k++) + { + TempInt=(int)jj[k]; + dbs[k+i*1050]=(jj[k]-TempInt)*dbs1[TempInt+1+i*210]+(TempInt+1-jj[k])*dbs1[TempInt+i*210]; + + } + + for (k=1045;k<1050;k++) + { + dbs[k+i*1050]=dbs[1044+i*1050]; + } + + } + + OnsetDetection2(dbs,Len,In,3,1.2); + for (i=0;i<Len;i++) + { + outArray2[i]=In[i]; + + } + + OnsetN=0; + count=0; + for (i=0;i<Len;i++) + { + if(In[i]>0) + { + OnsetN=OnsetN+1; + count=count+1; + } + } + Len2=count; + out2=(double *)malloc(112*Len2*sizeof(double)); + A6A=(double *)malloc(112*Len2*sizeof(double)); + OnsetToArray(In,Len,OutStart,OutEnd); + DoMultiPitch(dbs,1050,Len, PitchOut1, PitchOut2); + + + for (i=0;i<Len;i++) + { + for (j=0;j<112;j++) + { + PitchOut3[i*112+j]=PitchOut1[i*112+j]; + if(PitchOut3[i*112+j]>1) + PitchOut3[i*112+j]=1; + } + + } + + + for (i=0;i<OnsetN;i++) + { + for(j=0;j<112;j++) + { + A1[j]=0;A2[j]=0;A3[j]=0;A4[j]=0;A5[j]=0;A6[j]=0; + + } + maxV=0; + start=(int)OutStart[i]; + endd=(int)OutEnd[i]; + if(i>0) + { + startb=(int)OutStart[i-1]; + } + + for (j=0;j<112;j++) + { + sum=0; + count=0; + for (k=(start-1);k<endd;k++) + { + sum=sum+PitchOut3[k*112+j]; + count=count+1; + } + + A1[j]=sum; + A6[j]=sum/count; + A6A[i*112+j]=sum/count; + + } + + for (j=0;j<112;j++) + { + maxVal=PitchOut2[start*112+j]; + for (k=(start-1);k<endd;k++) + { + if(PitchOut2[k*112+j]>maxVal) + { + maxVal=PitchOut2[k*112+j]; + } + + } + + A3[j]=maxVal; + + } + + for (j=0;j<112;j++) + { + sum=0; + count=0; + for (k=(start-1);k<endd;k++) + { + if(PitchOut2[k*112+j]>0) + { + sum=sum+PitchOut2[k*112+j]; + count=count+1; + } + } + if(count>0) + A4[j]=sum/count; + else + A4[j]=0; + } + + + for (j=0;j<112;j++) + { + sum=0; + count=0; + for (k=(start-1);k<endd;k++) + { + if(PitchOut1[k*112+j]>0) + { + sum=sum+PitchOut1[k*112+j]; + count=count+1; + } + } + if(count>0) + A5[j]=sum/count; + else + A5[j]=0; + } + + maxV=A3[0]; + for (j=0;j<112;j++) + { + if(A3[j]>maxV) + maxV=A3[j]; + } + + for (j=0;j<112;j++) + { + + if(A1[j]>0) + { + D[j]=A1[j];D2[j]=A1[j]; + } + + else + { + D[j]=A1[j];D2[j]=A1[j]; + } + } + + for (j=0;j<112;j++) + { + if(A1[j]<8) + { + D[j]=0;D2[j]=0; + } + + } + + for(j=0;j<112;j++) + { + + if ((j>12)&&(D[j]>0)&&(D[j-12]>0)) + { + D[j]=0; D2[j]=0; + if((A3[j]>45)&&(A3[j]>(A3[j-12]+3))) + { + D[j]=1; + } + } + + + if ((j>19)&&(D[j]>0)&&(D[j-19]>0)) + { + + D[j]=0; D2[j]=0; + if((A3[j]>50)) + { + D[j]=1; + } + } + + if ((j>24)&&(D[j]>0)&&(D[j-24]>0)) + { + + D[j]=0; D2[j]=0; + if((A3[j]>50)) + { + D[j]=1; + } + } + + if ((j>28)&&(D[j]>0)&&(D[j-28]>0)) + { + + D[j]=0; D2[j]=0; + if((A3[j]>50)) + { + D[j]=1; + } + } + + if ((j>34)&&(abs(A5[j]-337.0-A5[j-34])<3.0)&&(D[j]>0)&&(D[j-34]>0)) + { + + D[j]=0; D2[j]=0; + if((A4[j]>25)&&(A3[j]>40)&&(A3[j]>(A3[j-34]-3))&&((A1[j]>8)||(A6[j]>0.8))) + { + D[j]=1; + } + } + + if((j>48)&&(j<59)&&(A3[j]<20)) + { + D[j]=0; + } + + if((j>58)&&(j<69)&&(A3[j]<28)) + { + D[j]=0; + } + + + if((j>68)&&(j<79)&&(A3[j]<40)) + { + D[j]=0; + } + + if((j>78)&&(A3[j]<50)) + { + D[j]=0; + } + + if((j>85)&&(A3[j]<55)) + { + D[j]=0; + } + + if((D2[j]>0)&&(A1[j]>15)) + { + D[j]=1; + } + if(i>1) + { + + for (k=(startb-1);k<start;k++) + { + tempArray[k-startb+1]=PitchOut3[j+k*112]; + + } + temp=Sum(tempArray,start-startb+1); + if(((maxV-A3[j])>20)&&(temp>3)) + { + D[j]=0; + } + + } + + } + + for(j=0;j<112;j++) + { + out[j+i*112]=D[j]; + out2[j+i*112]=D[j]; + } + } + + for (i=1;i<OnsetN;i++) + { + start2=(int)OutStart[i]; + endd2=(int)OutEnd[i]; + + for (j=0;j<112;j++) + { + sum=0; + count=0; + for (k=(start2-1);k<endd2;k++) + { + sum=sum+PitchOut3[k*112+j]; + count=count+1; + } + + A1[j]=sum; + } + + for (j=0;j<112;j++) + { + if((out2[(i-1)*112+j]>0)&&(out[j+i*112]>0)) + { + out[j+i*112]=0; + sum=0; + for(k=(start2-1);k<endd2;k++) + { + sum=sum+PitchOut1[j+k*112]; + + } + p=sum/A1[j]; + + index=(int)(p+0.5)-200; + + if((index>0)&&(i<(OnsetN-1))&&(start2>5)) + { + + M1=dbs[index+(start2-1)*1050]; + for (k=(start2-1);k<(start2+10);k++) + { + if(dbs[index+k*1050]>M1) + M1=dbs[index+k*1050]; + + } + + M2=dbs[index+(start2-5-1)*1050]; + for (k=(start2-5-1);k<start2;k++) + { + if(dbs[index+k*1050]<M2) + M2=dbs[index+k*1050]; + + } + + if((M1-M2)>10) + { + out[j+i*112]=1; + } + } + } + } + } + + count=0; + for (i=0;i<OnsetN;i++) + { + + start=(int)OutStart[i]; + endd=(int)OutEnd[i]; + + for(j=0;j<112;j++) + { + if(out[j+i*112]>0) + { + outArray3[count*3+0]=j+1-21;//exp((log(2.0))*(j+1-69)/12)*440; + outArray3[count*3+1]=start*0.01; + + if(i==(OnsetN-1)) + { + outArray3[count*3+2]=0.01*OutEnd[i]; + } + else + { + + for(k=(i+1);k<OnsetN;k++) + { + + if(k==(OnsetN-1)) + { + outArray3[count*3+2]=0.01*OutEnd[k]; + } + + if(out[j+k*112]>0) + { + outArray3[count*3+2]=0.01*OutStart[k]; + break; + } + + if(A6A[k*112+j]<0.5) + { + outArray3[count*3+2]=0.01*OutStart[k]; + break; + + } + + } + + } + + count=count+1; + } + + } + + } + outArray3[count*3+0]=0; + outArray3[count*3+1]=0; + outArray3[count*3+2]=0; + + free(tempArray); + free(OutStart); + free(OutEnd); + free(A1); + free(A2); + free(A3); + free(A4); + free(A5); + free(A6); + free(A6A); + free(D); + free(D2); + free(out2); + free(PitchOut1); + free(PitchOut2); + free(PitchOut3); + free(In); + free(dbs); + free(dbs1); + free(ss); + free(jj); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/plugins/Transcription.h Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,81 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#ifndef _TRANSCRIPTION_PLUGIN_H_ +#define _TRSNSCRIPTION_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> + +class Transcription : public Vamp::Plugin +{ +public: + Transcription(float inputSampleRate); + virtual ~Transcription(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const { return TimeDomain; } + + std::string getIdentifier() const; + std::string getName() const; + std::string getDescription() const; + std::string getMaker() const; + int getPluginVersion() const; + std::string getCopyright() const; + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + + OutputList getOutputDescriptors() const; + + FeatureSet process(const float *const *inputBuffers, + Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + size_t m_stepSize; + size_t m_blockSize; + double * m_SoundIn; + size_t m_SampleN; + size_t m_AllocN; + bool m_Excess; + Vamp::RealTime m_Base; +/* + void sofacomplexMex(double *y, double *z, int ncols,double StartNote,double NoteInterval1,double NoteNum,double C,double D); + void FindMaxN( double *InputArray, int InputLen,int MaxOrder); + double SumF(double *InputArray,int Start, int End); + int round10(int x) ; + void ConToPitch1250(double *In, int InLen); + void Norm1(double *In, int InLen); + void Smooth(double *In, int InLen,int smoothLen); + void FindPeaks(double *In, int InLen,double *Out1,double *Out2, int db, int db2, int db3); + void ConFrom1050To960(double *In, double *out, int InputLen); + void Move( double *InputArray, int InputLen,int m); + double SumArray( double *InputArray, int InputHLen, int InputVLen); + double Sum( double *InputArray, int InputHLen); + void MeanV2( double *InputArray, int InputHLen, int InputVLen, double *OutArray); + void SumV( double *InputArray, int InputHLen, int InputVLen, double *OutArray); + void SumV2( double *InputArray, int InputHLen, int InputVLen, double *OutArray); + void MaxV( double *InputArray, int InputHLen, int InputVLen, double *OutArray); + void MaxV2( double *InputArray, int InputHLen, int InputVLen, double *OutArray); + void MinArray( double *InputArray, int InputHLen, int InputVLen, double MinValue); + void MaxArray( double *InputArray, int InputHLen, int InputVLen, double MaxValue); + double GetMaxValue( double *InputArray, int InputHLen, int InputVLen); + void RemoveNoise( double *InputArray, int InputHLen, int InputVLen); + double MeanArray( double *InputArray, int InputHLen, int InputVLen); + void Mydiff( double *InputArray, int InputHLen, int InputVLen,int n); + void PeakDetect(double *In, int InLen); + void MeanV( double *InputArray, int InputHLen, int InputVLen, double *OutArray); +void Edetect(double *InputArray, int InputHLen, int InputVLen, double MinT, double db1,double *OutOne); +void OnsetDetection2(double *In,int InputLen,double *OutOne,double a,double b); +void PitchEstimation(double *In, int InLen, double *OutArray,double *OutArray2); +void DoMultiPitch(double *In, int RLen,int CLen, double *Out1, double *Out2); +int OnsetToArray(double *In, int Len, double *OutStart,double *OutEnd); +void dbfunction( double *InputArray, int InputHLen, int InputVLen,double *OutArray); + +void Transcribe(int Len,int inputLen,double *SoundIn,double *out,double *outArray2,double *outArray3);*/ + +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/qm-vamp-plugins.cat Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,13 @@ +vamp:qm-vamp-plugins:qm-tempotracker::Time > Tempo +vamp:qm-vamp-plugins:qm-onsetdetector::Time > Onsets +vamp:qm-vamp-plugins:qm-chromagram::Visualisation +vamp:qm-vamp-plugins:qm-constantq::Visualisation +vamp:qm-vamp-plugins:qm-tonalchange::Key and Tonality +vamp:qm-vamp-plugins:qm-keydetector::Key and Tonality +vamp:qm-vamp-plugins:qm-segmenter::Classification +vamp:qm-vamp-plugins:qm-similarity::Classification +vamp:qm-vamp-plugins:qm-mfcc::Low Level Features +vamp:qm-vamp-plugins:qm-barbeattracker::Time > Tempo +vamp:qm-vamp-plugins:qm-adaptivespectrogram::Visualisation +vamp:qm-vamp-plugins:qm-dwt::Visualisation +vamp:qm-vamp-plugins:qm-transcription::Notes
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/qm-vamp-plugins.n3 Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,1088 @@ +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . +@prefix vamp: <http://purl.org/ontology/vamp/> . +@prefix plugbase: <http://vamp-plugins.org/rdf/plugins/qm-vamp-plugins#> . +@prefix owl: <http://www.w3.org/2002/07/owl#> . +@prefix dc: <http://purl.org/dc/elements/1.1/> . +@prefix af: <http://purl.org/ontology/af/> . +@prefix foaf: <http://xmlns.com/foaf/0.1/> . +@prefix cc: <http://web.resource.org/cc/> . +@prefix : <#> . + +<> a vamp:PluginDescription ; + foaf:maker <http://www.vamp-plugins.org/doap.rdf#template-generator> ; + foaf:primaryTopic <http://vamp-plugins.org/rdf/plugins/qm-vamp-plugins> . + +:qm-vamp-plugins a vamp:PluginLibrary ; + vamp:identifier "qm-vamp-plugins" ; + vamp:available_plugin plugbase:qm-adaptivespectrogram ; + vamp:available_plugin plugbase:qm-barbeattracker ; + vamp:available_plugin plugbase:qm-chromagram ; + vamp:available_plugin plugbase:qm-constantq ; + vamp:available_plugin plugbase:qm-dwt ; + vamp:available_plugin plugbase:qm-keydetector ; + vamp:available_plugin plugbase:qm-mfcc ; + vamp:available_plugin plugbase:qm-onsetdetector ; + vamp:available_plugin plugbase:qm-segmenter ; + vamp:available_plugin plugbase:qm-similarity ; + vamp:available_plugin plugbase:qm-tempotracker ; + vamp:available_plugin plugbase:qm-tonalchange ; + vamp:available_plugin plugbase:qm-transcription ; + foaf:page <http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html> ; + . + +plugbase:qm-adaptivespectrogram a vamp:Plugin ; + dc:title "Adaptive Spectrogram" ; + vamp:name "Adaptive Spectrogram" ; + dc:description """Produce an adaptive spectrogram by adaptive selection from spectrograms at multiple resolutions""" ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Wen Xue and Chris Cannam. Copyright (c) 2009 Wen Xue and QMUL - All Rights Reserved""" ; + vamp:identifier "qm-adaptivespectrogram" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "1" ; + vamp:input_domain vamp:TimeDomain ; + + vamp:parameter plugbase:qm-adaptivespectrogram_param_n ; + vamp:parameter plugbase:qm-adaptivespectrogram_param_w ; + vamp:parameter plugbase:qm-adaptivespectrogram_param_coarse ; + vamp:parameter plugbase:qm-adaptivespectrogram_param_threaded ; + + vamp:output plugbase:qm-adaptivespectrogram_output_output ; + . +plugbase:qm-adaptivespectrogram_param_n a vamp:QuantizedParameter ; + vamp:identifier "n" ; + dc:title "Number of resolutions" ; + dc:format "" ; + vamp:min_value 2 ; + vamp:max_value 10 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 3 ; + vamp:value_names (); + . +plugbase:qm-adaptivespectrogram_param_w a vamp:QuantizedParameter ; + vamp:identifier "w" ; + dc:title "Smallest resolution" ; + dc:format "" ; + vamp:min_value 1 ; + vamp:max_value 14 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 9 ; + vamp:value_names ( "2" "4" "8" "16" "32" "64" "128" "256" "512" "1024" "2048" "4096" "8192" "16384"); + . +plugbase:qm-adaptivespectrogram_param_coarse a vamp:QuantizedParameter ; + vamp:identifier "coarse" ; + dc:title "Omit alternate resolutions" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 0 ; + vamp:value_names (); + . +plugbase:qm-adaptivespectrogram_param_threaded a vamp:QuantizedParameter ; + vamp:identifier "threaded" ; + dc:title "Multi-threaded processing" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 1 ; + vamp:value_names (); + . +plugbase:qm-adaptivespectrogram_output_output a vamp:DenseOutput ; + vamp:identifier "output" ; + dc:title "Output" ; + dc:description """The output of the plugin""" ; + vamp:unit "" ; + vamp:computes_signal_type af:Spectrogram ; + . +plugbase:qm-barbeattracker a vamp:Plugin ; + dc:title "Bar and Beat Tracker" ; + vamp:name "Bar and Beat Tracker" ; + dc:description """Estimate bar and beat locations""" ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Matthew Davies, Christian Landone and Chris Cannam. Copyright (c) 2006-2009 QMUL - All Rights Reserved""" ; + vamp:identifier "qm-barbeattracker" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "1" ; + vamp:input_domain vamp:TimeDomain ; + + vamp:parameter plugbase:qm-barbeattracker_param_bpb ; + + vamp:output plugbase:qm-barbeattracker_output_beats ; + vamp:output plugbase:qm-barbeattracker_output_bars ; + vamp:output plugbase:qm-barbeattracker_output_beatcounts ; + vamp:output plugbase:qm-barbeattracker_output_beatsd ; + . +plugbase:qm-barbeattracker_param_bpb a vamp:QuantizedParameter ; + vamp:identifier "bpb" ; + dc:title "Beats per Bar" ; + dc:format "" ; + vamp:min_value 2 ; + vamp:max_value 16 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 4 ; + vamp:value_names (); + . +plugbase:qm-barbeattracker_output_beats a vamp:SparseOutput ; + vamp:identifier "beats" ; + dc:title "Beats" ; + dc:description """Beat locations labelled with metrical position""" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 0 ; + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 86.1326 ; + vamp:computes_event_type af:Beat ; + . +plugbase:qm-barbeattracker_output_bars a vamp:SparseOutput ; + vamp:identifier "bars" ; + dc:title "Bars" ; + dc:description """Bar locations""" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 0 ; + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 86.1326 ; +# vamp:computes_event_type <Place event type URI here and uncomment> ; + . +plugbase:qm-barbeattracker_output_beatcounts a vamp:SparseOutput ; + vamp:identifier "beatcounts" ; + dc:title "Beat Count" ; + dc:description """Beat counter function""" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 1 ; + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 86.1326 ; +# vamp:computes_event_type <Place event type URI here and uncomment> ; + . +plugbase:qm-barbeattracker_output_beatsd a vamp:SparseOutput ; + vamp:identifier "beatsd" ; + dc:title "Beat Spectral Difference" ; + dc:description """Beat spectral difference function used for bar-line detection""" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 1 ; + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 86.1326 ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-chromagram a vamp:Plugin ; + dc:title "Chromagram" ; + vamp:name "Chromagram" ; + dc:description """Extract a series of tonal chroma vectors from the audio""" ; + foaf:page <http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html#qm-chromagram> ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Chris Cannam and Christian Landone. Copyright (c) 2006-2009 QMUL - All Rights Reserved""" ; + vamp:identifier "qm-chromagram" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "4" ; + vamp:input_domain vamp:FrequencyDomain ; + + + vamp:parameter plugbase:qm-chromagram_param_minpitch ; + vamp:parameter plugbase:qm-chromagram_param_maxpitch ; + vamp:parameter plugbase:qm-chromagram_param_tuning ; + vamp:parameter plugbase:qm-chromagram_param_bpo ; + vamp:parameter plugbase:qm-chromagram_param_normalization ; + + vamp:output plugbase:qm-chromagram_output_chromagram ; + vamp:output plugbase:qm-chromagram_output_chromameans ; + . +plugbase:qm-chromagram_param_minpitch a vamp:QuantizedParameter ; + vamp:identifier "minpitch" ; + dc:title "Minimum Pitch" ; + dc:format "MIDI units" ; + vamp:min_value 0 ; + vamp:max_value 127 ; + vamp:unit "MIDI units" ; + vamp:quantize_step 1 ; + vamp:default_value 36 ; + vamp:value_names (); + . +plugbase:qm-chromagram_param_maxpitch a vamp:QuantizedParameter ; + vamp:identifier "maxpitch" ; + dc:title "Maximum Pitch" ; + dc:format "MIDI units" ; + vamp:min_value 0 ; + vamp:max_value 127 ; + vamp:unit "MIDI units" ; + vamp:quantize_step 1 ; + vamp:default_value 96 ; + vamp:value_names (); + . +plugbase:qm-chromagram_param_tuning a vamp:Parameter ; + vamp:identifier "tuning" ; + dc:title "Tuning Frequency" ; + dc:format "Hz" ; + vamp:min_value 360 ; + vamp:max_value 500 ; + vamp:unit "Hz" ; + vamp:default_value 440 ; + vamp:value_names (); + . +plugbase:qm-chromagram_param_bpo a vamp:QuantizedParameter ; + vamp:identifier "bpo" ; + dc:title "Bins per Octave" ; + dc:format "bins" ; + vamp:min_value 2 ; + vamp:max_value 480 ; + vamp:unit "bins" ; + vamp:quantize_step 1 ; + vamp:default_value 12 ; + vamp:value_names (); + . +plugbase:qm-chromagram_param_normalization a vamp:QuantizedParameter ; + vamp:identifier "normalization" ; + dc:title "Normalization" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 2 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 0 ; + vamp:value_names ( "None" "Unit Sum" "Unit Maximum"); + . +plugbase:qm-chromagram_output_chromagram a vamp:DenseOutput ; + vamp:identifier "chromagram" ; + dc:title "Chromagram" ; + dc:description "Output of chromagram, as a single vector per process block" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 12 ; + vamp:bin_names ( "C" "C#" "D" "D#" "E" "F" "F#" "G" "G#" "A" "A#" "B"); + vamp:computes_signal_type af:Chromagram ; + . +plugbase:qm-chromagram_output_chromameans a vamp:DenseOutput ; + vamp:identifier "chromameans" ; + dc:title "Chroma Means" ; + dc:description "Mean values of chromagram bins across the duration of the input audio" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 12 ; + vamp:bin_names ( "C" "C#" "D" "D#" "E" "F" "F#" "G" "G#" "A" "A#" "B"); +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-constantq a vamp:Plugin ; + dc:title "Constant-Q Spectrogram" ; + vamp:name "Constant-Q Spectrogram" ; + dc:description """Extract a spectrogram with constant ratio of centre frequency to resolution from the input audio""" ; + foaf:page <http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html#qm-constantq> ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Chris Cannam and Christian Landone. Copyright (c) 2006-2009 QMUL - All Rights Reserved""" ; + vamp:identifier "qm-constantq" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "2" ; + vamp:input_domain vamp:FrequencyDomain ; + + + vamp:parameter plugbase:qm-constantq_param_minpitch ; + vamp:parameter plugbase:qm-constantq_param_maxpitch ; + vamp:parameter plugbase:qm-constantq_param_tuning ; + vamp:parameter plugbase:qm-constantq_param_bpo ; + vamp:parameter plugbase:qm-constantq_param_normalized ; + + vamp:output plugbase:qm-constantq_output_constantq ; + . +plugbase:qm-constantq_param_minpitch a vamp:QuantizedParameter ; + vamp:identifier "minpitch" ; + dc:title "Minimum Pitch" ; + dc:format "MIDI units" ; + vamp:min_value 0 ; + vamp:max_value 127 ; + vamp:unit "MIDI units" ; + vamp:quantize_step 1 ; + vamp:default_value 36 ; + vamp:value_names (); + . +plugbase:qm-constantq_param_maxpitch a vamp:QuantizedParameter ; + vamp:identifier "maxpitch" ; + dc:title "Maximum Pitch" ; + dc:format "MIDI units" ; + vamp:min_value 0 ; + vamp:max_value 127 ; + vamp:unit "MIDI units" ; + vamp:quantize_step 1 ; + vamp:default_value 84 ; + vamp:value_names (); + . +plugbase:qm-constantq_param_tuning a vamp:Parameter ; + vamp:identifier "tuning" ; + dc:title "Tuning Frequency" ; + dc:format "Hz" ; + vamp:min_value 360 ; + vamp:max_value 500 ; + vamp:unit "Hz" ; + vamp:default_value 440 ; + vamp:value_names (); + . +plugbase:qm-constantq_param_bpo a vamp:QuantizedParameter ; + vamp:identifier "bpo" ; + dc:title "Bins per Octave" ; + dc:format "bins" ; + vamp:min_value 2 ; + vamp:max_value 480 ; + vamp:unit "bins" ; + vamp:quantize_step 1 ; + vamp:default_value 12 ; + vamp:value_names (); + . +plugbase:qm-constantq_param_normalized a vamp:QuantizedParameter ; + vamp:identifier "normalized" ; + dc:title "Normalized" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 0 ; + vamp:value_names (); + . +plugbase:qm-constantq_output_constantq a vamp:DenseOutput ; + vamp:identifier "constantq" ; + dc:title "Constant-Q Spectrogram" ; + dc:description "Output of constant-Q transform, as a single vector per process block" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 1 ; + vamp:computes_signal_type af:Spectrogram ; + . +plugbase:qm-dwt a vamp:Plugin ; + dc:title "Discrete Wavelet Transform" ; + vamp:name "Discrete Wavelet Transform" ; + dc:description """Visualisation by scalogram""" ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Thomas Wilmering. Copyright (c) 2009 Thomas Wilmering and QMUL - All Rights Reserved""" ; + vamp:identifier "qm-dwt" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "1" ; + vamp:input_domain vamp:TimeDomain ; + + vamp:parameter plugbase:qm-dwt_param_scales ; + vamp:parameter plugbase:qm-dwt_param_wavelet ; + vamp:parameter plugbase:qm-dwt_param_threshold ; + vamp:parameter plugbase:qm-dwt_param_absolute ; + + vamp:output plugbase:qm-dwt_output_wcoeff ; + . +plugbase:qm-dwt_param_scales a vamp:QuantizedParameter ; + vamp:identifier "scales" ; + dc:title "Scales" ; + dc:format "" ; + vamp:min_value 1 ; + vamp:max_value 16 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 10 ; + vamp:value_names (); + . +plugbase:qm-dwt_param_wavelet a vamp:QuantizedParameter ; + vamp:identifier "wavelet" ; + dc:title "Wavelet" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 42 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 0 ; + vamp:value_names ( "Haar" "Daubechies 2" "Daubechies 3" "Daubechies 4" "Daubechies 5" "Daubechies 6" "Daubechies 7" "Daubechies 8" "Daubechies 9" "Daubechies 10" "Daubechies 20" "Daubechies 40" "Symlet 2" "Symlet 3" "Symlet 4" "Symlet 5" "Symlet 6" "Symlet 7" "Symlet 8" "Symlet 9" "Symlet 10" "Symlet 20" "Symlet 30" "Coiflet 1" "Coiflet 2" "Coiflet 3" "Coiflet 4" "Coiflet 5" "Biorthogonal 1.3" "Biorthogonal 1.5" "Biorthogonal 2.2" "Biorthogonal 2.4" "Biorthogonal 2.6" "Biorthogonal 2.8" "Biorthogonal 3.1" "Biorthogonal 3.3" "Biorthogonal 3.5" "Biorthogonal 3.7" "Biorthogonal 3.9" "Biorthogonal 4.4" "Biorthogonal 5.5" "Biorthogonal 6.8" "Meyer"); + . +plugbase:qm-dwt_param_threshold a vamp:Parameter ; + vamp:identifier "threshold" ; + dc:title "Threshold" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 0.01 ; + vamp:unit "" ; + vamp:default_value 0 ; + vamp:value_names (); + . +plugbase:qm-dwt_param_absolute a vamp:QuantizedParameter ; + vamp:identifier "absolute" ; + dc:title "Absolute values" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 0 ; + vamp:value_names (); + . +plugbase:qm-dwt_output_wcoeff a vamp:DenseOutput ; + vamp:identifier "wcoeff" ; + dc:title "Wavelet Coefficients" ; + dc:description """Wavelet coefficients""" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 10 ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-keydetector a vamp:Plugin ; + dc:title "Key Detector" ; + vamp:name "Key Detector" ; + dc:description """Estimate the key of the music""" ; + foaf:page <http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html#qm-keydetector> ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Katy Noland and Christian Landone. Copyright (c) 2006-2009 QMUL - All Rights Reserved""" ; + vamp:identifier "qm-keydetector" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "4" ; + vamp:input_domain vamp:TimeDomain ; + + vamp:parameter plugbase:qm-keydetector_param_tuning ; + vamp:parameter plugbase:qm-keydetector_param_length ; + + vamp:output plugbase:qm-keydetector_output_tonic ; + vamp:output plugbase:qm-keydetector_output_mode ; + vamp:output plugbase:qm-keydetector_output_key ; + vamp:output plugbase:qm-keydetector_output_keystrength ; + . +plugbase:qm-keydetector_param_tuning a vamp:Parameter ; + vamp:identifier "tuning" ; + dc:title "Tuning Frequency" ; + dc:format "Hz" ; + vamp:min_value 420 ; + vamp:max_value 460 ; + vamp:unit "Hz" ; + vamp:default_value 440 ; + vamp:value_names (); + . +plugbase:qm-keydetector_param_length a vamp:QuantizedParameter ; + vamp:identifier "length" ; + dc:title "Window Length" ; + dc:format "chroma frames" ; + vamp:min_value 1 ; + vamp:max_value 30 ; + vamp:unit "chroma frames" ; + vamp:quantize_step 1 ; + vamp:default_value 10 ; + vamp:value_names (); + . +plugbase:qm-keydetector_output_tonic a vamp:SparseOutput ; + vamp:identifier "tonic" ; + dc:title "Tonic Pitch" ; + dc:description "Tonic of the estimated key (from C = 1 to B = 12)" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + a vamp:QuantizedOutput ; + vamp:quantize_step 1 ; + a vamp:KnownExtentsOutput ; + vamp:min_value 1 ; + vamp:max_value 12 ; + vamp:bin_count 1 ; + vamp:bin_names ( ""); + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 1.34583 ; +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-keydetector_output_mode a vamp:SparseOutput ; + vamp:identifier "mode" ; + dc:title "Key Mode" ; + dc:description "Major or minor mode of the estimated key (major = 0, minor = 1)" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + a vamp:QuantizedOutput ; + vamp:quantize_step 1 ; + a vamp:KnownExtentsOutput ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:bin_count 1 ; + vamp:bin_names ( ""); + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 1.34583 ; +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-keydetector_output_key a vamp:SparseOutput ; + vamp:identifier "key" ; + dc:title "Key" ; + dc:description "Estimated key (from C major = 1 to B major = 12 and C minor = 13 to B minor = 24)" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + a vamp:QuantizedOutput ; + vamp:quantize_step 1 ; + a vamp:KnownExtentsOutput ; + vamp:min_value 1 ; + vamp:max_value 24 ; + vamp:bin_count 1 ; + vamp:bin_names ( ""); + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 1.34583 ; + vamp:computes_event_type af:KeyChange ; + . +plugbase:qm-keydetector_output_keystrength a vamp:DenseOutput ; + vamp:identifier "keystrength" ; + dc:title "Key Strength Plot" ; + dc:description "Correlation of the chroma vector with stored key profile for each major and minor key" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 25 ; + vamp:bin_names ( "F# / Gb major" "B major" "E major" "A major" "D major" "G major" "C major" "F major" "Bb major" "Eb major" "Ab major" "Db major" " " "Eb / D# minor" "G# minor" "C# minor" "F# minor" "B minor" "E minor" "A minor" "D minor" "G minor" "C minor" "F minor" "Bb minor"); +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-mfcc a vamp:Plugin ; + dc:title "Mel-Frequency Cepstral Coefficients" ; + vamp:name "Mel-Frequency Cepstral Coefficients" ; + dc:description """Calculate a series of MFCC vectors from the audio""" ; + foaf:page <http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html#qm-mfcc> ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Nicolas Chetry and Chris Cannam. Copyright (c) 2009 QMUL - All Rights Reserved""" ; + vamp:identifier "qm-mfcc" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "1" ; + vamp:input_domain vamp:FrequencyDomain ; + + + vamp:parameter plugbase:qm-mfcc_param_nceps ; + vamp:parameter plugbase:qm-mfcc_param_logpower ; + vamp:parameter plugbase:qm-mfcc_param_wantc0 ; + + vamp:output plugbase:qm-mfcc_output_coefficients ; + vamp:output plugbase:qm-mfcc_output_means ; + . +plugbase:qm-mfcc_param_nceps a vamp:QuantizedParameter ; + vamp:identifier "nceps" ; + dc:title "Number of Coefficients" ; + dc:format "" ; + vamp:min_value 1 ; + vamp:max_value 40 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 20 ; + vamp:value_names (); + . +plugbase:qm-mfcc_param_logpower a vamp:Parameter ; + vamp:identifier "logpower" ; + dc:title "Power for Mel Amplitude Logs" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 5 ; + vamp:unit "" ; + vamp:default_value 1 ; + vamp:value_names (); + . +plugbase:qm-mfcc_param_wantc0 a vamp:QuantizedParameter ; + vamp:identifier "wantc0" ; + dc:title "Include C0" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 1 ; + vamp:value_names (); + . +plugbase:qm-mfcc_output_coefficients a vamp:DenseOutput ; + vamp:identifier "coefficients" ; + dc:title "Coefficients" ; + dc:description "MFCC values" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 20 ; + vamp:bin_names ( "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""); +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-mfcc_output_means a vamp:DenseOutput ; + vamp:identifier "means" ; + dc:title "Means of Coefficients" ; + dc:description "Mean values of MFCCs across duration of audio input" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 20 ; + vamp:bin_names ( "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""); +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-onsetdetector a vamp:Plugin ; + dc:title "Note Onset Detector" ; + vamp:name "Note Onset Detector" ; + dc:description """Estimate individual note onset positions""" ; + foaf:page <http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html#qm-onsetdetector> ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Christian Landone, Chris Duxbury and Juan Pablo Bello. Copyright (c) 2006-2009 QMUL - All Rights Reserved""" ; + vamp:identifier "qm-onsetdetector" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "2" ; + vamp:input_domain vamp:FrequencyDomain ; + + + vamp:parameter plugbase:qm-onsetdetector_param_dftype ; + vamp:parameter plugbase:qm-onsetdetector_param_sensitivity ; + vamp:parameter plugbase:qm-onsetdetector_param_whiten ; + + vamp:output plugbase:qm-onsetdetector_output_onsets ; + vamp:output plugbase:qm-onsetdetector_output_detection_fn ; + vamp:output plugbase:qm-onsetdetector_output_smoothed_df ; + . +plugbase:qm-onsetdetector_param_dftype a vamp:QuantizedParameter ; + vamp:identifier "dftype" ; + dc:title "Onset Detection Function Type" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 4 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 3 ; + vamp:value_names ( "High-Frequency Content" "Spectral Difference" "Phase Deviation" "Complex Domain" "Broadband Energy Rise"); + . +plugbase:qm-onsetdetector_param_sensitivity a vamp:QuantizedParameter ; + vamp:identifier "sensitivity" ; + dc:title "Onset Detector Sensitivity" ; + dc:format "%" ; + vamp:min_value 0 ; + vamp:max_value 100 ; + vamp:unit "%" ; + vamp:quantize_step 1 ; + vamp:default_value 50 ; + vamp:value_names (); + . +plugbase:qm-onsetdetector_param_whiten a vamp:QuantizedParameter ; + vamp:identifier "whiten" ; + dc:title "Adaptive Whitening" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 0 ; + vamp:value_names (); + . +plugbase:qm-onsetdetector_output_onsets a vamp:SparseOutput ; + vamp:identifier "onsets" ; + dc:title "Note Onsets" ; + dc:description "Perceived note onset positions" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 0 ; + vamp:bin_names (); + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 86.1326 ; + vamp:computes_event_type af:Onset; + . +plugbase:qm-onsetdetector_output_detection_fn a vamp:DenseOutput ; + vamp:identifier "detection_fn" ; + dc:title "Onset Detection Function" ; + dc:description "Probability function of note onset likelihood" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 1 ; + vamp:bin_names ( ""); + vamp:computes_signal_type af:OnsetDetectionFunction ; + . +plugbase:qm-onsetdetector_output_smoothed_df a vamp:SparseOutput ; + vamp:identifier "smoothed_df" ; + dc:title "Smoothed Detection Function" ; + dc:description "Smoothed probability function used for peak-picking" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 1 ; + vamp:bin_names ( ""); + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 86.1326 ; + vamp:computes_signal_type af:OnsetDetectionFunction ; + . +plugbase:qm-segmenter a vamp:Plugin ; + dc:title "Segmenter" ; + vamp:name "Segmenter" ; + dc:description """Divide the track into a sequence of consistent segments""" ; + foaf:page <http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html#qm-segmenter> ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Mark Levy. Copyright (c) 2006-2009 QMUL - All Rights Reserved""" ; + vamp:identifier "qm-segmenter" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "2" ; + vamp:input_domain vamp:TimeDomain ; + + vamp:parameter plugbase:qm-segmenter_param_nSegmentTypes ; + vamp:parameter plugbase:qm-segmenter_param_featureType ; + vamp:parameter plugbase:qm-segmenter_param_neighbourhoodLimit ; + + vamp:output plugbase:qm-segmenter_output_segmentation ; + . +plugbase:qm-segmenter_param_nSegmentTypes a vamp:QuantizedParameter ; + vamp:identifier "nSegmentTypes" ; + dc:title "Number of segment-types" ; + dc:format "" ; + vamp:min_value 2 ; + vamp:max_value 12 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 10 ; + vamp:value_names (); + . +plugbase:qm-segmenter_param_featureType a vamp:QuantizedParameter ; + vamp:identifier "featureType" ; + dc:title "Feature Type" ; + dc:format "" ; + vamp:min_value 1 ; + vamp:max_value 3 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 1 ; + vamp:value_names ( "Hybrid (Constant-Q)" "Chromatic (Chroma)" "Timbral (MFCC)"); + . +plugbase:qm-segmenter_param_neighbourhoodLimit a vamp:QuantizedParameter ; + vamp:identifier "neighbourhoodLimit" ; + dc:title "Minimum segment duration" ; + dc:format "s" ; + vamp:min_value 1 ; + vamp:max_value 15 ; + vamp:unit "s" ; + vamp:quantize_step 0.2 ; + vamp:default_value 4 ; + vamp:value_names (); + . +plugbase:qm-segmenter_output_segmentation a vamp:SparseOutput ; + vamp:identifier "segmentation" ; + dc:title "Segmentation" ; + dc:description "Segmentation" ; + vamp:fixed_bin_count "true" ; + vamp:unit "segment-type" ; + a vamp:QuantizedOutput ; + vamp:quantize_step 1 ; + a vamp:KnownExtentsOutput ; + vamp:min_value 1 ; + vamp:max_value 10 ; + vamp:bin_count 1 ; + vamp:bin_names ( ""); + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 5 ; + vamp:computes_event_type af:StructuralSegment ; + . +plugbase:qm-similarity a vamp:Plugin ; + dc:title "Similarity" ; + vamp:name "Similarity" ; + dc:description """Return a distance matrix for similarity between the input audio channels""" ; + foaf:page <http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html#qm-similarity> ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Mark Levy, Kurt Jacobson and Chris Cannam. Copyright (c) 2009 QMUL - All Rights Reserved""" ; + vamp:identifier "qm-similarity" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "1" ; + vamp:input_domain vamp:TimeDomain ; + + vamp:parameter plugbase:qm-similarity_param_featureType ; + + vamp:output plugbase:qm-similarity_output_distancematrix ; + vamp:output plugbase:qm-similarity_output_distancevector ; + vamp:output plugbase:qm-similarity_output_sorteddistancevector ; + vamp:output plugbase:qm-similarity_output_means ; + vamp:output plugbase:qm-similarity_output_variances ; + vamp:output plugbase:qm-similarity_output_beatspectrum ; + . +plugbase:qm-similarity_param_featureType a vamp:QuantizedParameter ; + vamp:identifier "featureType" ; + dc:title "Feature Type" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 4 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 1 ; + vamp:value_names ( "Timbre" "Timbre and Rhythm" "Chroma" "Chroma and Rhythm" "Rhythm only"); + . +plugbase:qm-similarity_output_distancematrix a vamp:DenseOutput ; + vamp:identifier "distancematrix" ; + dc:title "Distance Matrix" ; + dc:description "Distance matrix for similarity metric. Smaller = more similar. Should be symmetrical." ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 0 ; + vamp:bin_names (); +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-similarity_output_distancevector a vamp:DenseOutput ; + vamp:identifier "distancevector" ; + dc:title "Distance from First Channel" ; + dc:description "Distance vector for similarity of each channel to the first channel. Smaller = more similar." ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 0 ; + vamp:bin_names (); +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-similarity_output_sorteddistancevector a vamp:DenseOutput ; + vamp:identifier "sorteddistancevector" ; + dc:title "Ordered Distances from First Channel" ; + dc:description "Vector of the order of other channels in similarity to the first, followed by distance vector for similarity of each to the first. Smaller = more similar." ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 0 ; + vamp:bin_names (); +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-similarity_output_means a vamp:DenseOutput ; + vamp:identifier "means" ; + dc:title "Feature Means" ; + dc:description "Means of the feature bins. Feature time (sec) corresponds to input channel. Number of bins depends on selected feature type." ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 20 ; + vamp:bin_names ( "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""); +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-similarity_output_variances a vamp:DenseOutput ; + vamp:identifier "variances" ; + dc:title "Feature Variances" ; + dc:description "Variances of the feature bins. Feature time (sec) corresponds to input channel. Number of bins depends on selected feature type." ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 20 ; + vamp:bin_names ( "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""); +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-similarity_output_beatspectrum a vamp:SparseOutput ; + vamp:identifier "beatspectrum" ; + dc:title "Beat Spectra" ; + dc:description "Rhythmic self-similarity vectors (beat spectra) for the input channels. Feature time (sec) corresponds to input channel. Not returned if rhythm weighting is zero." ; + vamp:fixed_bin_count "false" ; + vamp:unit "" ; + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 1 ; +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:qm-tempotracker a vamp:Plugin ; + dc:title "Tempo and Beat Tracker" ; + vamp:name "Tempo and Beat Tracker" ; + dc:description """Estimate beat locations and tempo""" ; + foaf:page <http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html#qm-tempotracker> ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Christian Landone and Matthew Davies. Copyright (c) 2006-2009 QMUL - All Rights Reserved""" ; + vamp:identifier "qm-tempotracker" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "4" ; + vamp:input_domain vamp:FrequencyDomain ; + + + vamp:parameter plugbase:qm-tempotracker_param_method ; + vamp:parameter plugbase:qm-tempotracker_param_dftype ; + vamp:parameter plugbase:qm-tempotracker_param_whiten ; + + vamp:output plugbase:qm-tempotracker_output_beats ; + vamp:output plugbase:qm-tempotracker_output_detection_fn ; + vamp:output plugbase:qm-tempotracker_output_tempo ; + . +plugbase:qm-tempotracker_param_method a vamp:QuantizedParameter ; + vamp:identifier "method" ; + dc:title "Beat Tracking Method" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 1 ; + vamp:value_names ( "Old" "New"); + . +plugbase:qm-tempotracker_param_dftype a vamp:QuantizedParameter ; + vamp:identifier "dftype" ; + dc:title "Onset Detection Function Type" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 4 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 3 ; + vamp:value_names ( "High-Frequency Content" "Spectral Difference" "Phase Deviation" "Complex Domain" "Broadband Energy Rise"); + . +plugbase:qm-tempotracker_param_whiten a vamp:QuantizedParameter ; + vamp:identifier "whiten" ; + dc:title "Adaptive Whitening" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 0 ; + vamp:value_names (); + . +plugbase:qm-tempotracker_output_beats a vamp:SparseOutput ; + vamp:identifier "beats" ; + dc:title "Beats" ; + dc:description "Estimated metrical beat locations" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 0 ; + vamp:bin_names (); + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 86.1326 ; + vamp:computes_event_type af:Beat; + . +plugbase:qm-tempotracker_output_detection_fn a vamp:DenseOutput ; + vamp:identifier "detection_fn" ; + dc:title "Onset Detection Function" ; + dc:description "Probability function of note onset likelihood" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 1 ; + vamp:bin_names ( ""); + vamp:computes_signal_type af:OnsetDetectionFunction; + . +plugbase:qm-tempotracker_output_tempo a vamp:SparseOutput ; + vamp:identifier "tempo" ; + dc:title "Tempo" ; + dc:description "Locked tempo estimates" ; + vamp:fixed_bin_count "true" ; + vamp:unit "bpm" ; + vamp:bin_count 1 ; + vamp:bin_names ( ""); + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 86.1326 ; + vamp:computes_event_type af:Tempo ; + . +plugbase:qm-tonalchange a vamp:Plugin ; + dc:title "Tonal Change" ; + vamp:name "Tonal Change" ; + dc:description """Detect and return the positions of harmonic changes such as chord boundaries""" ; + foaf:page <http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html#qm-tonalchange> ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Martin Gasser and Christopher Harte. Copyright (c) 2006-2009 QMUL - All Rights Reserved""" ; + vamp:identifier "qm-tonalchange" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "1" ; + vamp:input_domain vamp:TimeDomain ; + + vamp:parameter plugbase:qm-tonalchange_param_smoothingwidth ; + vamp:parameter plugbase:qm-tonalchange_param_minpitch ; + vamp:parameter plugbase:qm-tonalchange_param_maxpitch ; + vamp:parameter plugbase:qm-tonalchange_param_tuning ; + + vamp:output plugbase:qm-tonalchange_output_tcstransform ; + vamp:output plugbase:qm-tonalchange_output_tcfunction ; + vamp:output plugbase:qm-tonalchange_output_changepositions ; + . +plugbase:qm-tonalchange_param_smoothingwidth a vamp:QuantizedParameter ; + vamp:identifier "smoothingwidth" ; + dc:title "Gaussian smoothing" ; + dc:format "frames" ; + vamp:min_value 0 ; + vamp:max_value 20 ; + vamp:unit "frames" ; + vamp:quantize_step 1 ; + vamp:default_value 5 ; + vamp:value_names (); + . +plugbase:qm-tonalchange_param_minpitch a vamp:QuantizedParameter ; + vamp:identifier "minpitch" ; + dc:title "Chromagram minimum pitch" ; + dc:format "MIDI units" ; + vamp:min_value 0 ; + vamp:max_value 127 ; + vamp:unit "MIDI units" ; + vamp:quantize_step 1 ; + vamp:default_value 32 ; + vamp:value_names (); + . +plugbase:qm-tonalchange_param_maxpitch a vamp:QuantizedParameter ; + vamp:identifier "maxpitch" ; + dc:title "Chromagram maximum pitch" ; + dc:format "MIDI units" ; + vamp:min_value 0 ; + vamp:max_value 127 ; + vamp:unit "MIDI units" ; + vamp:quantize_step 1 ; + vamp:default_value 108 ; + vamp:value_names (); + . +plugbase:qm-tonalchange_param_tuning a vamp:Parameter ; + vamp:identifier "tuning" ; + dc:title "Chromagram tuning frequency" ; + dc:format "Hz" ; + vamp:min_value 420 ; + vamp:max_value 460 ; + vamp:unit "Hz" ; + vamp:default_value 440 ; + vamp:value_names (); + . +plugbase:qm-tonalchange_output_tcstransform a vamp:DenseOutput ; + vamp:identifier "tcstransform" ; + dc:title "Transform to 6D Tonal Content Space" ; + dc:description "" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + a vamp:KnownExtentsOutput ; + vamp:min_value -1 ; + vamp:max_value 1 ; + vamp:bin_count 6 ; + vamp:bin_names ( "" "" "" "" "" ""); + vamp:computes_signal_type af:TonalContentSpace; + . +plugbase:qm-tonalchange_output_tcfunction a vamp:SparseOutput ; + vamp:identifier "tcfunction" ; + dc:title "Tonal Change Detection Function" ; + dc:description "" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 1 ; + vamp:bin_names ( ""); + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 21.5332 ; + vamp:computes_signal_type af:TonalChangeDetectionFunction; + . +plugbase:qm-tonalchange_output_changepositions a vamp:SparseOutput ; + vamp:identifier "changepositions" ; + dc:title "Tonal Change Positions" ; + dc:description "" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 0 ; + vamp:bin_names (); + vamp:sample_type vamp:VariableSampleRate ; + vamp:sample_rate 21.5332 ; + vamp:computes_event_type af:TonalOnset; + . +plugbase:qm-transcription a vamp:Plugin ; + dc:title "Polyphonic Transcription" ; + vamp:name "Polyphonic Transcription" ; + dc:description """Transcribe the input audio to estimated notes""" ; + foaf:page <http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html#qm-transcription> ; + foaf:maker [ foaf:name "Queen Mary, University of London" ] ; # FIXME could give plugin author's URI here + dc:rights """Plugin by Dr. Ruohua Zhou. Copyright (c) 2008-2009 QMUL - All Rights Reserved""" ; + vamp:identifier "qm-transcription" ; + vamp:vamp_API_version vamp:api_version_2 ; + owl:versionInfo "1" ; + vamp:input_domain vamp:TimeDomain ; + vamp:output plugbase:qm-transcription_output_transcription ; + . +plugbase:qm-transcription_output_transcription a vamp:SparseOutput ; + vamp:identifier "transcription" ; + dc:title "Transcription" ; + dc:description """Estimated note pitch (MIDI note number from 0 to 127)""" ; + vamp:fixed_bin_count "true" ; + vamp:unit "MIDI units" ; + a vamp:QuantizedOutput ; + vamp:quantize_step 1 ; + a vamp:KnownExtentsOutput ; + vamp:min_value 0 ; + vamp:max_value 127 ; + vamp:bin_count 1 ; + vamp:sample_type vamp:VariableSampleRate ; + vamp:computes_event_type af:Note ; + . + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/qm-vamp-plugins.pro Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,87 @@ + +TEMPLATE = lib +CONFIG += plugin warn_on release +CONFIG -= qt + +linux-g++* { + QMAKE_CXXFLAGS_RELEASE += -DNDEBUG -O3 -fno-exceptions -fPIC -ffast-math -msse -mfpmath=sse -ftree-vectorize -fomit-frame-pointer + DEFINES += USE_PTHREADS + INCLUDEPATH += ../vamp-plugin-sdk ../qm-dsp + LIBPATH += ../vamp-plugin-sdk ../qm-dsp +} + +linux-g++ { + LIBS += -static-libgcc -Wl,-Bstatic -lqm-dsp -lvamp-sdk -L/usr/lib/sse2/atlas -L/usr/lib/atlas/sse -llapack -lblas $$system(g++ -print-file-name=libstdc++.a) -lc -Wl,-Bdynamic -lpthread -Wl,--version-script=vamp-plugin.map +} + +linux-g++-64 { + QMAKE_CXXFLAGS_RELEASE += -msse2 + LIBS += -Lbuild/linux/amd64 -Wl,-Bstatic -lqm-dsp -lvamp-sdk -llapack -lcblas -latlas -lc -Wl,-Bdynamic -lpthread -Wl,--version-script=vamp-plugin.map +} + +macx-g++* { + QMAKE_MAC_SDK=/Developer/SDKs/MacOSX10.4u.sdk + QMAKE_CXXFLAGS_RELEASE += -mmacosx-version-min=10.4 -O2 -g0 + QMAKE_CFLAGS_RELEASE += -mmacosx-version-min=10.4 + CONFIG += x86 ppc x86_64 + QMAKE_CXX = g++-4.0 + QMAKE_CC = gcc-4.0 + QMAKE_LINK = g++-4.0 + DEFINES += USE_PTHREADS + LIBS += -mmacosx-version-min=10.4 -lqm-dsp -L../inst/lib -lvamp-sdk -framework Accelerate -lpthread -exported_symbols_list vamp-plugin.list + INCLUDEPATH += ../vamp-plugin-sdk ../qm-dsp + LIBPATH += ../include ../lib ../qm-dsp +} + +win32-x-g++ { + QMAKE_CXXFLAGS_RELEASE += -DNDEBUG -O2 -march=pentium3 -msse + INCLUDEPATH += ../include ../qm-dsp + LIBPATH += ./build/mingw32 ../lib ../qm-dsp ../qm-dsp/release + LIBS += -shared -Wl,-Bstatic -lqm-dsp -lvamp-sdk -llapack -lcblas -latlas -lf77blas -lg2cstubs -Wl,-Bdynamic -Wl,--version-script=vamp-plugin.map +} + +solaris* { + QMAKE_CXXFLAGS_RELEASE += -DNDEBUG -fast + INCLUDEPATH += /usr/local/include ../qm-dsp + INCLUDEPATH += /opt/ATLAS3.9.14/include + LIBPATH += ../qm-dsp /opt/ATLAS3.9.14/lib + DEFINES += USE_PTHREADS + LIBS += -Bstatic -lqm-dsp -lvamp-sdk -llapack -lcblas -latlas -Bdynamic -lpthread -Wl,--version-script=vamp-plugin.map -lCstd -lCrun +} + +OBJECTS_DIR = tmp_obj +MOC_DIR = tmp_moc + +DEPENDPATH += plugins +INCLUDEPATH += . plugins + +# Input +HEADERS += plugins/AdaptiveSpectrogram.h \ + plugins/BarBeatTrack.h \ + plugins/BeatTrack.h \ + plugins/DWT.h \ + plugins/OnsetDetect.h \ + plugins/ChromagramPlugin.h \ + plugins/ConstantQSpectrogram.h \ + plugins/KeyDetect.h \ + plugins/MFCCPlugin.h \ + plugins/SegmenterPlugin.h \ + plugins/SimilarityPlugin.h \ + plugins/TonalChangeDetect.h \ + plugins/Transcription.h +SOURCES += g2cstubs.c \ + plugins/AdaptiveSpectrogram.cpp \ + plugins/BarBeatTrack.cpp \ + plugins/BeatTrack.cpp \ + plugins/DWT.cpp \ + plugins/OnsetDetect.cpp \ + plugins/ChromagramPlugin.cpp \ + plugins/ConstantQSpectrogram.cpp \ + plugins/KeyDetect.cpp \ + plugins/MFCCPlugin.cpp \ + plugins/SegmenterPlugin.cpp \ + plugins/SimilarityPlugin.cpp \ + plugins/TonalChangeDetect.cpp \ + plugins/Transcription.cpp \ + ./libmain.cpp +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/songparts/valgrinder.sh Wed Apr 11 09:31:28 2012 +0100 @@ -0,0 +1,15 @@ +#!/bin/sh +ids=`VAMP_PATH=. vamp-simple-host --list-ids` +testfile=$1 +if [ ! -f "$testfile" ]; then + echo "Usage: valgrinder.sh <testfile.wav>" + exit 2 +fi +for id in $ids; do + id=`echo $id | sed 's/^vamp://'` + echo + echo "Testing $id on $testfile..." + echo + VAMP_PATH=. valgrind vamp-simple-host "$id" "$testfile" -o /dev/null + echo +done