Mercurial > hg > tuning-difference
changeset 21:d660db57e902
Rearrange code, include subrepo etc
author | Chris Cannam |
---|---|
date | Thu, 05 Feb 2015 10:13:31 +0000 |
parents | 331a520cdadb |
children | de942cbe5b27 |
files | .hgsub .hgsubstate COPYING Makefile.inc Makefile.linux Makefile.mingw32 Makefile.osx README chroma-compare-plugin/Makefile.inc chroma-compare-plugin/Makefile.linux chroma-compare-plugin/Makefile.mingw32 chroma-compare-plugin/Makefile.osx chroma-compare-plugin/TuningDifference.cpp chroma-compare-plugin/TuningDifference.h chroma-compare-plugin/plugins.cpp chroma-compare-plugin/vamp-plugin.list chroma-compare-plugin/vamp-plugin.map iterative-chroma/chroma-excerpt.ttl iterative-chroma/chromacompare.sh iterative-match/match-cost.ttl iterative-match/matchcompare.sh spectrum-compare-plugin/Makefile.inc spectrum-compare-plugin/Makefile.linux spectrum-compare-plugin/Makefile.mingw32 spectrum-compare-plugin/Makefile.osx spectrum-compare-plugin/TuningDifference.cpp spectrum-compare-plugin/TuningDifference.h spectrum-compare-plugin/plugins.cpp spectrum-compare-plugin/vamp-plugin.list spectrum-compare-plugin/vamp-plugin.map src/TuningDifference.cpp src/TuningDifference.h src/plugins.cpp tuning-and-key/keycompare.sh tuning-and-key/keydetector.ttl vamp-plugin.list vamp-plugin.map |
diffstat | 37 files changed, 1018 insertions(+), 1634 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgsub Thu Feb 05 10:13:31 2015 +0000 @@ -0,0 +1,1 @@ +constant-q-cpp = https://code.soundsoftware.ac.uk/hg/constant-q-cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgsubstate Thu Feb 05 10:13:31 2015 +0000 @@ -0,0 +1,1 @@ +25ff58cc00be316d9a32e232a78a00e9374e0433 constant-q-cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/COPYING Thu Feb 05 10:13:31 2015 +0000 @@ -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/Makefile.inc Thu Feb 05 10:13:31 2015 +0000 @@ -0,0 +1,60 @@ + +# Edit this to the base name of your plugin library +# +PLUGIN_LIBRARY_NAME := tuning-difference + +# Edit this to list the .cpp or .c files in your plugin project +# +PLUGIN_SOURCES := src/TuningDifference.cpp src/plugins.cpp + +# Edit this to list the .h files in your plugin project +# +PLUGIN_HEADERS := src/TuningDifference.h + + +## Normally you should not edit anything below this line + +SRC_DIR := . + +CFLAGS := $(ARCHFLAGS) $(CFLAGS) +CXXFLAGS := $(CFLAGS) -I. -I$(VAMPSDK_DIR) -Iconstant-q-cpp $(CXXFLAGS) + +LDFLAGS := $(ARCHFLAGS) $(LDFLAGS) -Lconstant-q-cpp -lcq +PLUGIN_LDFLAGS := $(LDFLAGS) $(PLUGIN_LDFLAGS) + +# Defaults, overridden from the platform-specific Makefile +VAMPSDK_DIR ?= ../vamp-plugin-sdk +PLUGIN_EXT ?= .so +CXX ?= g++ +CC ?= gcc + +PLUGIN := $(PLUGIN_LIBRARY_NAME)$(PLUGIN_EXT) + +PLUGIN_OBJECTS := $(PLUGIN_SOURCES:.cpp=.o) +PLUGIN_OBJECTS := $(PLUGIN_OBJECTS:.c=.o) + +all: constant-q-cpp $(PLUGIN) + +.PHONY: constant-q-cpp +constant-q-cpp: + $(MAKE) -C $@ -f Makefile$(MAKEFILE_EXT) libcq.a + +$(PLUGIN): $(PLUGIN_OBJECTS) + $(CXX) -o $@ $^ $(PLUGIN_LDFLAGS) + +$(PLUGIN_OBJECTS): $(PLUGIN_HEADERS) + +clean: + rm -f $(PLUGIN_OBJECTS) + $(MAKE) -C constant-q-cpp -f Makefile$(MAKEFILE_EXT) clean + +distclean: clean + rm -f $(PLUGIN) + +depend: + makedepend -Y -fMakefile.inc $(PLUGIN_SOURCES) $(PLUGIN_HEADERS) + +# DO NOT DELETE + +src/TuningDifference.o: src/TuningDifference.h +src/plugins.o: src/TuningDifference.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile.linux Thu Feb 05 10:13:31 2015 +0000 @@ -0,0 +1,16 @@ + +#CXXFLAGS := -Wall -Wextra -Werror -g -fPIC -std=c++11 + +CXXFLAGS := -Wall -Wextra -Werror -O3 -msse -msse2 -mfpmath=sse -ftree-vectorize -fPIC -std=c++11 + +VAMPSDK_DIR := ../vamp-plugin-sdk + +PLUGIN_LDFLAGS := -shared -Wl,-Bsymbolic -Wl,-z,defs -Wl,--version-script=vamp-plugin.map $(VAMPSDK_DIR)/libvamp-sdk.a + +PLUGIN_EXT := .so + +MAKEFILE_EXT := .linux + +include Makefile.inc + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile.mingw32 Thu Feb 05 10:13:31 2015 +0000 @@ -0,0 +1,21 @@ + +TOOLPREFIX ?= +CXX = $(TOOLPREFIX)g++ +CC = $(TOOLPREFIX)gcc +LD = $(TOOLPREFIX)g++ +AR = $(TOOLPREFIX)ar +RANLIB = $(TOOLPREFIX)ranlib + +#CFLAGS := -Wall -Wextra -g + +CFLAGS := -Wall -Wextra -O3 -ftree-vectorize + +VAMPSDK_DIR := ../vamp-plugin-sdk + +PLUGIN_LDFLAGS := -shared -static -Wl,--retain-symbols-file=vamp-plugin.list $(VAMPSDK_DIR)/libvamp-sdk.a + +PLUGIN_EXT := .dll + +MAKEFILE_EXT := .mingw32 + +include Makefile.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile.osx Thu Feb 05 10:13:31 2015 +0000 @@ -0,0 +1,18 @@ + +#CFLAGS := -Wall -Wextra -g -fPIC + +CFLAGS := -Wall -Wextra -O3 -ftree-vectorize -fPIC + +ARCHFLAGS ?= -mmacosx-version-min=10.6 -arch x86_64 -arch i386 + +VAMPSDK_DIR := ../vamp-plugin-sdk + +PLUGIN_LDFLAGS := -dynamiclib -exported_symbols_list vamp-plugin.list $(VAMPSDK_DIR)/libvamp-sdk.a + +PLUGIN_EXT := .dylib + +MAKEFILE_EXT := .osx + +include Makefile.inc + +
--- a/README Thu Feb 05 09:52:28 2015 +0000 +++ b/README Thu Feb 05 10:13:31 2015 +0000 @@ -1,4 +1,20 @@ -The successful attempt is in chroma-compare-plugin. It's very slow, -will be working on that. +Plugin to calculate comparative tuning of recordings +---------------------------------------------------- +This plugin estimates the tuning frequency (concert-A) of a recording, +by comparing it with a "reference" recording of the same music that +has a known tuning frequency. The aim is to identify the tuning +frequency of the unknown recording even in difficult cases, such as +where A is tuned more than a semitone below 440Hz. + +The reference recording could be another performance at known pitch +or, for example, a MIDI rendering at 440Hz. The two recordings must be +in the same key. + +The plugin expects to receive the two recordings of the same piece of +music as its two channels of input. (You can provide these using the +--multiplex option in Sonic Annotator, for example.) If you just feed +it a single piece of music, it will probably estimate that it has the +same tuning frequency as itself! +
--- a/chroma-compare-plugin/Makefile.inc Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ - -# Edit this to the base name of your plugin library -# -PLUGIN_LIBRARY_NAME := tuning-difference - -# Edit this to list the .cpp or .c files in your plugin project -# -PLUGIN_SOURCES := TuningDifference.cpp plugins.cpp - -# Edit this to list the .h files in your plugin project -# -PLUGIN_HEADERS := TuningDifference.h - - -## Normally you should not edit anything below this line - -SRC_DIR := . - -CFLAGS := $(ARCHFLAGS) $(CFLAGS) -CXXFLAGS := $(CFLAGS) -I. -I$(VAMPSDK_DIR) -I../../constant-q-cpp $(CXXFLAGS) - -LDFLAGS := $(ARCHFLAGS) $(LDFLAGS) -L../../constant-q-cpp -lcq -PLUGIN_LDFLAGS := $(LDFLAGS) $(PLUGIN_LDFLAGS) - -# Defaults, overridden from the platform-specific Makefile -VAMPSDK_DIR ?= ../vamp-plugin-sdk -PLUGIN_EXT ?= .so -CXX ?= g++ -CC ?= gcc - -PLUGIN := $(PLUGIN_LIBRARY_NAME)$(PLUGIN_EXT) - -PLUGIN_OBJECTS := $(PLUGIN_SOURCES:.cpp=.o) -PLUGIN_OBJECTS := $(PLUGIN_OBJECTS:.c=.o) - -$(PLUGIN): $(PLUGIN_OBJECTS) - $(CXX) -o $@ $^ $(PLUGIN_LDFLAGS) - -$(PLUGIN_OBJECTS): $(PLUGIN_HEADERS) - -clean: - rm -f $(PLUGIN_OBJECTS) - -distclean: clean - rm -f $(PLUGIN) - -depend: - makedepend -Y -fMakefile.inc $(PLUGIN_SOURCES) $(PLUGIN_HEADERS) - -# DO NOT DELETE - -TuningDifference.o: TuningDifference.h -plugins.o: TuningDifference.h
--- a/chroma-compare-plugin/Makefile.linux Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ - -# For a debug build... - -#CXXFLAGS := -Wall -Wextra -Werror -g -fPIC -std=c++11 - -# ... or for a release build - -CXXFLAGS := -Wall -Wextra -Werror -O3 -msse -msse2 -mfpmath=sse -ftree-vectorize -fPIC -std=c++11 - - -# Location of Vamp plugin SDK relative to the project directory - -VAMPSDK_DIR := ../../vamp-plugin-sdk - - -# Libraries and linker flags required by plugin: add any -l<library> -# options here - -PLUGIN_LDFLAGS := -shared -Wl,-Bsymbolic -Wl,-z,defs -Wl,--version-script=vamp-plugin.map $(VAMPSDK_DIR)/libvamp-sdk.a - - -# File extension for plugin library on this platform - -PLUGIN_EXT := .so - - -include Makefile.inc - -
--- a/chroma-compare-plugin/Makefile.mingw32 Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ - -## Makefile for Vamp plugin using MinGW tools on Windows. -## -## Edit this to adjust compiler and library settings when -## building using MinGW. -## -## Note that the list of source files, etc, goes in Makefile.inc -## instead so that it can be included by all platform Makefiles. - -TOOLPREFIX ?= -CXX = $(TOOLPREFIX)g++ -CC = $(TOOLPREFIX)gcc -LD = $(TOOLPREFIX)g++ -AR = $(TOOLPREFIX)ar -RANLIB = $(TOOLPREFIX)ranlib - - -# For a debug build... - -CFLAGS := -Wall -Wextra -g - -# ... or for a release build - -#CFLAGS := -Wall -Wextra -O3 -ftree-vectorize - - -# Location of Vamp plugin SDK relative to the project directory - -VAMPSDK_DIR := ../vamp-plugin-sdk - - -# Libraries and linker flags required by plugin: add any -l<library> -# options here - -PLUGIN_LDFLAGS := -shared -static -Wl,--retain-symbols-file=vamp-plugin.list $(VAMPSDK_DIR)/libvamp-sdk.a - - -# File extension for plugin library on this platform - -PLUGIN_EXT := .dll - - -include Makefile.inc
--- a/chroma-compare-plugin/Makefile.osx Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ - -## Makefile for Vamp plugin using command-line tools on OS/X. -## -## Edit this to adjust compiler and library settings when -## building for OS/X. -## -## Note that the list of source files, etc, goes in Makefile.inc -## instead so that it can be included by all platform Makefiles. - - -# For a debug build... - -CFLAGS := -Wall -Wextra -g -fPIC - -# ... or for a release build - -#CFLAGS := -Wall -Wextra -O3 -ftree-vectorize -fPIC - - -# Flags to determine processor architecture and system SDK - -ARCHFLAGS ?= -mmacosx-version-min=10.6 -arch x86_64 -arch i386 - - -# Location of Vamp plugin SDK relative to the project directory - -VAMPSDK_DIR := ../vamp-plugin-sdk - - -# Libraries and linker flags required by plugin: add any -l<library> -# options here - -PLUGIN_LDFLAGS := -dynamiclib -exported_symbols_list vamp-plugin.list $(VAMPSDK_DIR)/libvamp-sdk.a - - -# File extension for plugin library on this platform - -PLUGIN_EXT := .dylib - - -include Makefile.inc - -
--- a/chroma-compare-plugin/TuningDifference.cpp Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,481 +0,0 @@ - -#include "TuningDifference.h" - -#include <iostream> - -#include <cmath> -#include <cstdio> - -#include <algorithm> - -using namespace std; - -static double pitchToFrequency(int pitch, - double centsOffset = 0., - double concertA = 440.) -{ - double p = double(pitch) + (centsOffset / 100.); - return concertA * pow(2.0, (p - 69.0) / 12.0); -} - -static double frequencyForCentsAbove440(double cents) -{ - return pitchToFrequency(69, cents, 440.); -} - -TuningDifference::TuningDifference(float inputSampleRate) : - Plugin(inputSampleRate), - m_bpo(60), - m_refChroma(new Chromagram(paramsForTuningFrequency(440.))), - m_blockSize(0), - m_frameCount(0) -{ -} - -TuningDifference::~TuningDifference() -{ -} - -string -TuningDifference::getIdentifier() const -{ - return "tuning-difference"; -} - -string -TuningDifference::getName() const -{ - return "Tuning Difference"; -} - -string -TuningDifference::getDescription() const -{ - // Return something helpful here! - return ""; -} - -string -TuningDifference::getMaker() const -{ - // Your name here - return ""; -} - -int -TuningDifference::getPluginVersion() const -{ - // Increment this each time you release a version that behaves - // differently from the previous one - return 1; -} - -string -TuningDifference::getCopyright() const -{ - // This function is not ideally named. It does not necessarily - // need to say who made the plugin -- getMaker does that -- but it - // should indicate the terms under which it is distributed. For - // example, "Copyright (year). All Rights Reserved", or "GPL" - return ""; -} - -TuningDifference::InputDomain -TuningDifference::getInputDomain() const -{ - return TimeDomain; -} - -size_t -TuningDifference::getPreferredBlockSize() const -{ - return 0; -} - -size_t -TuningDifference::getPreferredStepSize() const -{ - return 0; -} - -size_t -TuningDifference::getMinChannelCount() const -{ - return 2; -} - -size_t -TuningDifference::getMaxChannelCount() const -{ - return 2; -} - -TuningDifference::ParameterList -TuningDifference::getParameterDescriptors() const -{ - ParameterList list; - //!!! parameter: max search range - //!!! parameter: fine search precision - return list; -} - -float -TuningDifference::getParameter(string) const -{ - return 0; -} - -void -TuningDifference::setParameter(string, float) -{ -} - -TuningDifference::ProgramList -TuningDifference::getPrograms() const -{ - ProgramList list; - return list; -} - -string -TuningDifference::getCurrentProgram() const -{ - return ""; // no programs -} - -void -TuningDifference::selectProgram(string) -{ -} - -TuningDifference::OutputList -TuningDifference::getOutputDescriptors() const -{ - OutputList list; - - OutputDescriptor d; - d.identifier = "cents"; - d.name = "Tuning Difference"; - d.description = "Difference in averaged frequency profile between channels 1 and 2, in cents. A positive value means channel 2 is higher."; - d.unit = "cents"; - d.hasFixedBinCount = true; - d.binCount = 1; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleType = OutputDescriptor::VariableSampleRate; - d.hasDuration = false; - m_outputs[d.identifier] = list.size(); - list.push_back(d); - - d.identifier = "tuningfreq"; - d.name = "Relative Tuning Frequency"; - d.description = "Tuning frequency of channel 2, if channel 1 is assumed to contain the same music as it at a tuning frequency of A=440Hz."; - d.unit = "hz"; - d.hasFixedBinCount = true; - d.binCount = 1; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleType = OutputDescriptor::VariableSampleRate; - d.hasDuration = false; - m_outputs[d.identifier] = list.size(); - list.push_back(d); - - d.identifier = "reffeature"; - d.name = "Reference Feature"; - d.description = "Chroma feature from reference audio."; - d.unit = ""; - d.hasFixedBinCount = true; - d.binCount = m_bpo; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleType = OutputDescriptor::FixedSampleRate; - d.sampleRate = 1; - d.hasDuration = false; - m_outputs[d.identifier] = list.size(); - list.push_back(d); - - d.identifier = "otherfeature"; - d.name = "Other Feature"; - d.description = "Chroma feature from other audio, before rotation."; - d.unit = ""; - d.hasFixedBinCount = true; - d.binCount = m_bpo; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleType = OutputDescriptor::FixedSampleRate; - d.sampleRate = 1; - d.hasDuration = false; - m_outputs[d.identifier] = list.size(); - list.push_back(d); - - d.identifier = "rotfeature"; - d.name = "Other Feature at Rotated Frequency"; - d.description = "Chroma feature from reference audio calculated with the tuning frequency obtained from rotation matching."; - d.unit = ""; - d.hasFixedBinCount = true; - d.binCount = m_bpo; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleType = OutputDescriptor::FixedSampleRate; - d.sampleRate = 1; - d.hasDuration = false; - m_outputs[d.identifier] = list.size(); - list.push_back(d); - - return list; -} - -bool -TuningDifference::initialise(size_t channels, size_t stepSize, size_t blockSize) -{ - if (channels < getMinChannelCount() || - channels > getMaxChannelCount()) return false; - - if (stepSize != blockSize) return false; - - m_blockSize = blockSize; - - reset(); - - return true; -} - -void -TuningDifference::reset() -{ - if (m_frameCount > 0) { - m_refChroma.reset(new Chromagram(paramsForTuningFrequency(440.))); - m_frameCount = 0; - } - m_refTotals = TFeature(m_bpo, 0.0); - m_other.clear(); -} - -template<typename T> -void addTo(vector<T> &a, const vector<T> &b) -{ - transform(a.begin(), a.end(), b.begin(), a.begin(), plus<T>()); -} - -template<typename T> -T distance(const vector<T> &a, const vector<T> &b) -{ - return inner_product(a.begin(), a.end(), b.begin(), T(), - plus<T>(), [](T x, T y) { return fabs(x - y); }); -} - -TuningDifference::TFeature -TuningDifference::computeFeatureFromTotals(const TFeature &totals) const -{ - if (m_frameCount == 0) return totals; - - TFeature feature(m_bpo); - double sum = 0.0; - - for (int i = 0; i < m_bpo; ++i) { - double value = totals[i] / m_frameCount; - feature[i] += value; - sum += value; - } - - for (int i = 0; i < m_bpo; ++i) { - feature[i] /= sum; - } - - cerr << "computeFeatureFromTotals: feature values:" << endl; - for (auto v: feature) cerr << v << " "; - cerr << endl; - - return feature; -} - -Chromagram::Parameters -TuningDifference::paramsForTuningFrequency(double hz) const -{ - Chromagram::Parameters params(m_inputSampleRate); - params.lowestOctave = 0; - params.octaveCount = 6; - params.binsPerOctave = m_bpo; - params.tuningFrequency = hz; - params.atomHopFactor = 0.5; - return params; -} - -TuningDifference::TFeature -TuningDifference::computeFeatureFromSignal(const Signal &signal, double hz) const -{ - Chromagram chromagram(paramsForTuningFrequency(hz)); - - TFeature totals(m_bpo, 0.0); - - cerr << "computeFeatureFromSignal: hz = " << hz << ", frame count = " << m_frameCount << endl; - - for (int i = 0; i < m_frameCount; ++i) { - Signal::const_iterator first = signal.begin() + i * m_blockSize; - Signal::const_iterator last = first + m_blockSize; - if (last > signal.end()) last = signal.end(); - CQBase::RealSequence input(first, last); - input.resize(m_blockSize); - CQBase::RealBlock block = chromagram.process(input); - for (const auto &v: block) addTo(totals, v); - } - - return computeFeatureFromTotals(totals); -} - -TuningDifference::FeatureSet -TuningDifference::process(const float *const *inputBuffers, Vamp::RealTime) -{ - CQBase::RealBlock block; - CQBase::RealSequence input; - - input = CQBase::RealSequence - (inputBuffers[0], inputBuffers[0] + m_blockSize); - block = m_refChroma->process(input); - for (const auto &v: block) addTo(m_refTotals, v); - - m_other.insert(m_other.end(), - inputBuffers[1], inputBuffers[1] + m_blockSize); - - ++m_frameCount; - return FeatureSet(); -} - -double -TuningDifference::featureDistance(const TFeature &other, int rotation) const -{ - if (rotation == 0) { - return distance(m_refFeature, other); - } else { - // A positive rotation pushes the tuning frequency up for this - // chroma, negative one pulls it down. If a positive rotation - // makes this chroma match an un-rotated reference, then this - // chroma must have initially been lower than the reference. - TFeature r(other); - if (rotation < 0) { - rotate(r.begin(), r.begin() - rotation, r.end()); - } else { - rotate(r.begin(), r.end() - rotation, r.end()); - } - return distance(m_refFeature, r); - } -} - -int -TuningDifference::findBestRotation(const TFeature &other) const -{ - map<double, int> dists; - - int maxSemis = 6; - int maxRotation = (m_bpo * maxSemis) / 12; - - for (int r = -maxRotation; r <= maxRotation; ++r) { - double dist = featureDistance(other, r); - dists[dist] = r; - cerr << "rotation " << r << ": score " << dist << endl; - } - - int best = dists.begin()->second; - - cerr << "best is " << best << endl; - return best; -} - -pair<int, double> -TuningDifference::findFineFrequency(int coarseCents, double coarseScore) -{ - int coarseResolution = 1200 / m_bpo; - int searchDistance = coarseResolution/2 - 1; - - double bestScore = coarseScore; - int bestCents = coarseCents; - double bestHz = frequencyForCentsAbove440(coarseCents); - - cerr << "corresponding coarse Hz " << bestHz << " scores " << coarseScore << endl; - cerr << "searchDistance = " << searchDistance << endl; - - for (int sign = -1; sign <= 1; sign += 2) { - for (int offset = 1; offset <= searchDistance; ++offset) { - - int fineCents = coarseCents + sign * offset; - - cerr << "trying with fineCents = " << fineCents << "..." << endl; - - double fineHz = frequencyForCentsAbove440(fineCents); - TFeature fineFeature = computeFeatureFromSignal(m_other, fineHz); - double fineScore = featureDistance(fineFeature); - - cerr << "fine offset = " << offset << ", cents = " << fineCents - << ", Hz = " << fineHz << ", score " << fineScore - << " (best score so far " << bestScore << ")" << endl; - - if (fineScore < bestScore) { - cerr << "is good!" << endl; - bestScore = fineScore; - bestCents = fineCents; - bestHz = fineHz; - } else { - break; - } - } - } - - //!!! could keep a vector of scores & then interpolate... - - return pair<int, double>(bestCents, bestHz); -} - -TuningDifference::FeatureSet -TuningDifference::getRemainingFeatures() -{ - FeatureSet fs; - if (m_frameCount == 0) return fs; - - m_refFeature = computeFeatureFromTotals(m_refTotals); - TFeature otherFeature = computeFeatureFromSignal(m_other, 440.); - - Feature f; - - f.values.clear(); - for (auto v: m_refFeature) f.values.push_back(v); - fs[m_outputs["reffeature"]].push_back(f); - - f.values.clear(); - for (auto v: otherFeature) f.values.push_back(v); - fs[m_outputs["otherfeature"]].push_back(f); - - int rotation = findBestRotation(otherFeature); - - int coarseCents = -(rotation * 1200) / m_bpo; - - cerr << "rotation " << rotation << " -> cents " << coarseCents << endl; - - double coarseHz = frequencyForCentsAbove440(coarseCents); - - TFeature coarseFeature = computeFeatureFromSignal(m_other, coarseHz); - double coarseScore = featureDistance(coarseFeature); - - cerr << "corresponding Hz " << coarseHz << " scores " << coarseScore << endl; - - //!!! This should be returning the fine chroma, not the coarse - f.values.clear(); - for (auto v: coarseFeature) f.values.push_back(v); - fs[m_outputs["rotfeature"]].push_back(f); - - pair<int, double> fine = findFineFrequency(coarseCents, coarseScore); - int fineCents = fine.first; - double fineHz = fine.second; - - f.values.clear(); - f.values.push_back(fineHz); - fs[m_outputs["tuningfreq"]].push_back(f); - - f.values.clear(); - f.values.push_back(fineCents); - fs[m_outputs["cents"]].push_back(f); - - cerr << "overall best Hz = " << fineHz << endl; - - return fs; -} -
--- a/chroma-compare-plugin/TuningDifference.h Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -#ifndef TUNING_DIFFERENCE_H -#define TUNING_DIFFERENCE_H - -#include <vamp-sdk/Plugin.h> - -#include <cq/Chromagram.h> - -#include <memory> - -using std::string; -using std::vector; - -class TuningDifference : public Vamp::Plugin -{ -public: - TuningDifference(float inputSampleRate); - virtual ~TuningDifference(); - - string getIdentifier() const; - string getName() const; - string getDescription() const; - string getMaker() const; - int getPluginVersion() const; - string getCopyright() const; - - InputDomain getInputDomain() const; - size_t getPreferredBlockSize() const; - size_t getPreferredStepSize() const; - size_t getMinChannelCount() const; - size_t getMaxChannelCount() const; - - ParameterList getParameterDescriptors() const; - float getParameter(string identifier) const; - void setParameter(string identifier, float value); - - ProgramList getPrograms() const; - string getCurrentProgram() const; - void selectProgram(string name); - - OutputList getOutputDescriptors() const; - - bool initialise(size_t channels, size_t stepSize, size_t blockSize); - void reset(); - - FeatureSet process(const float *const *inputBuffers, - Vamp::RealTime timestamp); - - FeatureSet getRemainingFeatures(); - -protected: - typedef vector<float> Signal; - typedef vector<double> TFeature; - - int m_bpo; - std::unique_ptr<Chromagram> m_refChroma; - TFeature m_refTotals; - TFeature m_refFeature; - Signal m_other; - int m_blockSize; - int m_frameCount; - - Chromagram::Parameters paramsForTuningFrequency(double hz) const; - TFeature computeFeatureFromTotals(const TFeature &totals) const; - TFeature computeFeatureFromSignal(const Signal &signal, double hz) const; - double featureDistance(const TFeature &other, int rotation = 0) const; - int findBestRotation(const TFeature &other) const; - std::pair<int, double> findFineFrequency(int coarseCents, double coarseScore); - - mutable std::map<string, int> m_outputs; -}; - - -#endif
--- a/chroma-compare-plugin/plugins.cpp Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ - -#include <vamp/vamp.h> -#include <vamp-sdk/PluginAdapter.h> - -#include "TuningDifference.h" - -static Vamp::PluginAdapter<TuningDifference> tdAdapter; - - -const VampPluginDescriptor * -vampGetPluginDescriptor(unsigned int version, unsigned int index) -{ - if (version < 1) return 0; - - switch (index) { - case 0: return tdAdapter.getDescriptor(); - default: return 0; - } -} - -
--- a/chroma-compare-plugin/vamp-plugin.list Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -_vampGetPluginDescriptor
--- a/chroma-compare-plugin/vamp-plugin.map Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -{ - global: vampGetPluginDescriptor; - local: *; -};
--- a/iterative-chroma/chroma-excerpt.ttl Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . -@prefix vamp: <http://purl.org/ontology/vamp/> . -@prefix : <#> . - -:transform a vamp:Transform ; - vamp:plugin <http://vamp-plugins.org/rdf/plugins/qm-vamp-plugins#qm-chromagram> ; - vamp:duration "PT30S"^^xsd:duration ; - vamp:parameter_binding [ - vamp:parameter [ vamp:identifier "bpo" ] ; - vamp:value "60"^^xsd:float ; - ] ; - vamp:parameter_binding [ - vamp:parameter [ vamp:identifier "tuning" ] ; - vamp:value "440"^^xsd:float ; - ] ; - vamp:parameter_binding [ - vamp:parameter [ vamp:identifier "normalization" ] ; - vamp:value "1"^^xsd:float ; # unit sum - ] ; - vamp:output <http://vamp-plugins.org/rdf/plugins/qm-vamp-plugins#qm-chromagram_output_chromagram> .
--- a/iterative-chroma/chromacompare.sh Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -#!/bin/bash - -set -e - -mypath=`dirname $0` - -sonic-annotator --minversion 1.1 || exit 1 - -reference="$1" -other="$2" - -usage() { - echo "Usage: $0 reference.wav other.wav" 1>&2 - exit 2 -} - -test -n "$reference" || usage -test -n "$other" || usage - -if ! test -f "$reference" ; then - echo "Reference file $reference not found" 1>&2 - exit 1 -fi - -if ! test -f "$other" ; then - echo "Other file $other not found" 1>&2 - exit 1 -fi - -refchroma="/tmp/$$.ref" -otherchroma="/tmp/$$.other" -tmpscript="/tmp/$$.dc" -transform="/tmp/$$.ttl" -scores="/tmp/$$.scores.txt" -trap "rm $refchroma $otherchroma $tmpscript $transform $scores" 0 - -extract() { - hz="$1" - file="$2" - cat chroma-excerpt.ttl | sed 's,"440","'"$hz"'",' > "$transform" - sonic-annotator -t "$transform" --summary mean --summary-only -w csv --csv-stdout --csv-omit-filename "$file" 2>/dev/null | cut -d, -f4-63 | sed 's/,/\n/g' -} - -extract 440 "$reference" | cat -n > "$refchroma" - -sox "$other" -r 44100 -c 1 b.wav - -for cents in $(seq -400 10 400) ; do - - hz=$(perl -e "print 440.0 * (2.0 ** ($cents / 1200.0))") - - extract "$hz" b.wav | cat -n > "$otherchroma" - ( - echo "6 k 0" - join "$refchroma" "$otherchroma" | \ - awk '{ print $2, $3, "- d * +" }' # square difference - echo "p" - ) > "$tmpscript" - - dist=$( cat "$tmpscript" | dc ) - echo "$dist $hz" - -done | tee "$scores" - -echo -echo Scores: -sort -n "$scores" - -echo -bestfreq=$(sort -n "$scores" | head -1 | awk '{ print $2; }') -echo "I reckon the tuning frequency is $bestfreq" - -
--- a/iterative-match/match-cost.ttl Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . -@prefix vamp: <http://purl.org/ontology/vamp/> . -@prefix : <#> . - -:param_chroma - vamp:parameter [ vamp:identifier "usechroma" ] ; - vamp:value "1"^^xsd:float . - -:param_freq - vamp:parameter [ vamp:identifier "freq2" ] ; - vamp:value "440"^^xsd:float . - -:transform_a a vamp:Transform ; - vamp:plugin <http://vamp-plugins.org/rdf/plugins/match-vamp-plugin#match> ; - vamp:plugin_version "3"^^xsd:int ; - vamp:step_size "882"^^xsd:int ; - vamp:block_size "2048"^^xsd:int ; - vamp:sample_rate "44100"^^xsd:int ; - vamp:parameter_binding :param_chroma ; - vamp:parameter_binding :param_freq ; - vamp:output [ vamp:identifier "overall_cost" ] . -
--- a/iterative-match/matchcompare.sh Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -#!/bin/bash - -set -e - -mypath=`dirname $0` - -sonic-annotator --minversion 1.1 || exit 1 - -reference="$1" -other="$2" - -usage() { - echo "Usage: $0 reference.wav other.wav" 1>&2 - exit 2 -} - -test -n "$reference" || usage -test -n "$other" || usage - -set -u - -transform="/tmp/$$.ttl" -scores="/tmp/$$.scores.txt" -trap "rm $transform $scores" 0 - -#export VAMP_PATH="$mypath"/../match-vamp - -sox "$reference" -r 44100 -c 1 a.wav -sox "$other" -r 44100 -c 1 b.wav - -for cents in $(seq -400 10 400) ; do - - freq=$(perl -e "print 440.0 * (2.0 ** ($cents / 1200.0))") - - cat match-cost.ttl | sed "s,440,$freq," > "$transform" - - score=$(sonic-annotator -t "$transform" --multiplex -w csv --csv-stdout a.wav b.wav | awk -F, '{ print $3 }') - - echo "$score $freq" - -done | tee "$scores" - -echo -echo Scores: -sort -n "$scores" - -echo -bestfreq=$(sort -n "$scores" | head -1 | awk '{ print $2; }') -echo "I reckon the tuning frequency is $bestfreq" -
--- a/spectrum-compare-plugin/Makefile.inc Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ - -## Makefile for Vamp plugin builds using command-line tools. -## -## This file defines all of the system-independent information about -## your project: the list of source files, plugin library name, etc. -## Edit this file to make sure it has all the right information. -## -## This file does not define the system-specific stuff such as which -## compiler to use -- that goes into Makefile.osx, Makefile.mingw32, -## Makefile.linux etc. Those files all include this file, so that -## they all have a consistent set of project data. -## -## To build the plugin project, type -## -## $ gmake -f Makefile.osx -## -## or whatever the equivalent filename suffix is for your platform. -## -## This requires GNU make, which is what you get with OS/X, Linux, or -## MinGW/Cygwin on Windows. -## -## (For Windows builds using MS Visual Studio, start instead with the -## VampExamplePlugins project found in the build directory of the SDK.) - - -# Edit this to the base name of your plugin library -# -PLUGIN_LIBRARY_NAME := tuning-difference - -# Edit this to list the .cpp or .c files in your plugin project -# -PLUGIN_SOURCES := TuningDifference.cpp plugins.cpp - -# Edit this to list the .h files in your plugin project -# -PLUGIN_HEADERS := TuningDifference.h - - -## Normally you should not edit anything below this line - -SRC_DIR := . - -CFLAGS := $(ARCHFLAGS) $(CFLAGS) -CXXFLAGS := $(CFLAGS) -I. -I$(VAMPSDK_DIR) $(CXXFLAGS) - -LDFLAGS := $(ARCHFLAGS) $(LDFLAGS) -PLUGIN_LDFLAGS := $(LDFLAGS) $(PLUGIN_LDFLAGS) - -# Defaults, overridden from the platform-specific Makefile -VAMPSDK_DIR ?= ../vamp-plugin-sdk -PLUGIN_EXT ?= .so -CXX ?= g++ -CC ?= gcc - -PLUGIN := $(PLUGIN_LIBRARY_NAME)$(PLUGIN_EXT) - -PLUGIN_OBJECTS := $(PLUGIN_SOURCES:.cpp=.o) -PLUGIN_OBJECTS := $(PLUGIN_OBJECTS:.c=.o) - -$(PLUGIN): $(PLUGIN_OBJECTS) - $(CXX) -o $@ $^ $(PLUGIN_LDFLAGS) - -$(PLUGIN_OBJECTS): $(PLUGIN_HEADERS) - -clean: - rm -f $(PLUGIN_OBJECTS) - -distclean: clean - rm -f $(PLUGIN) - -depend: - makedepend -Y -fMakefile.inc $(PLUGIN_SOURCES) $(PLUGIN_HEADERS) - -# DO NOT DELETE - -TuningDifference.o: TuningDifference.h -plugins.o: TuningDifference.h
--- a/spectrum-compare-plugin/Makefile.linux Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ - -## Makefile for Vamp plugin using GNU tools on Linux. -## -## Edit this to adjust compiler and library settings when -## building for Linux. -## -## Note that the list of source files, etc, goes in Makefile.inc -## instead so that it can be included by all platform Makefiles. - - -# For a debug build... - -CFLAGS := -Wall -Wextra -g -fPIC - -# ... or for a release build - -#CFLAGS := -Wall -Wextra -O3 -msse -msse2 -mfpmath=sse -ftree-vectorize -fPIC - - -# Location of Vamp plugin SDK relative to the project directory - -VAMPSDK_DIR := ../vamp-plugin-sdk - - -# Libraries and linker flags required by plugin: add any -l<library> -# options here - -PLUGIN_LDFLAGS := -shared -Wl,-Bsymbolic -Wl,-z,defs -Wl,--version-script=vamp-plugin.map $(VAMPSDK_DIR)/libvamp-sdk.a - - -# File extension for plugin library on this platform - -PLUGIN_EXT := .so - - -include Makefile.inc - -
--- a/spectrum-compare-plugin/Makefile.mingw32 Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ - -## Makefile for Vamp plugin using MinGW tools on Windows. -## -## Edit this to adjust compiler and library settings when -## building using MinGW. -## -## Note that the list of source files, etc, goes in Makefile.inc -## instead so that it can be included by all platform Makefiles. - -TOOLPREFIX ?= -CXX = $(TOOLPREFIX)g++ -CC = $(TOOLPREFIX)gcc -LD = $(TOOLPREFIX)g++ -AR = $(TOOLPREFIX)ar -RANLIB = $(TOOLPREFIX)ranlib - - -# For a debug build... - -CFLAGS := -Wall -Wextra -g - -# ... or for a release build - -#CFLAGS := -Wall -Wextra -O3 -ftree-vectorize - - -# Location of Vamp plugin SDK relative to the project directory - -VAMPSDK_DIR := ../vamp-plugin-sdk - - -# Libraries and linker flags required by plugin: add any -l<library> -# options here - -PLUGIN_LDFLAGS := -shared -static -Wl,--retain-symbols-file=vamp-plugin.list $(VAMPSDK_DIR)/libvamp-sdk.a - - -# File extension for plugin library on this platform - -PLUGIN_EXT := .dll - - -include Makefile.inc
--- a/spectrum-compare-plugin/Makefile.osx Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ - -## Makefile for Vamp plugin using command-line tools on OS/X. -## -## Edit this to adjust compiler and library settings when -## building for OS/X. -## -## Note that the list of source files, etc, goes in Makefile.inc -## instead so that it can be included by all platform Makefiles. - - -# For a debug build... - -CFLAGS := -Wall -Wextra -g -fPIC - -# ... or for a release build - -#CFLAGS := -Wall -Wextra -O3 -ftree-vectorize -fPIC - - -# Flags to determine processor architecture and system SDK - -ARCHFLAGS ?= -mmacosx-version-min=10.6 -arch x86_64 -arch i386 - - -# Location of Vamp plugin SDK relative to the project directory - -VAMPSDK_DIR := ../vamp-plugin-sdk - - -# Libraries and linker flags required by plugin: add any -l<library> -# options here - -PLUGIN_LDFLAGS := -dynamiclib -exported_symbols_list vamp-plugin.list $(VAMPSDK_DIR)/libvamp-sdk.a - - -# File extension for plugin library on this platform - -PLUGIN_EXT := .dylib - - -include Makefile.inc - -
--- a/spectrum-compare-plugin/TuningDifference.cpp Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,382 +0,0 @@ - -#include "TuningDifference.h" - -#include <iostream> - -#include <cmath> -#include <cstdio> - -using std::cerr; -using std::endl; - -static double targetFmin = 60.0; -static double targetFmax = 1500.0; - -TuningDifference::TuningDifference(float inputSampleRate) : - Plugin(inputSampleRate) -{ -} - -TuningDifference::~TuningDifference() -{ -} - -string -TuningDifference::getIdentifier() const -{ - return "tuning-difference"; -} - -string -TuningDifference::getName() const -{ - return "Tuning Difference"; -} - -string -TuningDifference::getDescription() const -{ - // Return something helpful here! - return ""; -} - -string -TuningDifference::getMaker() const -{ - // Your name here - return ""; -} - -int -TuningDifference::getPluginVersion() const -{ - // Increment this each time you release a version that behaves - // differently from the previous one - return 1; -} - -string -TuningDifference::getCopyright() const -{ - // This function is not ideally named. It does not necessarily - // need to say who made the plugin -- getMaker does that -- but it - // should indicate the terms under which it is distributed. For - // example, "Copyright (year). All Rights Reserved", or "GPL" - return ""; -} - -TuningDifference::InputDomain -TuningDifference::getInputDomain() const -{ - return FrequencyDomain; -} - -size_t -TuningDifference::getPreferredBlockSize() const -{ - return 16384; -} - -size_t -TuningDifference::getPreferredStepSize() const -{ - return 0; -} - -size_t -TuningDifference::getMinChannelCount() const -{ - return 2; -} - -size_t -TuningDifference::getMaxChannelCount() const -{ - return 2; -} - -TuningDifference::ParameterList -TuningDifference::getParameterDescriptors() const -{ - ParameterList list; - return list; -} - -float -TuningDifference::getParameter(string) const -{ - return 0; -} - -void -TuningDifference::setParameter(string, float) -{ -} - -TuningDifference::ProgramList -TuningDifference::getPrograms() const -{ - ProgramList list; - return list; -} - -string -TuningDifference::getCurrentProgram() const -{ - return ""; // no programs -} - -void -TuningDifference::selectProgram(string) -{ -} - -TuningDifference::OutputList -TuningDifference::getOutputDescriptors() const -{ - OutputList list; - - OutputDescriptor d; - d.identifier = "cents"; - d.name = "Tuning Difference"; - d.description = "Difference in averaged frequency profile between channels 1 and 2, in cents. A positive value means channel 2 is higher."; - d.unit = "cents"; - d.hasFixedBinCount = true; - d.binCount = 1; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleType = OutputDescriptor::VariableSampleRate; - d.hasDuration = false; - list.push_back(d); - - d.identifier = "tuningfreq"; - d.name = "Relative Tuning Frequency"; - d.description = "Tuning frequency of channel 2, if channel 1 is assumed to contain the same music as it at a tuning frequency of A=440Hz."; - d.unit = "hz"; - d.hasFixedBinCount = true; - d.binCount = 1; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleType = OutputDescriptor::VariableSampleRate; - d.hasDuration = false; - list.push_back(d); - - d.identifier = "curve"; - d.name = "Shift Correlation Curve"; - d.description = "Correlation between shifted and unshifted sources, for each probed shift in cents."; - d.unit = ""; - d.hasFixedBinCount = true; - d.binCount = 1; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleType = OutputDescriptor::FixedSampleRate; - d.sampleRate = 100; - d.hasDuration = false; - list.push_back(d); - - int targetBinMin = int(floor(targetFmin * m_blockSize / m_inputSampleRate)); - int targetBinMax = int(ceil(targetFmax * m_blockSize / m_inputSampleRate)); - cerr << "target bin range: " << targetBinMin << " -> " << targetBinMax << endl; - - d.identifier = "averages"; - d.name = "Harmonic spectrum averages"; - d.description = "Average of harmonic spectrum for each channel."; - d.unit = ""; - d.hasFixedBinCount = true; - d.binCount = (targetBinMax > targetBinMin ? targetBinMax - targetBinMin + 1 : 100); - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleType = OutputDescriptor::FixedSampleRate; - d.sampleRate = 1; - d.hasDuration = false; - list.push_back(d); - - return list; -} - -bool -TuningDifference::initialise(size_t channels, size_t stepSize, size_t blockSize) -{ - if (channels < getMinChannelCount() || - channels > getMaxChannelCount()) return false; - - if (blockSize != getPreferredBlockSize() || - stepSize != blockSize/2) return false; - - m_blockSize = blockSize; - - reset(); - - return true; -} - -void -TuningDifference::reset() -{ - m_sum[0].clear(); - m_sum[1].clear(); - m_frameCount = 0; -} - -TuningDifference::FeatureSet -TuningDifference::process(const float *const *inputBuffers, Vamp::RealTime timestamp) -{ - for (int c = 0; c < 2; ++c) { - if (m_sum[c].size() == 0) { - m_sum[c].resize(m_blockSize/2 + 1, 0.0); - } - vector<double> mags(m_blockSize/2 + 1, 0.0); - for (int i = 0; i <= m_blockSize/2; ++i) { - double energy = - inputBuffers[c][i*2 ] * inputBuffers[c][i*2 ] + - inputBuffers[c][i*2+1] * inputBuffers[c][i*2+1]; - double mag = sqrt(energy); - mags[i] = mag; - } - for (int i = 0; i <= m_blockSize/2; ++i) { - for (int h = 2; h <= 4; ++h) { - double max = 0.0; - for (int j = 0; j <= h; ++j) { - int ix = i * h + j - h/2; - if (ix <= m_blockSize/2) { - double harmMag = mags[ix]; - if (j == 0 || harmMag > max) { - max = harmMag; - } - } - } - mags[i] += max; - } - } - for (int i = 0; i <= m_blockSize/2; ++i) { - m_sum[c][i] += mags[i]; - } - } - - ++m_frameCount; - return FeatureSet(); -} - -TuningDifference::FeatureSet -TuningDifference::getRemainingFeatures() -{ - int n = m_sum[0].size(); - if (n == 0) return FeatureSet(); - - Feature f; - FeatureSet fs; - - int maxshift = 2400; // cents - - int bestshift = -1; - double bestdist = 0; - - for (int i = 0; i < n; ++i) { - m_sum[0][i] /= m_frameCount; - m_sum[1][i] /= m_frameCount; - } - - for (int c = 0; c < 2; ++c) { - for (int i = 0; i < n; ++i) { - if (i == 0 || i == n-1 || - m_sum[c][i] < m_sum[c][i-1] || - m_sum[c][i] < m_sum[c][i+1]) { - m_sum[c][i] = 0.0; - } - } - } - - int targetBinMin = int(floor(targetFmin * m_blockSize / m_inputSampleRate)); - int targetBinMax = int(ceil(targetFmax * m_blockSize / m_inputSampleRate)); - cerr << "target bin range: " << targetBinMin << " -> " << targetBinMax << endl; - - for (int c = 0; c < 2; ++c) { - double tot = 0.0; - for (int i = targetBinMin; i <= targetBinMax; ++i) { - tot += m_sum[c][i]; - } - if (tot != 0.0) { - for (int i = 0; i < n; ++i) { - m_sum[c][i] /= tot; - } - } - } - - f.values.clear(); - for (int i = targetBinMin; i < targetBinMax; ++i) { - f.values.push_back(m_sum[0][i]); - } - fs[3].push_back(f); - f.values.clear(); - for (int i = targetBinMin; i < targetBinMax; ++i) { - f.values.push_back(m_sum[1][i]); - } - fs[3].push_back(f); - - f.values.clear(); - - for (int shift = -maxshift; shift <= maxshift; ++shift) { - - double multiplier = pow(2.0, double(shift) / 1200.0); - double dist = 0.0; - -// cerr << "shift = " << shift << ", multiplier = " << multiplier << endl; - - int contributing = 0; - - for (int i = targetBinMin; i < targetBinMax; ++i) { - - double source = i / multiplier; - int s0 = int(source), s1 = s0 + 1; - double p1 = source - s0; - double p0 = 1.0 - p1; - - double value = 0.0; - if (s0 >= 0 && s0 < n) { - value += p0 * m_sum[1][s0]; - ++contributing; - } - if (s1 >= 0 && s1 < n) { - value += p1 * m_sum[1][s1]; - ++contributing; - } - -// if (shift == -1) { -// cerr << "for multiplier " << multiplier << ", target " << i << ", source " << source << ", value " << p0 << " * " << m_sum[1][s0] << " + " << p1 << " * " << m_sum[1][s1] << " = " << value << ", other " << m_sum[0][i] << endl; -// } - - double diff = fabs(m_sum[0][i] - value); - dist += diff; - } - - dist /= contributing; - - f.values.clear(); - f.values.push_back(dist); - char label[100]; - sprintf(label, "%f at shift %d freq mult %f", dist, shift, multiplier); - f.label = label; - fs[2].push_back(f); - - if (bestshift == -1 || dist < bestdist) { - bestshift = shift; - bestdist = dist; - } - } - - f.timestamp = Vamp::RealTime::zeroTime; - f.hasTimestamp = true; - f.label = ""; - - f.values.clear(); - cerr << "best dist = " << bestdist << " at shift " << bestshift << endl; - f.values.push_back(-bestshift); - fs[0].push_back(f); - - f.values.clear(); - f.values.push_back(440.0 / pow(2.0, double(bestshift) / 1200.0)); - fs[1].push_back(f); - - return fs; -} -
--- a/spectrum-compare-plugin/TuningDifference.h Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -#ifndef TUNING_DIFFERENCE_H -#define TUNING_DIFFERENCE_H - -#include <vamp-sdk/Plugin.h> - -using std::string; -using std::vector; - -class TuningDifference : public Vamp::Plugin -{ -public: - TuningDifference(float inputSampleRate); - virtual ~TuningDifference(); - - string getIdentifier() const; - string getName() const; - string getDescription() const; - string getMaker() const; - int getPluginVersion() const; - string getCopyright() const; - - InputDomain getInputDomain() const; - size_t getPreferredBlockSize() const; - size_t getPreferredStepSize() const; - size_t getMinChannelCount() const; - size_t getMaxChannelCount() const; - - ParameterList getParameterDescriptors() const; - float getParameter(string identifier) const; - void setParameter(string identifier, float value); - - ProgramList getPrograms() const; - string getCurrentProgram() const; - void selectProgram(string name); - - OutputList getOutputDescriptors() const; - - bool initialise(size_t channels, size_t stepSize, size_t blockSize); - void reset(); - - FeatureSet process(const float *const *inputBuffers, - Vamp::RealTime timestamp); - - FeatureSet getRemainingFeatures(); - -protected: - int m_blockSize; - vector<double> m_sum[2]; - int m_frameCount; -}; - - -#endif
--- a/spectrum-compare-plugin/plugins.cpp Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ - -#include <vamp/vamp.h> -#include <vamp-sdk/PluginAdapter.h> - -#include "TuningDifference.h" - -static Vamp::PluginAdapter<TuningDifference> tdAdapter; - - -const VampPluginDescriptor * -vampGetPluginDescriptor(unsigned int version, unsigned int index) -{ - if (version < 1) return 0; - - switch (index) { - case 0: return tdAdapter.getDescriptor(); - default: return 0; - } -} - -
--- a/spectrum-compare-plugin/vamp-plugin.list Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -_vampGetPluginDescriptor
--- a/spectrum-compare-plugin/vamp-plugin.map Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -{ - global: vampGetPluginDescriptor; - local: *; -};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/TuningDifference.cpp Thu Feb 05 10:13:31 2015 +0000 @@ -0,0 +1,492 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + 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 "TuningDifference.h" + +#include <iostream> + +#include <cmath> +#include <cstdio> + +#include <algorithm> + +using namespace std; + +static double pitchToFrequency(int pitch, + double centsOffset = 0., + double concertA = 440.) +{ + double p = double(pitch) + (centsOffset / 100.); + return concertA * pow(2.0, (p - 69.0) / 12.0); +} + +static double frequencyForCentsAbove440(double cents) +{ + return pitchToFrequency(69, cents, 440.); +} + +TuningDifference::TuningDifference(float inputSampleRate) : + Plugin(inputSampleRate), + m_bpo(60), + m_refChroma(new Chromagram(paramsForTuningFrequency(440.))), + m_blockSize(0), + m_frameCount(0) +{ +} + +TuningDifference::~TuningDifference() +{ +} + +string +TuningDifference::getIdentifier() const +{ + return "tuning-difference"; +} + +string +TuningDifference::getName() const +{ + return "Tuning Difference"; +} + +string +TuningDifference::getDescription() const +{ + // Return something helpful here! + return ""; +} + +string +TuningDifference::getMaker() const +{ + // Your name here + return ""; +} + +int +TuningDifference::getPluginVersion() const +{ + // Increment this each time you release a version that behaves + // differently from the previous one + return 1; +} + +string +TuningDifference::getCopyright() const +{ + // This function is not ideally named. It does not necessarily + // need to say who made the plugin -- getMaker does that -- but it + // should indicate the terms under which it is distributed. For + // example, "Copyright (year). All Rights Reserved", or "GPL" + return ""; +} + +TuningDifference::InputDomain +TuningDifference::getInputDomain() const +{ + return TimeDomain; +} + +size_t +TuningDifference::getPreferredBlockSize() const +{ + return 0; +} + +size_t +TuningDifference::getPreferredStepSize() const +{ + return 0; +} + +size_t +TuningDifference::getMinChannelCount() const +{ + return 2; +} + +size_t +TuningDifference::getMaxChannelCount() const +{ + return 2; +} + +TuningDifference::ParameterList +TuningDifference::getParameterDescriptors() const +{ + ParameterList list; + //!!! parameter: max search range + //!!! parameter: fine search precision + return list; +} + +float +TuningDifference::getParameter(string) const +{ + return 0; +} + +void +TuningDifference::setParameter(string, float) +{ +} + +TuningDifference::ProgramList +TuningDifference::getPrograms() const +{ + ProgramList list; + return list; +} + +string +TuningDifference::getCurrentProgram() const +{ + return ""; // no programs +} + +void +TuningDifference::selectProgram(string) +{ +} + +TuningDifference::OutputList +TuningDifference::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor d; + d.identifier = "cents"; + d.name = "Tuning Difference"; + d.description = "Difference in averaged frequency profile between channels 1 and 2, in cents. A positive value means channel 2 is higher."; + d.unit = "cents"; + d.hasFixedBinCount = true; + d.binCount = 1; + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::VariableSampleRate; + d.hasDuration = false; + m_outputs[d.identifier] = list.size(); + list.push_back(d); + + d.identifier = "tuningfreq"; + d.name = "Relative Tuning Frequency"; + d.description = "Tuning frequency of channel 2, if channel 1 is assumed to contain the same music as it at a tuning frequency of A=440Hz."; + d.unit = "hz"; + d.hasFixedBinCount = true; + d.binCount = 1; + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::VariableSampleRate; + d.hasDuration = false; + m_outputs[d.identifier] = list.size(); + list.push_back(d); + + d.identifier = "reffeature"; + d.name = "Reference Feature"; + d.description = "Chroma feature from reference audio."; + d.unit = ""; + d.hasFixedBinCount = true; + d.binCount = m_bpo; + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::FixedSampleRate; + d.sampleRate = 1; + d.hasDuration = false; + m_outputs[d.identifier] = list.size(); + list.push_back(d); + + d.identifier = "otherfeature"; + d.name = "Other Feature"; + d.description = "Chroma feature from other audio, before rotation."; + d.unit = ""; + d.hasFixedBinCount = true; + d.binCount = m_bpo; + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::FixedSampleRate; + d.sampleRate = 1; + d.hasDuration = false; + m_outputs[d.identifier] = list.size(); + list.push_back(d); + + d.identifier = "rotfeature"; + d.name = "Other Feature at Rotated Frequency"; + d.description = "Chroma feature from reference audio calculated with the tuning frequency obtained from rotation matching."; + d.unit = ""; + d.hasFixedBinCount = true; + d.binCount = m_bpo; + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::FixedSampleRate; + d.sampleRate = 1; + d.hasDuration = false; + m_outputs[d.identifier] = list.size(); + list.push_back(d); + + return list; +} + +bool +TuningDifference::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + if (channels < getMinChannelCount() || + channels > getMaxChannelCount()) return false; + + if (stepSize != blockSize) return false; + + m_blockSize = blockSize; + + reset(); + + return true; +} + +void +TuningDifference::reset() +{ + if (m_frameCount > 0) { + m_refChroma.reset(new Chromagram(paramsForTuningFrequency(440.))); + m_frameCount = 0; + } + m_refTotals = TFeature(m_bpo, 0.0); + m_other.clear(); +} + +template<typename T> +void addTo(vector<T> &a, const vector<T> &b) +{ + transform(a.begin(), a.end(), b.begin(), a.begin(), plus<T>()); +} + +template<typename T> +T distance(const vector<T> &a, const vector<T> &b) +{ + return inner_product(a.begin(), a.end(), b.begin(), T(), + plus<T>(), [](T x, T y) { return fabs(x - y); }); +} + +TuningDifference::TFeature +TuningDifference::computeFeatureFromTotals(const TFeature &totals) const +{ + if (m_frameCount == 0) return totals; + + TFeature feature(m_bpo); + double sum = 0.0; + + for (int i = 0; i < m_bpo; ++i) { + double value = totals[i] / m_frameCount; + feature[i] += value; + sum += value; + } + + for (int i = 0; i < m_bpo; ++i) { + feature[i] /= sum; + } + + cerr << "computeFeatureFromTotals: feature values:" << endl; + for (auto v: feature) cerr << v << " "; + cerr << endl; + + return feature; +} + +Chromagram::Parameters +TuningDifference::paramsForTuningFrequency(double hz) const +{ + Chromagram::Parameters params(m_inputSampleRate); + params.lowestOctave = 0; + params.octaveCount = 6; + params.binsPerOctave = m_bpo; + params.tuningFrequency = hz; + params.atomHopFactor = 0.5; + return params; +} + +TuningDifference::TFeature +TuningDifference::computeFeatureFromSignal(const Signal &signal, double hz) const +{ + Chromagram chromagram(paramsForTuningFrequency(hz)); + + TFeature totals(m_bpo, 0.0); + + cerr << "computeFeatureFromSignal: hz = " << hz << ", frame count = " << m_frameCount << endl; + + for (int i = 0; i < m_frameCount; ++i) { + Signal::const_iterator first = signal.begin() + i * m_blockSize; + Signal::const_iterator last = first + m_blockSize; + if (last > signal.end()) last = signal.end(); + CQBase::RealSequence input(first, last); + input.resize(m_blockSize); + CQBase::RealBlock block = chromagram.process(input); + for (const auto &v: block) addTo(totals, v); + } + + return computeFeatureFromTotals(totals); +} + +TuningDifference::FeatureSet +TuningDifference::process(const float *const *inputBuffers, Vamp::RealTime) +{ + CQBase::RealBlock block; + CQBase::RealSequence input; + + input = CQBase::RealSequence + (inputBuffers[0], inputBuffers[0] + m_blockSize); + block = m_refChroma->process(input); + for (const auto &v: block) addTo(m_refTotals, v); + + m_other.insert(m_other.end(), + inputBuffers[1], inputBuffers[1] + m_blockSize); + + ++m_frameCount; + return FeatureSet(); +} + +double +TuningDifference::featureDistance(const TFeature &other, int rotation) const +{ + if (rotation == 0) { + return distance(m_refFeature, other); + } else { + // A positive rotation pushes the tuning frequency up for this + // chroma, negative one pulls it down. If a positive rotation + // makes this chroma match an un-rotated reference, then this + // chroma must have initially been lower than the reference. + TFeature r(other); + if (rotation < 0) { + rotate(r.begin(), r.begin() - rotation, r.end()); + } else { + rotate(r.begin(), r.end() - rotation, r.end()); + } + return distance(m_refFeature, r); + } +} + +int +TuningDifference::findBestRotation(const TFeature &other) const +{ + map<double, int> dists; + + int maxSemis = 6; + int maxRotation = (m_bpo * maxSemis) / 12; + + for (int r = -maxRotation; r <= maxRotation; ++r) { + double dist = featureDistance(other, r); + dists[dist] = r; + cerr << "rotation " << r << ": score " << dist << endl; + } + + int best = dists.begin()->second; + + cerr << "best is " << best << endl; + return best; +} + +pair<int, double> +TuningDifference::findFineFrequency(int coarseCents, double coarseScore) +{ + int coarseResolution = 1200 / m_bpo; + int searchDistance = coarseResolution/2 - 1; + + double bestScore = coarseScore; + int bestCents = coarseCents; + double bestHz = frequencyForCentsAbove440(coarseCents); + + cerr << "corresponding coarse Hz " << bestHz << " scores " << coarseScore << endl; + cerr << "searchDistance = " << searchDistance << endl; + + for (int sign = -1; sign <= 1; sign += 2) { + for (int offset = 1; offset <= searchDistance; ++offset) { + + int fineCents = coarseCents + sign * offset; + + cerr << "trying with fineCents = " << fineCents << "..." << endl; + + double fineHz = frequencyForCentsAbove440(fineCents); + TFeature fineFeature = computeFeatureFromSignal(m_other, fineHz); + double fineScore = featureDistance(fineFeature); + + cerr << "fine offset = " << offset << ", cents = " << fineCents + << ", Hz = " << fineHz << ", score " << fineScore + << " (best score so far " << bestScore << ")" << endl; + + if (fineScore < bestScore) { + cerr << "is good!" << endl; + bestScore = fineScore; + bestCents = fineCents; + bestHz = fineHz; + } else { + break; + } + } + } + + //!!! could keep a vector of scores & then interpolate... + + return pair<int, double>(bestCents, bestHz); +} + +TuningDifference::FeatureSet +TuningDifference::getRemainingFeatures() +{ + FeatureSet fs; + if (m_frameCount == 0) return fs; + + m_refFeature = computeFeatureFromTotals(m_refTotals); + TFeature otherFeature = computeFeatureFromSignal(m_other, 440.); + + Feature f; + + f.values.clear(); + for (auto v: m_refFeature) f.values.push_back(v); + fs[m_outputs["reffeature"]].push_back(f); + + f.values.clear(); + for (auto v: otherFeature) f.values.push_back(v); + fs[m_outputs["otherfeature"]].push_back(f); + + int rotation = findBestRotation(otherFeature); + + int coarseCents = -(rotation * 1200) / m_bpo; + + cerr << "rotation " << rotation << " -> cents " << coarseCents << endl; + + double coarseHz = frequencyForCentsAbove440(coarseCents); + + TFeature coarseFeature = computeFeatureFromSignal(m_other, coarseHz); + double coarseScore = featureDistance(coarseFeature); + + cerr << "corresponding Hz " << coarseHz << " scores " << coarseScore << endl; + + //!!! This should be returning the fine chroma, not the coarse + f.values.clear(); + for (auto v: coarseFeature) f.values.push_back(v); + fs[m_outputs["rotfeature"]].push_back(f); + + pair<int, double> fine = findFineFrequency(coarseCents, coarseScore); + int fineCents = fine.first; + double fineHz = fine.second; + + f.values.clear(); + f.values.push_back(fineHz); + fs[m_outputs["tuningfreq"]].push_back(f); + + f.values.clear(); + f.values.push_back(fineCents); + fs[m_outputs["cents"]].push_back(f); + + cerr << "overall best Hz = " << fineHz << endl; + + return fs; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/TuningDifference.h Thu Feb 05 10:13:31 2015 +0000 @@ -0,0 +1,85 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + 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 TUNING_DIFFERENCE_H +#define TUNING_DIFFERENCE_H + +#include <vamp-sdk/Plugin.h> + +#include <cq/Chromagram.h> + +#include <memory> + +using std::string; +using std::vector; + +class TuningDifference : public Vamp::Plugin +{ +public: + TuningDifference(float inputSampleRate); + virtual ~TuningDifference(); + + string getIdentifier() const; + string getName() const; + string getDescription() const; + string getMaker() const; + int getPluginVersion() const; + string getCopyright() const; + + InputDomain getInputDomain() const; + size_t getPreferredBlockSize() const; + size_t getPreferredStepSize() const; + size_t getMinChannelCount() const; + size_t getMaxChannelCount() const; + + ParameterList getParameterDescriptors() const; + float getParameter(string identifier) const; + void setParameter(string identifier, float value); + + ProgramList getPrograms() const; + string getCurrentProgram() const; + void selectProgram(string name); + + OutputList getOutputDescriptors() const; + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + FeatureSet process(const float *const *inputBuffers, + Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + typedef vector<float> Signal; + typedef vector<double> TFeature; + + int m_bpo; + std::unique_ptr<Chromagram> m_refChroma; + TFeature m_refTotals; + TFeature m_refFeature; + Signal m_other; + int m_blockSize; + int m_frameCount; + + Chromagram::Parameters paramsForTuningFrequency(double hz) const; + TFeature computeFeatureFromTotals(const TFeature &totals) const; + TFeature computeFeatureFromSignal(const Signal &signal, double hz) const; + double featureDistance(const TFeature &other, int rotation = 0) const; + int findBestRotation(const TFeature &other) const; + std::pair<int, double> findFineFrequency(int coarseCents, double coarseScore); + + mutable std::map<string, int> m_outputs; +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/plugins.cpp Thu Feb 05 10:13:31 2015 +0000 @@ -0,0 +1,21 @@ + +#include <vamp/vamp.h> +#include <vamp-sdk/PluginAdapter.h> + +#include "TuningDifference.h" + +static Vamp::PluginAdapter<TuningDifference> tdAdapter; + + +const VampPluginDescriptor * +vampGetPluginDescriptor(unsigned int version, unsigned int index) +{ + if (version < 1) return 0; + + switch (index) { + case 0: return tdAdapter.getDescriptor(); + default: return 0; + } +} + +
--- a/tuning-and-key/keycompare.sh Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -#!/bin/bash - -##!!! This is unfinished -- abandoned because a premise turned out not to be sound - -set -e - -mypath=`dirname $0` - -sonic-annotator --minversion 1.1 || exit 1 - -reference="$1" -other="$2" - -usage() { - echo "Usage: $0 reference.wav other.wav" 1>&2 - exit 2 -} - -test -n "$reference" || usage -test -n "$other" || usage - -set -u - -transform="/tmp/$$.ttl" -trap "rm $transform" 0 - -provisional=$(sonic-annotator -d vamp:nnls-chroma:tuning:tuning "$other" -w csv --csv-stdout | tail -1 | awk -F, '{ print $4 }') - -ref_tonic=$(sonic-annotator -t "keydetector.ttl" "$reference" -w csv --csv-stdout --csv-omit-filename --summary mode|tail -1|awk -F, '{ print $4 }') - -cat "keydetector.ttl" | sed "s,440,$provisional," > "$transform" - -tonic=$(sonic-annotator -t "$transform" "$other" -w csv --csv-stdout --csv-omit-filename --summary mode|tail -1|awk -F, '{ print $4 }') - -# modular arithmetic here is wrong. but it turns out our tuning freq -# estimation above is also wrong anyway for our test file - -sum="print ($provisional * (2.0 ** ((($tonic - $ref_tonic) % 12) / 12.0)))" -freq=$(perl -e "$sum") - -echo "Sum is: $sum" -echo "Estimated frequency is $freq (provisional: $provisional; reference tonic: $ref_tonic; test tonic: $tonic)" -
--- a/tuning-and-key/keydetector.ttl Thu Feb 05 09:52:28 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . -@prefix vamp: <http://purl.org/ontology/vamp/> . -@prefix : <#> . - -:param_tuningfreq - vamp:parameter [ vamp:identifier "tuning" ] ; - vamp:value "440"^^xsd:float . - -:transform_a a vamp:Transform ; - vamp:plugin <http://vamp-plugins.org/rdf/plugins/qm-vamp-plugins#qm-keydetector> ; - vamp:sample_rate "44100"^^xsd:int ; - vamp:parameter_binding :param_tuningfreq ; - vamp:output [ vamp:identifier "tonic" ] . -