bringing vamp-sdk into 2.0-ongoing branch
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 10 Jan 2008 13:47:50 +0000 (13:47 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Thu, 10 Jan 2008 13:47:50 +0000 (13:47 +0000)
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2867 d708f5d6-7413-0410-9779-e7cbd77b26cf

39 files changed:
libs/vamp-sdk/COPYING [new file with mode: 0644]
libs/vamp-sdk/Doxyfile [new file with mode: 0644]
libs/vamp-sdk/Makefile [new file with mode: 0644]
libs/vamp-sdk/README [new file with mode: 0644]
libs/vamp-sdk/examples/AmplitudeFollower.cpp [new file with mode: 0644]
libs/vamp-sdk/examples/AmplitudeFollower.h [new file with mode: 0644]
libs/vamp-sdk/examples/PercussionOnsetDetector.cpp [new file with mode: 0644]
libs/vamp-sdk/examples/PercussionOnsetDetector.h [new file with mode: 0644]
libs/vamp-sdk/examples/SpectralCentroid.cpp [new file with mode: 0644]
libs/vamp-sdk/examples/SpectralCentroid.h [new file with mode: 0644]
libs/vamp-sdk/examples/ZeroCrossing.cpp [new file with mode: 0644]
libs/vamp-sdk/examples/ZeroCrossing.h [new file with mode: 0644]
libs/vamp-sdk/examples/plugins.cpp [new file with mode: 0644]
libs/vamp-sdk/examples/vamp-example-plugins.cat [new file with mode: 0644]
libs/vamp-sdk/host/system.h [new file with mode: 0644]
libs/vamp-sdk/host/vamp-simple-host.cpp [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/Plugin.h [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/PluginAdapter.cpp [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/PluginAdapter.h [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/PluginBase.h [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/PluginHostAdapter.cpp [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/PluginHostAdapter.h [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/RealTime.cpp [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/RealTime.h [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/doc-overview [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.cpp [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.h [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.cpp [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.h [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.h [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.cpp [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.h [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/libvamp-hostsdk.la.in [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/libvamp-sdk.la.in [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/vamp-hostsdk.pc.in [new file with mode: 0644]
libs/vamp-sdk/vamp-sdk/vamp-sdk.pc.in [new file with mode: 0644]
libs/vamp-sdk/vamp/vamp.h [new file with mode: 0644]
libs/vamp-sdk/vamp/vamp.pc.in [new file with mode: 0644]

diff --git a/libs/vamp-sdk/COPYING b/libs/vamp-sdk/COPYING
new file mode 100644 (file)
index 0000000..19fa472
--- /dev/null
@@ -0,0 +1,26 @@
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+
diff --git a/libs/vamp-sdk/Doxyfile b/libs/vamp-sdk/Doxyfile
new file mode 100644 (file)
index 0000000..e8dfca3
--- /dev/null
@@ -0,0 +1,1235 @@
+# Doxyfile 1.4.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = Vamp Plugin SDK
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         = 1.1
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP         = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is YES.
+
+SHOW_DIRECTORIES       = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the progam writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           = docs/doxygen/warning.log
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  = vamp vamp-sdk vamp-sdk/hostext examples host
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS          = *.h \
+                         *.C \
+                         *.cpp \
+                         *.cc \
+                         doc-overview
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = qrc_*.cpp \
+                         moc_*.cpp \
+                         *.moc.cpp \
+                         *_skel.cpp
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.  Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.  The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+#USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 3
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.  This is useful
+# if you want to understand what is going on.  On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = NO
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             = HAVE_FFTW3F HAVE_FISHSOUND HAVE_JACK HAVE_LIBLO HAVE_LRDF HAVE_MAD HAVE_OGGZ HAVE_PORTAUDIO HAVE_SAMPLERATE HAVE_SNDFILE HAVE_VAMP
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#   TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#   TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS         = NO
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = NO
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/libs/vamp-sdk/Makefile b/libs/vamp-sdk/Makefile
new file mode 100644 (file)
index 0000000..5253ff4
--- /dev/null
@@ -0,0 +1,249 @@
+
+# Makefile for the Vamp plugin SDK.  This builds the SDK objects,
+# libraries, example plugins, and the test host.  Please adjust to
+# suit your operating system requirements.
+
+APIDIR         = vamp
+SDKDIR         = vamp-sdk
+HOSTEXTDIR      = vamp-sdk/hostext
+EXAMPLEDIR     = examples
+HOSTDIR                = host
+
+###
+### Start of user-serviceable parts
+###
+
+# Default build target (or use "make <target>" to select one).
+# Targets are:
+#   all       -- build everything
+#   sdk       -- build all the Vamp SDK libraries for plugins and hosts
+#   sdkstatic -- build only the static versions of the SDK libraries
+#   plugins   -- build the example plugins (and the SDK if required)
+#   host      -- build the simple Vamp plugin host (and the SDK if required)
+#   test      -- build the host and example plugins, and run a quick test
+#   clean     -- remove binary targets
+#   distclean -- remove all targets
+#
+default:       all
+
+# Compile flags
+#
+CXXFLAGS       := $(CXXFLAGS) -O2 -Wall -I. -fpic
+
+# ar, ranlib
+#
+AR             := ar
+RANLIB         := ranlib
+
+# Libraries required for the plugins.
+# (Note that it is desirable to statically link libstdc++ if possible,
+# because our plugin exposes only a C API so there are no boundary
+# compatibility problems.)
+#
+PLUGIN_LIBS    = $(SDKDIR)/libvamp-sdk.a
+#PLUGIN_LIBS   = $(SDKDIR)/libvamp-sdk.a $(shell g++ -print-file-name=libstdc++.a)
+
+# File extension for a dynamically loadable object
+#
+PLUGIN_EXT     = .so
+#PLUGIN_EXT    = .dll
+#PLUGIN_EXT    = .dylib
+
+# Libraries required for the host.
+#
+HOST_LIBS      = $(SDKDIR)/libvamp-hostsdk.a -lsndfile -ldl
+
+# Locations for "make install".  This will need quite a bit of 
+# editing for non-Linux platforms.  Of course you don't necessarily
+# have to use "make install".
+#
+INSTALL_PREFIX           := /usr
+INSTALL_API_HEADERS      := $(INSTALL_PREFIX)/include/vamp
+INSTALL_SDK_HEADERS      := $(INSTALL_PREFIX)/include/vamp-sdk
+INSTALL_HOSTEXT_HEADERS          := $(INSTALL_PREFIX)/include/vamp-sdk/hostext
+INSTALL_SDK_LIBS         := $(INSTALL_PREFIX)/lib
+
+INSTALL_SDK_LIBNAME      := libvamp-sdk.so.1.1.0
+INSTALL_SDK_LINK_ABI     := libvamp-sdk.so.1
+INSTALL_SDK_LINK_DEV     := libvamp-sdk.so
+INSTALL_SDK_STATIC        := libvamp-sdk.a
+INSTALL_SDK_LA            := libvamp-sdk.la
+
+INSTALL_HOSTSDK_LIBNAME   := libvamp-hostsdk.so.2.0.0
+INSTALL_HOSTSDK_LINK_ABI  := libvamp-hostsdk.so.2
+INSTALL_HOSTSDK_LINK_DEV  := libvamp-hostsdk.so
+INSTALL_HOSTSDK_STATIC    := libvamp-hostsdk.a
+INSTALL_HOSTSDK_LA        := libvamp-hostsdk.la
+
+INSTALL_PKGCONFIG        := $(INSTALL_PREFIX)/lib/pkgconfig
+
+# Flags required to tell the compiler to create a dynamically loadable object
+#
+DYNAMIC_LDFLAGS                = -shared -Wl,-Bsymbolic
+PLUGIN_LDFLAGS         = $(DYNAMIC_LDFLAGS)
+SDK_DYNAMIC_LDFLAGS    = $(DYNAMIC_LDFLAGS) -Wl,-soname=$(INSTALL_SDK_LIBNAME)
+HOSTSDK_DYNAMIC_LDFLAGS        = $(DYNAMIC_LDFLAGS) -Wl,-soname=$(INSTALL_HOSTSDK_LIBNAME)
+
+## For OS/X with g++:
+#PLUGIN_LDFLAGS        = -dynamiclib
+
+
+### End of user-serviceable parts
+
+
+API_HEADERS    = \
+               $(APIDIR)/vamp.h
+
+SDK_HEADERS    = \
+               $(SDKDIR)/Plugin.h \
+               $(SDKDIR)/PluginAdapter.h \
+               $(SDKDIR)/PluginBase.h \
+               $(SDKDIR)/RealTime.h
+
+HOSTSDK_HEADERS        = \
+               $(SDKDIR)/Plugin.h \
+               $(SDKDIR)/PluginBase.h \
+               $(SDKDIR)/PluginHostAdapter.h \
+               $(SDKDIR)/RealTime.h
+
+HOSTEXT_HEADERS = \
+               $(HOSTEXTDIR)/PluginChannelAdapter.h \
+               $(HOSTEXTDIR)/PluginInputDomainAdapter.h \
+               $(HOSTEXTDIR)/PluginLoader.h \
+               $(HOSTEXTDIR)/PluginWrapper.h
+
+SDK_OBJECTS    = \
+               $(SDKDIR)/PluginAdapter.o \
+               $(SDKDIR)/RealTime.o
+
+HOSTSDK_OBJECTS        = \
+               $(SDKDIR)/PluginHostAdapter.o \
+               $(HOSTEXTDIR)/PluginChannelAdapter.o \
+               $(HOSTEXTDIR)/PluginInputDomainAdapter.o \
+               $(HOSTEXTDIR)/PluginLoader.o \
+               $(HOSTEXTDIR)/PluginWrapper.o \
+               $(SDKDIR)/RealTime.o
+
+SDK_STATIC     = \
+               $(SDKDIR)/libvamp-sdk.a
+
+HOSTSDK_STATIC = \
+               $(SDKDIR)/libvamp-hostsdk.a
+
+SDK_DYNAMIC    = \
+               $(SDKDIR)/libvamp-sdk.so
+
+HOSTSDK_DYNAMIC        = \
+               $(SDKDIR)/libvamp-hostsdk.so
+
+SDK_LA         = \
+               $(SDKDIR)/libvamp-sdk.la
+
+HOSTSDK_LA     = \
+               $(SDKDIR)/libvamp-hostsdk.la
+
+PLUGIN_HEADERS = \
+               $(EXAMPLEDIR)/SpectralCentroid.h \
+               $(EXAMPLEDIR)/PercussionOnsetDetector.h \
+               $(EXAMPLEDIR)/AmplitudeFollower.h \
+               $(EXAMPLEDIR)/ZeroCrossing.h
+
+PLUGIN_OBJECTS = \
+               $(EXAMPLEDIR)/SpectralCentroid.o \
+               $(EXAMPLEDIR)/PercussionOnsetDetector.o \
+               $(EXAMPLEDIR)/AmplitudeFollower.o \
+               $(EXAMPLEDIR)/ZeroCrossing.o \
+               $(EXAMPLEDIR)/plugins.o
+
+PLUGIN_TARGET  = \
+               $(EXAMPLEDIR)/vamp-example-plugins$(PLUGIN_EXT)
+
+HOST_HEADERS   = \
+               $(HOSTDIR)/system.h
+
+HOST_OBJECTS   = \
+               $(HOSTDIR)/vamp-simple-host.o
+
+HOST_TARGET    = \
+               $(HOSTDIR)/vamp-simple-host
+
+sdk:           sdkstatic $(SDK_DYNAMIC) $(HOSTSDK_DYNAMIC)
+
+sdkstatic:     $(SDK_STATIC) $(HOSTSDK_STATIC)
+               $(RANLIB) $(SDK_STATIC)
+               $(RANLIB) $(HOSTSDK_STATIC)
+
+plugins:       $(PLUGIN_TARGET)
+
+host:          $(HOST_TARGET)
+
+all:           sdk plugins host test
+
+$(SDK_STATIC): $(SDK_OBJECTS) $(API_HEADERS) $(SDK_HEADERS)
+               $(AR) r $@ $(SDK_OBJECTS)
+
+$(HOSTSDK_STATIC):     $(HOSTSDK_OBJECTS) $(API_HEADERS) $(HOSTSDK_HEADERS) $(HOSTEXT_HEADERS)
+               $(AR) r $@ $(HOSTSDK_OBJECTS)
+
+$(SDK_DYNAMIC):        $(SDK_OBJECTS) $(API_HEADERS) $(SDK_HEADERS)
+               $(CXX) $(LDFLAGS) $(SDK_DYNAMIC_LDFLAGS) -o $@ $(SDK_OBJECTS)
+
+$(HOSTSDK_DYNAMIC):    $(HOSTSDK_OBJECTS) $(API_HEADERS) $(HOSTSDK_HEADERS) $(HOSTEXT_HEADERS)
+               $(CXX) $(LDFLAGS) $(HOSTSDK_DYNAMIC_LDFLAGS) -o $@ $(HOSTSDK_OBJECTS)
+
+$(PLUGIN_TARGET):      $(PLUGIN_OBJECTS) $(SDK_STATIC) $(PLUGIN_HEADERS)
+               $(CXX) $(LDFLAGS) $(PLUGIN_LDFLAGS) -o $@ $(PLUGIN_OBJECTS) $(PLUGIN_LIBS)
+
+$(HOST_TARGET):        $(HOST_OBJECTS) $(HOSTSDK_STATIC) $(HOST_HEADERS)
+               $(CXX) $(LDFLAGS) $(HOST_LDFLAGS) -o $@ $(HOST_OBJECTS) $(HOST_LIBS)
+
+test:          plugins host
+               VAMP_PATH=$(EXAMPLEDIR) $(HOST_TARGET) -l
+
+clean:         
+               rm -f $(SDK_OBJECTS) $(HOSTSDK_OBJECTS) $(PLUGIN_OBJECTS) $(HOST_OBJECTS)
+
+distclean:     clean
+               rm -f $(SDK_STATIC) $(SDK_DYNAMIC) $(HOSTSDK_STATIC) $(HOSTSDK_DYNAMIC) $(PLUGIN_TARGET) $(HOST_TARGET) *~ */*~
+
+install:       $(SDK_STATIC) $(SDK_DYNAMIC) $(HOSTSDK_STATIC) $(HOSTSDK_DYNAMIC) $(PLUGIN_TARGET) $(HOST_TARGET)
+               mkdir -p $(INSTALL_API_HEADERS)
+               mkdir -p $(INSTALL_SDK_HEADERS)
+               mkdir -p $(INSTALL_HOSTEXT_HEADERS)
+               mkdir -p $(INSTALL_SDK_LIBS)
+               mkdir -p $(INSTALL_PKGCONFIG)
+               cp $(API_HEADERS) $(INSTALL_API_HEADERS)
+               cp $(SDK_HEADERS) $(INSTALL_SDK_HEADERS)
+               cp $(HOSTSDK_HEADERS) $(INSTALL_SDK_HEADERS)
+               cp $(HOSTEXT_HEADERS) $(INSTALL_HOSTEXT_HEADERS)
+               cp $(SDK_STATIC) $(INSTALL_SDK_LIBS)
+               cp $(HOSTSDK_STATIC) $(INSTALL_SDK_LIBS)
+               cp $(SDK_DYNAMIC) $(INSTALL_SDK_LIBS)/$(INSTALL_SDK_LIBNAME)
+               cp $(HOSTSDK_DYNAMIC) $(INSTALL_SDK_LIBS)/$(INSTALL_HOSTSDK_LIBNAME)
+               rm -f $(INSTALL_SDK_LIBS)/$(INSTALL_SDK_LINK_ABI)
+               ln -s $(INSTALL_SDK_LIBNAME) $(INSTALL_SDK_LIBS)/$(INSTALL_SDK_LINK_ABI)
+               rm -f $(INSTALL_SDK_LIBS)/$(INSTALL_HOSTSDK_LINK_ABI)
+               ln -s $(INSTALL_HOSTSDK_LIBNAME) $(INSTALL_SDK_LIBS)/$(INSTALL_HOSTSDK_LINK_ABI)
+               rm -f $(INSTALL_SDK_LIBS)/$(INSTALL_SDK_LINK_DEV)
+               ln -s $(INSTALL_SDK_LIBNAME) $(INSTALL_SDK_LIBS)/$(INSTALL_SDK_LINK_DEV)
+               rm -f $(INSTALL_SDK_LIBS)/$(INSTALL_HOSTSDK_LINK_DEV)
+               ln -s $(INSTALL_HOSTSDK_LIBNAME) $(INSTALL_SDK_LIBS)/$(INSTALL_HOSTSDK_LINK_DEV)
+               sed "s,%PREFIX%,$(INSTALL_PREFIX)," $(APIDIR)/vamp.pc.in \
+               > $(INSTALL_PKGCONFIG)/vamp.pc
+               sed "s,%PREFIX%,$(INSTALL_PREFIX)," $(SDKDIR)/vamp-sdk.pc.in \
+               > $(INSTALL_PKGCONFIG)/vamp-sdk.pc
+               sed "s,%PREFIX%,$(INSTALL_PREFIX)," $(SDKDIR)/vamp-hostsdk.pc.in \
+               > $(INSTALL_PKGCONFIG)/vamp-hostsdk.pc
+               sed -e "s,%LIBNAME%,$(INSTALL_SDK_LIBNAME),g" \
+                   -e "s,%LINK_ABI%,$(INSTALL_SDK_LINK_ABI),g" \
+                   -e "s,%LINK_DEV%,$(INSTALL_SDK_LINK_DEV),g" \
+                   -e "s,%STATIC%,$(INSTALL_SDK_STATIC),g" \
+                   -e "s,%LIBS%,$(INSTALL_SDK_LIBS),g" $(SDK_LA).in \
+               > $(INSTALL_SDK_LIBS)/$(INSTALL_SDK_LA)
+               sed -e "s,%LIBNAME%,$(INSTALL_HOSTSDK_LIBNAME),g" \
+                   -e "s,%LINK_ABI%,$(INSTALL_HOSTSDK_LINK_ABI),g" \
+                   -e "s,%LINK_DEV%,$(INSTALL_HOSTSDK_LINK_DEV),g" \
+                   -e "s,%STATIC%,$(INSTALL_HOSTSDK_STATIC),g" \
+                   -e "s,%LIBS%,$(INSTALL_SDK_LIBS),g" $(HOSTSDK_LA).in \
+               > $(INSTALL_SDK_LIBS)/$(INSTALL_HOSTSDK_LA)
+
diff --git a/libs/vamp-sdk/README b/libs/vamp-sdk/README
new file mode 100644 (file)
index 0000000..9454038
--- /dev/null
@@ -0,0 +1,240 @@
+
+Vamp
+====
+
+An API for audio analysis and feature extraction plugins.
+
+   http://www.vamp-plugins.org/
+
+Vamp is an API for C and C++ plugins that process sampled audio data
+to produce descriptive output (measurements or semantic observations).
+
+The principal differences between Vamp and a real-time audio
+processing plugin system such as VST are:
+
+ * Vamp plugins may output complex multidimensional data with labels.
+   As a consequence, they are likely to work best when the output
+   data has a much lower sampling rate than the input.  (This also
+   means it is usually desirable to implement them in C++ using the
+   high-level base class provided rather than use the raw C API.)
+
+ * While Vamp plugins receive data block-by-block, they are not
+   required to return output immediately on receiving the input.
+   A Vamp plugin may be non-causal, preferring to store up data
+   based on its input until the end of a processing run and then
+   return all results at once.
+
+ * Vamp plugins have more control over their inputs than a typical
+   real-time processing plugin.  For example, they can indicate to
+   the host their preferred processing block and step sizes, and these
+   may differ.
+
+ * Vamp plugins may ask to receive data in the frequency domain
+   instead of the time domain.  The host takes the responsibility
+   for converting the input data using an FFT of windowed frames.
+   This simplifies plugins that do straightforward frequency-domain
+   processing and permits the host to cache frequency-domain data
+   when possible.
+
+ * A Vamp plugin is configured once before each processing run, and
+   receives no further parameter changes during use -- unlike real-
+   time plugin APIs in which the input parameters may change at any
+   time.  This also means that fundamental properties such as the
+   number of values per output or the preferred processing block
+   size may depend on the input parameters.
+
+ * Vamp plugins do not have to be able to run in real time.
+
+
+About this SDK
+==============
+
+This is version 1.1b of the Vamp plugin Software Development Kit.
+Plugins and hosts built with this SDK are binary compatible with those
+built using version 1.0 of the SDK.
+
+This SDK contains the following:
+
+ * vamp/vamp.h
+
+The formal C language plugin API for Vamp plugins.
+
+A Vamp plugin is a dynamic library (.so, .dll or .dylib depending on
+platform) exposing one C-linkage entry point (vampGetPluginDescriptor)
+which returns data defined in the rest of this C header.
+
+Although the C API is the official API for Vamp, we don't recommend
+that you program directly to it.  The C++ abstraction found in the
+vamp-sdk directory (below) is preferable for most purposes and is
+more thoroughly documented.
+
+ * vamp-sdk
+
+C++ classes for straightforwardly implementing Vamp plugins and hosts.
+
+Plugins should subclass Vamp::Plugin and then use Vamp::PluginAdapter
+to expose the correct C API for the plugin.  Plugin authors should
+read vamp-sdk/PluginBase.h and Plugin.h for code documentation, and
+refer to the example plugin code in the examples directory.  Plugins
+should link with -lvampsdk.  [*NOTE: this has changed from vamp-sdk in
+previous versions, to avoid conflict with the use of hyphens for
+library versioning schemes on some platforms.]
+
+Hosts may use the Vamp::PluginHostAdapter to convert the loaded
+plugin's C API back into a Vamp::Plugin object.  Host authors should
+refer to the example host code in the host directory.  Hosts should
+link with -lvamphostsdk.  [*NOTE: this has changed from vamp-hostsdk
+in previous versions, to avoid conflict with the use of hyphens for
+library versioning schemes on some platforms.]
+
+ * vamp-sdk/hostext
+
+Additional C++ classes to make a host's life easier (introduced in
+version 1.1 of the Vamp SDK).
+
+Vamp::HostExt::PluginLoader provides a very easy interface for a host
+to discover, load, and find out category information about the
+available plugins.  Most "casual" Vamp hosts will probably want to use
+this class.
+
+Vamp::HostExt::PluginInputDomainAdapter provides a means for hosts to
+handle plugins that expect frequency-domain input, without having to
+convert the input themselves.
+
+Vamp::HostExt::PluginChannelAdapter provides a means for hosts to use
+plugins that do not necessarily support the same number of audio
+channels as they have available, without having to worry about
+applying a channel management / mixdown policy themselves.
+
+The PluginLoader class can also use the input domain and channel
+adapters automatically to make the entire conversion process
+transparent to the host if required.
+
+ * examples
+
+Example plugins implemented using the C++ classes.  ZeroCrossing
+calculates the positions and density of zero-crossing points in an
+audio waveform.  SpectralCentroid calculates the centre of gravity of
+the frequency domain representation of each block of audio.
+AmplitudeFollower tracks the amplitude of a signal based on a method
+from the SuperCollider real-time audio system.
+PercussionOnsetDetector estimates the locations of percussive onsets
+using a simple method described in "Drum Source Separation using
+Percussive Feature Detection and Spectral Modulation" by Dan Barry,
+Derry Fitzgerald, Eugene Coyle and Bob Lawlor, ISSC 2005.
+
+ * host
+
+A simple command-line Vamp host, capable of loading a plugin and using
+it to process a complete audio file, with its default parameters.
+Requires libsndfile (http://www.mega-nerd.com/libsndfile/).
+
+If you don't have libsndfile, you may want to edit the Makefile to
+change the default build target from "all" to "sdk", so as to compile
+only the SDK and not the host.
+
+
+Plugin Lookup and Categorisation
+================================
+
+The Vamp API does not officially specify how to load plugin libraries
+or where to find them.  However, the SDK does include a function
+(Vamp::PluginHostAdapter::getPluginPath()) that returns a recommended
+directory search path that hosts may use for plugin libraries, and a
+class (Vamp::HostExt::PluginLoader) that implements a sensible
+cross-platform lookup policy using this path.  We recommend using this
+class in your host unless you have a good reason not to want to.  This
+implementation also permits the user to set the environment variable
+VAMP_PATH to override the default path if desired.
+
+The policy used by Vamp::HostExt::PluginLoader -- and our
+recommendation for any host -- is to search each directory in the path
+returned by getPluginPath for .DLL (on Windows), .so (on Linux,
+Solaris, BSD etc) or .dylib (on OS/X) files, then to load each one and
+perform a dynamic name lookup on the vampGetPluginDescriptor function
+to enumerate the plugins in the library.  This operation will
+necessarily be system-dependent.
+
+Vamp also has an informal convention for sorting plugins into
+functional categories.  In addition to the library file itself, a
+plugin library may install a category file with the same name as the
+library but .cat extension.  The existence and format of this file are
+not specified by the Vamp API, but by convention the file may contain
+lines of the format
+
+vamp:pluginlibrary:pluginname::General Category > Specific Category
+
+which a host may read and use to assign plugins a location within a
+category tree for display to the user.  The expectation is that
+advanced users may also choose to set up their own preferred category
+trees, which is why this information is not queried as part of the
+Vamp plugin's API itself.  The Vamp::HostExt::PluginLoader class also
+provides support for plugin category lookup using this scheme.
+
+
+Building and Installing the SDK and Examples
+============================================
+
+To build the SDK, the simple host, and the example plugins, edit the
+Makefile to suit your platform according to the comments in it, then
+run "make".
+
+To use an IDE to build a plugin or host using the Vamp SDK, simply add
+the .cpp files in the vamp-sdk directory to your project.
+
+Installing the example plugins so that they can be found by other Vamp
+hosts depends on your platform:
+
+ * Windows: copy the files
+      examples/vamp-example-plugins.dll
+      examples/vamp-example-plugins.cat
+   to
+      C:\Program Files\Vamp Plugins
+
+ * Linux: copy the files
+      examples/vamp-example-plugins.so
+      examples/vamp-example-plugins.cat
+   to
+      /usr/local/lib/vamp/
+
+ * OS/X: copy the files
+      examples/vamp-example-plugins.dylib
+      examples/vamp-example-plugins.cat
+   to
+      /Library/Audio/Plug-Ins/Vamp
+
+
+Licensing
+=========
+
+This plugin SDK is freely redistributable under a "new-style BSD"
+licence.  See the file COPYING for more details.  In short, you may
+modify and redistribute the SDK and example plugins within any
+commercial or non-commercial, proprietary or open-source plugin or
+application under almost any conditions, with no obligation to provide
+source code, provided you retain the original copyright note.
+
+
+See Also
+========
+
+Sonic Visualiser, an interactive open-source graphical audio
+inspection, analysis and visualisation tool supporting Vamp plugins.
+http://www.sonicvisualiser.org/
+
+
+Authors
+=======
+
+Vamp and the Vamp SDK were designed and made at the Centre for Digital
+Music at Queen Mary, University of London.
+
+The SDK was written by Chris Cannam, copyright (c) 2005-2007
+Chris Cannam and QMUL.
+
+Mark Sandler and Christian Landone provided ideas and direction, and
+Mark Levy, Dan Stowell, Martin Gasser and Craig Sapp provided testing
+and other input for the 1.0 API and SDK.  The API also uses some ideas
+from prior plugin systems, notably DSSI (http://dssi.sourceforge.net)
+and FEAPI (http://feapi.sourceforge.net).
+
diff --git a/libs/vamp-sdk/examples/AmplitudeFollower.cpp b/libs/vamp-sdk/examples/AmplitudeFollower.cpp
new file mode 100644 (file)
index 0000000..7023297
--- /dev/null
@@ -0,0 +1,247 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Dan Stowell.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "AmplitudeFollower.h"
+
+#include <cmath>
+
+#include <string>
+#include <vector>
+#include <iostream>
+
+using std::string;
+using std::vector;
+using std::cerr;
+using std::endl;
+
+/**
+ * An implementation of SuperCollider's amplitude-follower algorithm
+ * as a simple Vamp plugin.
+ */
+
+AmplitudeFollower::AmplitudeFollower(float inputSampleRate) :
+    Plugin(inputSampleRate),
+    m_stepSize(0),
+    m_previn(0.0f),
+    m_clampcoef(0.01f),
+    m_relaxcoef(0.01f)
+{
+}
+
+AmplitudeFollower::~AmplitudeFollower()
+{
+}
+
+string
+AmplitudeFollower::getIdentifier() const
+{
+    return "amplitudefollower";
+}
+
+string
+AmplitudeFollower::getName() const
+{
+    return "Amplitude Follower";
+}
+
+string
+AmplitudeFollower::getDescription() const
+{
+    return "Track the amplitude of the audio signal";
+}
+
+string
+AmplitudeFollower::getMaker() const
+{
+    return "Vamp SDK Example Plugins";
+}
+
+int
+AmplitudeFollower::getPluginVersion() const
+{
+    return 1;
+}
+
+string
+AmplitudeFollower::getCopyright() const
+{
+    return "Code copyright 2006 Dan Stowell; method from SuperCollider.  Freely redistributable (BSD license)";
+}
+
+bool
+AmplitudeFollower::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    if (channels < getMinChannelCount() ||
+       channels > getMaxChannelCount()) return false;
+
+    m_stepSize = std::min(stepSize, blockSize);
+       
+    // Translate the coefficients 
+    // from their "convenient" 60dB convergence-time values
+    // to real coefficients
+    m_clampcoef = m_clampcoef==0.0 ? 0.0 : exp(log(0.1)/(m_clampcoef * m_inputSampleRate));
+    m_relaxcoef = m_relaxcoef==0.0 ? 0.0 : exp(log(0.1)/(m_relaxcoef * m_inputSampleRate));
+
+    return true;
+}
+
+void
+AmplitudeFollower::reset()
+{
+    m_previn = 0.0f;
+}
+
+AmplitudeFollower::OutputList
+AmplitudeFollower::getOutputDescriptors() const
+{
+    OutputList list;
+
+    OutputDescriptor sca;
+    sca.identifier = "amplitude";
+    sca.name = "Amplitude";
+    sca.description = "";
+    sca.unit = "V";
+    sca.hasFixedBinCount = true;
+    sca.binCount = 1;
+    sca.hasKnownExtents = false;
+    sca.isQuantized = false;
+    sca.sampleType = OutputDescriptor::OneSamplePerStep;
+    list.push_back(sca);
+
+    return list;
+}
+
+AmplitudeFollower::ParameterList
+AmplitudeFollower::getParameterDescriptors() const
+{
+    ParameterList list;
+       
+    ParameterDescriptor att;
+    att.identifier = "attack";
+    att.name = "Attack time";
+    att.description = "";
+    att.unit = "s";
+    att.minValue = 0.0f;
+    att.maxValue = 1.f;
+    att.defaultValue = 0.01f;
+    att.isQuantized = false;
+    
+    list.push_back(att);
+    
+    ParameterDescriptor dec;
+    dec.identifier = "release";
+    dec.name = "Release time";
+    dec.description = "";
+    dec.unit = "s";
+    dec.minValue = 0.0f;
+    dec.maxValue = 1.f;
+    dec.defaultValue = 0.01f;
+    dec.isQuantized = false;
+    
+    list.push_back(dec);
+    
+    return list;
+}
+
+void AmplitudeFollower::setParameter(std::string paramid, float newval)
+{
+    if (paramid == "attack") {
+        m_clampcoef = newval;
+    } else if (paramid == "release") {
+        m_relaxcoef = newval;
+    }
+}
+
+float AmplitudeFollower::getParameter(std::string paramid) const
+{
+    if (paramid == "attack") {
+        return m_clampcoef;
+    } else if (paramid == "release") {
+        return m_relaxcoef;
+    }
+
+    return 0.0f;
+}
+
+AmplitudeFollower::FeatureSet
+AmplitudeFollower::process(const float *const *inputBuffers,
+                           Vamp::RealTime timestamp)
+{
+    if (m_stepSize == 0) {
+       cerr << "ERROR: AmplitudeFollower::process: "
+            << "AmplitudeFollower has not been initialised"
+            << endl;
+       return FeatureSet();
+    }
+
+    float previn = m_previn;
+
+    FeatureSet returnFeatures;
+       
+    float val;
+    float peak = 0.0f;
+
+    for (size_t i = 0; i < m_stepSize; ++i) {
+
+        val = fabs(inputBuffers[0][i]);
+               
+        if (val < previn) {
+            val = val + (previn - val) * m_relaxcoef;
+        } else {
+            val = val + (previn - val) * m_clampcoef;
+        }
+
+        if (val > peak) peak = val;
+        previn = val;
+    }
+
+    m_previn = previn;
+
+    // Now store the "feature" (peak amp) for this sample
+    Feature feature;
+    feature.hasTimestamp = false;
+    feature.values.push_back(peak);
+    returnFeatures[0].push_back(feature);
+
+    return returnFeatures;
+}
+
+AmplitudeFollower::FeatureSet
+AmplitudeFollower::getRemainingFeatures()
+{
+    return FeatureSet();
+}
+
diff --git a/libs/vamp-sdk/examples/AmplitudeFollower.h b/libs/vamp-sdk/examples/AmplitudeFollower.h
new file mode 100644 (file)
index 0000000..6c3426e
--- /dev/null
@@ -0,0 +1,84 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Dan Stowell.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _AMPLITUDE_FOLLOWER_PLUGIN_H_
+#define _AMPLITUDE_FOLLOWER_PLUGIN_H_
+
+#include "vamp-sdk/Plugin.h"
+
+/**
+ * Example plugin implementing the SuperCollider amplitude follower
+ * function.
+ */
+
+class AmplitudeFollower : public Vamp::Plugin
+{
+public:
+    AmplitudeFollower(float inputSampleRate);
+    virtual ~AmplitudeFollower();
+
+    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;
+       
+    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;
+    float  m_previn;
+    float  m_clampcoef;
+    float  m_relaxcoef;
+};
+
+
+#endif
diff --git a/libs/vamp-sdk/examples/PercussionOnsetDetector.cpp b/libs/vamp-sdk/examples/PercussionOnsetDetector.cpp
new file mode 100644 (file)
index 0000000..447eb19
--- /dev/null
@@ -0,0 +1,285 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "PercussionOnsetDetector.h"
+
+using std::string;
+using std::vector;
+using std::cerr;
+using std::endl;
+
+#include <cmath>
+
+
+PercussionOnsetDetector::PercussionOnsetDetector(float inputSampleRate) :
+    Plugin(inputSampleRate),
+    m_stepSize(0),
+    m_blockSize(0),
+    m_threshold(3),
+    m_sensitivity(40),
+    m_priorMagnitudes(0),
+    m_dfMinus1(0),
+    m_dfMinus2(0)
+{
+}
+
+PercussionOnsetDetector::~PercussionOnsetDetector()
+{
+    delete[] m_priorMagnitudes;
+}
+
+string
+PercussionOnsetDetector::getIdentifier() const
+{
+    return "percussiononsets";
+}
+
+string
+PercussionOnsetDetector::getName() const
+{
+    return "Simple Percussion Onset Detector";
+}
+
+string
+PercussionOnsetDetector::getDescription() const
+{
+    return "Detect percussive note onsets by identifying broadband energy rises";
+}
+
+string
+PercussionOnsetDetector::getMaker() const
+{
+    return "Vamp SDK Example Plugins";
+}
+
+int
+PercussionOnsetDetector::getPluginVersion() const
+{
+    return 2;
+}
+
+string
+PercussionOnsetDetector::getCopyright() const
+{
+    return "Code copyright 2006 Queen Mary, University of London, after Dan Barry et al 2005.  Freely redistributable (BSD license)";
+}
+
+size_t
+PercussionOnsetDetector::getPreferredStepSize() const
+{
+    return 0;
+}
+
+size_t
+PercussionOnsetDetector::getPreferredBlockSize() const
+{
+    return 1024;
+}
+
+bool
+PercussionOnsetDetector::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    if (channels < getMinChannelCount() ||
+       channels > getMaxChannelCount()) return false;
+
+    m_stepSize = stepSize;
+    m_blockSize = blockSize;
+
+    m_priorMagnitudes = new float[m_blockSize/2];
+
+    for (size_t i = 0; i < m_blockSize/2; ++i) {
+        m_priorMagnitudes[i] = 0.f;
+    }
+
+    m_dfMinus1 = 0.f;
+    m_dfMinus2 = 0.f;
+
+    return true;
+}
+
+void
+PercussionOnsetDetector::reset()
+{
+    for (size_t i = 0; i < m_blockSize/2; ++i) {
+        m_priorMagnitudes[i] = 0.f;
+    }
+
+    m_dfMinus1 = 0.f;
+    m_dfMinus2 = 0.f;
+}
+
+PercussionOnsetDetector::ParameterList
+PercussionOnsetDetector::getParameterDescriptors() const
+{
+    ParameterList list;
+
+    ParameterDescriptor d;
+    d.identifier = "threshold";
+    d.name = "Energy rise threshold";
+    d.description = "Energy rise within a frequency bin necessary to count toward broadband total";
+    d.unit = "dB";
+    d.minValue = 0;
+    d.maxValue = 20;
+    d.defaultValue = 3;
+    d.isQuantized = false;
+    list.push_back(d);
+
+    d.identifier = "sensitivity";
+    d.name = "Sensitivity";
+    d.description = "Sensitivity of peak detector applied to broadband detection function";
+    d.unit = "%";
+    d.minValue = 0;
+    d.maxValue = 100;
+    d.defaultValue = 40;
+    d.isQuantized = false;
+    list.push_back(d);
+
+    return list;
+}
+
+float
+PercussionOnsetDetector::getParameter(std::string id) const
+{
+    if (id == "threshold") return m_threshold;
+    if (id == "sensitivity") return m_sensitivity;
+    return 0.f;
+}
+
+void
+PercussionOnsetDetector::setParameter(std::string id, float value)
+{
+    if (id == "threshold") {
+        if (value < 0) value = 0;
+        if (value > 20) value = 20;
+        m_threshold = value;
+    } else if (id == "sensitivity") {
+        if (value < 0) value = 0;
+        if (value > 100) value = 100;
+        m_sensitivity = value;
+    }
+}
+
+PercussionOnsetDetector::OutputList
+PercussionOnsetDetector::getOutputDescriptors() const
+{
+    OutputList list;
+
+    OutputDescriptor d;
+    d.identifier = "onsets";
+    d.name = "Onsets";
+    d.description = "Percussive note onset locations";
+    d.unit = "";
+    d.hasFixedBinCount = true;
+    d.binCount = 0;
+    d.hasKnownExtents = false;
+    d.isQuantized = false;
+    d.sampleType = OutputDescriptor::VariableSampleRate;
+    d.sampleRate = m_inputSampleRate;
+    list.push_back(d);
+
+    d.identifier = "detectionfunction";
+    d.name = "Detection Function";
+    d.description = "Broadband energy rise detection function";
+    d.binCount = 1;
+    d.isQuantized = true;
+    d.quantizeStep = 1.0;
+    d.sampleType = OutputDescriptor::OneSamplePerStep;
+    list.push_back(d);
+
+    return list;
+}
+
+PercussionOnsetDetector::FeatureSet
+PercussionOnsetDetector::process(const float *const *inputBuffers,
+                                 Vamp::RealTime ts)
+{
+    if (m_stepSize == 0) {
+       cerr << "ERROR: PercussionOnsetDetector::process: "
+            << "PercussionOnsetDetector has not been initialised"
+            << endl;
+       return FeatureSet();
+    }
+
+    int count = 0;
+
+    for (size_t i = 1; i < m_blockSize/2; ++i) {
+
+        float real = inputBuffers[0][i*2];
+        float imag = inputBuffers[0][i*2 + 1];
+
+        float sqrmag = real * real + imag * imag;
+
+        if (m_priorMagnitudes[i] > 0.f) {
+            float diff = 10.f * log10f(sqrmag / m_priorMagnitudes[i]);
+
+//        std::cout << "i=" << i << ", mag=" << mag << ", prior=" << m_priorMagnitudes[i] << ", diff=" << diff << ", threshold=" << m_threshold << std::endl;
+
+            if (diff >= m_threshold) ++count;
+        }
+
+        m_priorMagnitudes[i] = sqrmag;
+    }
+
+    FeatureSet returnFeatures;
+
+    Feature detectionFunction;
+    detectionFunction.hasTimestamp = false;
+    detectionFunction.values.push_back(count);
+    returnFeatures[1].push_back(detectionFunction);
+
+    if (m_dfMinus2 < m_dfMinus1 &&
+        m_dfMinus1 >= count &&
+        m_dfMinus1 > ((100 - m_sensitivity) * m_blockSize) / 200) {
+
+        Feature onset;
+        onset.hasTimestamp = true;
+        onset.timestamp = ts - Vamp::RealTime::frame2RealTime
+            (m_stepSize, lrintf(m_inputSampleRate));
+        returnFeatures[0].push_back(onset);
+    }
+
+    m_dfMinus2 = m_dfMinus1;
+    m_dfMinus1 = count;
+
+    return returnFeatures;
+}
+
+PercussionOnsetDetector::FeatureSet
+PercussionOnsetDetector::getRemainingFeatures()
+{
+    return FeatureSet();
+}
+
diff --git a/libs/vamp-sdk/examples/PercussionOnsetDetector.h b/libs/vamp-sdk/examples/PercussionOnsetDetector.h
new file mode 100644 (file)
index 0000000..d54c0cf
--- /dev/null
@@ -0,0 +1,90 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _PERCUSSION_ONSET_DETECTOR_PLUGIN_H_
+#define _PERCUSSION_ONSET_DETECTOR_PLUGIN_H_
+
+#include "vamp-sdk/Plugin.h"
+
+/**
+ * Example plugin that detects percussive events.
+ */
+
+class PercussionOnsetDetector : public Vamp::Plugin
+{
+public:
+    PercussionOnsetDetector(float inputSampleRate);
+    virtual ~PercussionOnsetDetector();
+
+    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;
+
+    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:
+    size_t m_stepSize;
+    size_t m_blockSize;
+
+    float  m_threshold;
+    float  m_sensitivity;
+    float *m_priorMagnitudes;
+    float  m_dfMinus1;
+    float  m_dfMinus2;
+};
+
+
+#endif
diff --git a/libs/vamp-sdk/examples/SpectralCentroid.cpp b/libs/vamp-sdk/examples/SpectralCentroid.cpp
new file mode 100644 (file)
index 0000000..82d80b8
--- /dev/null
@@ -0,0 +1,188 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "SpectralCentroid.h"
+
+using std::string;
+using std::vector;
+using std::cerr;
+using std::endl;
+
+#include <cmath>
+
+
+SpectralCentroid::SpectralCentroid(float inputSampleRate) :
+    Plugin(inputSampleRate),
+    m_stepSize(0),
+    m_blockSize(0)
+{
+}
+
+SpectralCentroid::~SpectralCentroid()
+{
+}
+
+string
+SpectralCentroid::getIdentifier() const
+{
+    return "spectralcentroid";
+}
+
+string
+SpectralCentroid::getName() const
+{
+    return "Spectral Centroid";
+}
+
+string
+SpectralCentroid::getDescription() const
+{
+    return "Calculate the centroid frequency of the spectrum of the input signal";
+}
+
+string
+SpectralCentroid::getMaker() const
+{
+    return "Vamp SDK Example Plugins";
+}
+
+int
+SpectralCentroid::getPluginVersion() const
+{
+    return 2;
+}
+
+string
+SpectralCentroid::getCopyright() const
+{
+    return "Freely redistributable (BSD license)";
+}
+
+bool
+SpectralCentroid::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    if (channels < getMinChannelCount() ||
+       channels > getMaxChannelCount()) return false;
+
+    m_stepSize = stepSize;
+    m_blockSize = blockSize;
+
+    return true;
+}
+
+void
+SpectralCentroid::reset()
+{
+}
+
+SpectralCentroid::OutputList
+SpectralCentroid::getOutputDescriptors() const
+{
+    OutputList list;
+
+    OutputDescriptor d;
+    d.identifier = "logcentroid";
+    d.name = "Log Frequency Centroid";
+    d.description = "Centroid of the log weighted frequency spectrum";
+    d.unit = "Hz";
+    d.hasFixedBinCount = true;
+    d.binCount = 1;
+    d.hasKnownExtents = false;
+    d.isQuantized = false;
+    d.sampleType = OutputDescriptor::OneSamplePerStep;
+    list.push_back(d);
+
+    d.identifier = "linearcentroid";
+    d.name = "Linear Frequency Centroid";
+    d.description = "Centroid of the linear frequency spectrum";
+    list.push_back(d);
+
+    return list;
+}
+
+SpectralCentroid::FeatureSet
+SpectralCentroid::process(const float *const *inputBuffers, Vamp::RealTime)
+{
+    if (m_stepSize == 0) {
+       cerr << "ERROR: SpectralCentroid::process: "
+            << "SpectralCentroid has not been initialised"
+            << endl;
+       return FeatureSet();
+    }
+
+    double numLin = 0.0, numLog = 0.0, denom = 0.0;
+
+    for (size_t i = 1; i <= m_blockSize/2; ++i) {
+       double freq = (double(i) * m_inputSampleRate) / m_blockSize;
+       double real = inputBuffers[0][i*2];
+       double imag = inputBuffers[0][i*2 + 1];
+       double power = sqrt(real * real + imag * imag) / (m_blockSize/2);
+       numLin += freq * power;
+        numLog += log10f(freq) * power;
+       denom += power;
+    }
+
+    FeatureSet returnFeatures;
+
+//    std::cerr << "power " << denom << ", block size " << m_blockSize << std::endl;
+
+    if (denom != 0.0) {
+       float centroidLin = float(numLin / denom);
+       float centroidLog = powf(10, float(numLog / denom));
+
+       Feature feature;
+       feature.hasTimestamp = false;
+        if (!std::isnan(centroidLog) && !std::isinf(centroidLog)) {
+            feature.values.push_back(centroidLog);
+        }
+       returnFeatures[0].push_back(feature);
+
+        feature.values.clear();
+        if (!std::isnan(centroidLin) && !std::isinf(centroidLin)) {
+            feature.values.push_back(centroidLin);
+        }
+       returnFeatures[1].push_back(feature);
+    }
+
+    return returnFeatures;
+}
+
+SpectralCentroid::FeatureSet
+SpectralCentroid::getRemainingFeatures()
+{
+    return FeatureSet();
+}
+
diff --git a/libs/vamp-sdk/examples/SpectralCentroid.h b/libs/vamp-sdk/examples/SpectralCentroid.h
new file mode 100644 (file)
index 0000000..02cc8d9
--- /dev/null
@@ -0,0 +1,78 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _SPECTRAL_CENTROID_PLUGIN_H_
+#define _SPECTRAL_CENTROID_PLUGIN_H_
+
+#include "vamp-sdk/Plugin.h"
+
+/**
+ * Example plugin that calculates the centre of gravity of the
+ * frequency domain representation of each block of audio.
+ */
+
+class SpectralCentroid : public Vamp::Plugin
+{
+public:
+    SpectralCentroid(float inputSampleRate);
+    virtual ~SpectralCentroid();
+
+    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;
+
+    OutputList getOutputDescriptors() const;
+
+    FeatureSet process(const float *const *inputBuffers,
+                       Vamp::RealTime timestamp);
+
+    FeatureSet getRemainingFeatures();
+
+protected:
+    size_t m_stepSize;
+    size_t m_blockSize;
+};
+
+
+#endif
diff --git a/libs/vamp-sdk/examples/ZeroCrossing.cpp b/libs/vamp-sdk/examples/ZeroCrossing.cpp
new file mode 100644 (file)
index 0000000..4b678e3
--- /dev/null
@@ -0,0 +1,194 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "ZeroCrossing.h"
+
+using std::string;
+using std::vector;
+using std::cerr;
+using std::endl;
+
+
+ZeroCrossing::ZeroCrossing(float inputSampleRate) :
+    Plugin(inputSampleRate),
+    m_stepSize(0),
+    m_previousSample(0.0f)
+{
+}
+
+ZeroCrossing::~ZeroCrossing()
+{
+}
+
+string
+ZeroCrossing::getIdentifier() const
+{
+    return "zerocrossing";
+}
+
+string
+ZeroCrossing::getName() const
+{
+    return "Zero Crossings";
+}
+
+string
+ZeroCrossing::getDescription() const
+{
+    return "Detect and count zero crossing points";
+}
+
+string
+ZeroCrossing::getMaker() const
+{
+    return "Vamp SDK Example Plugins";
+}
+
+int
+ZeroCrossing::getPluginVersion() const
+{
+    return 2;
+}
+
+string
+ZeroCrossing::getCopyright() const
+{
+    return "Freely redistributable (BSD license)";
+}
+
+bool
+ZeroCrossing::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    if (channels < getMinChannelCount() ||
+       channels > getMaxChannelCount()) return false;
+
+    m_stepSize = std::min(stepSize, blockSize);
+
+    return true;
+}
+
+void
+ZeroCrossing::reset()
+{
+    m_previousSample = 0.0f;
+}
+
+ZeroCrossing::OutputList
+ZeroCrossing::getOutputDescriptors() const
+{
+    OutputList list;
+
+    OutputDescriptor zc;
+    zc.identifier = "counts";
+    zc.name = "Zero Crossing Counts";
+    zc.description = "The number of zero crossing points per processing block";
+    zc.unit = "crossings";
+    zc.hasFixedBinCount = true;
+    zc.binCount = 1;
+    zc.hasKnownExtents = false;
+    zc.isQuantized = true;
+    zc.quantizeStep = 1.0;
+    zc.sampleType = OutputDescriptor::OneSamplePerStep;
+    list.push_back(zc);
+
+    zc.identifier = "zerocrossings";
+    zc.name = "Zero Crossings";
+    zc.description = "The locations of zero crossing points";
+    zc.unit = "";
+    zc.hasFixedBinCount = true;
+    zc.binCount = 0;
+    zc.sampleType = OutputDescriptor::VariableSampleRate;
+    zc.sampleRate = m_inputSampleRate;
+    list.push_back(zc);
+
+    return list;
+}
+
+ZeroCrossing::FeatureSet
+ZeroCrossing::process(const float *const *inputBuffers,
+                      Vamp::RealTime timestamp)
+{
+    if (m_stepSize == 0) {
+       cerr << "ERROR: ZeroCrossing::process: "
+            << "ZeroCrossing has not been initialised"
+            << endl;
+       return FeatureSet();
+    }
+
+    float prev = m_previousSample;
+    size_t count = 0;
+
+    FeatureSet returnFeatures;
+
+    for (size_t i = 0; i < m_stepSize; ++i) {
+
+       float sample = inputBuffers[0][i];
+       bool crossing = false;
+
+       if (sample <= 0.0) {
+           if (prev > 0.0) crossing = true;
+       } else if (sample > 0.0) {
+           if (prev <= 0.0) crossing = true;
+       }
+
+       if (crossing) {
+           ++count; 
+           Feature feature;
+           feature.hasTimestamp = true;
+           feature.timestamp = timestamp +
+               Vamp::RealTime::frame2RealTime(i, (size_t)m_inputSampleRate);
+           returnFeatures[1].push_back(feature);
+       }
+
+       prev = sample;
+    }
+
+    m_previousSample = prev;
+
+    Feature feature;
+    feature.hasTimestamp = false;
+    feature.values.push_back(count);
+
+    returnFeatures[0].push_back(feature);
+    return returnFeatures;
+}
+
+ZeroCrossing::FeatureSet
+ZeroCrossing::getRemainingFeatures()
+{
+    return FeatureSet();
+}
+
diff --git a/libs/vamp-sdk/examples/ZeroCrossing.h b/libs/vamp-sdk/examples/ZeroCrossing.h
new file mode 100644 (file)
index 0000000..ede2a74
--- /dev/null
@@ -0,0 +1,78 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _ZERO_CROSSING_PLUGIN_H_
+#define _ZERO_CROSSING_PLUGIN_H_
+
+#include "vamp-sdk/Plugin.h"
+
+/**
+ * Example plugin that calculates the positions and density of
+ * zero-crossing points in an audio waveform.
+*/
+
+class ZeroCrossing : public Vamp::Plugin
+{
+public:
+    ZeroCrossing(float inputSampleRate);
+    virtual ~ZeroCrossing();
+
+    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;
+
+    OutputList getOutputDescriptors() const;
+
+    FeatureSet process(const float *const *inputBuffers,
+                       Vamp::RealTime timestamp);
+
+    FeatureSet getRemainingFeatures();
+
+protected:
+    size_t m_stepSize;
+    float m_previousSample;
+};
+
+
+#endif
diff --git a/libs/vamp-sdk/examples/plugins.cpp b/libs/vamp-sdk/examples/plugins.cpp
new file mode 100644 (file)
index 0000000..25c6e6c
--- /dev/null
@@ -0,0 +1,63 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "vamp/vamp.h"
+#include "vamp-sdk/PluginAdapter.h"
+
+#include "ZeroCrossing.h"
+#include "SpectralCentroid.h"
+#include "PercussionOnsetDetector.h"
+#include "AmplitudeFollower.h"
+
+static Vamp::PluginAdapter<ZeroCrossing> zeroCrossingAdapter;
+static Vamp::PluginAdapter<SpectralCentroid> spectralCentroidAdapter;
+static Vamp::PluginAdapter<PercussionOnsetDetector> percussionOnsetAdapter;
+static Vamp::PluginAdapter<AmplitudeFollower> amplitudeAdapter;
+
+const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version,
+                                                    unsigned int index)
+{
+    if (version < 1) return 0;
+
+    switch (index) {
+    case  0: return zeroCrossingAdapter.getDescriptor();
+    case  1: return spectralCentroidAdapter.getDescriptor();
+    case  2: return percussionOnsetAdapter.getDescriptor();
+    case  3: return amplitudeAdapter.getDescriptor();
+    default: return 0;
+    }
+}
+
diff --git a/libs/vamp-sdk/examples/vamp-example-plugins.cat b/libs/vamp-sdk/examples/vamp-example-plugins.cat
new file mode 100644 (file)
index 0000000..7676c4a
--- /dev/null
@@ -0,0 +1,5 @@
+vamp:vamp-example-plugins:zerocrossing::Low Level Features
+vamp:vamp-example-plugins:spectralcentroid::Low Level Features
+vamp:vamp-example-plugins:percussiononsets::Time > Onsets
+vamp:vamp-example-plugins:amplitudefollower::Low Level Features
+
diff --git a/libs/vamp-sdk/host/system.h b/libs/vamp-sdk/host/system.h
new file mode 100644 (file)
index 0000000..15aa8c1
--- /dev/null
@@ -0,0 +1,75 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _SYSTEM_H_
+#define _SYSTEM_H_
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+#define DLOPEN(a,b)  LoadLibrary((a).c_str())
+#define DLSYM(a,b)   GetProcAddress((HINSTANCE)(a),(b))
+#define DLCLOSE(a)   FreeLibrary((HINSTANCE)(a))
+#define DLERROR()    ""
+
+#define PLUGIN_SUFFIX "dll"
+
+#else
+
+#include <dlfcn.h>
+
+#define DLOPEN(a,b)  dlopen((a).c_str(),(b))
+#define DLSYM(a,b)   dlsym((a),(b))
+#define DLCLOSE(a)   dlclose((a))
+#define DLERROR()    dlerror()
+
+#ifdef __APPLE__
+
+#define PLUGIN_SUFFIX  "dylib"
+#define HAVE_OPENDIR 1
+
+#else 
+
+#define PLUGIN_SUFFIX  "so"
+#define HAVE_OPENDIR 1
+
+#endif /* __APPLE__ */
+
+#endif /* ! _WIN32 */
+
+#endif
+
diff --git a/libs/vamp-sdk/host/vamp-simple-host.cpp b/libs/vamp-sdk/host/vamp-simple-host.cpp
new file mode 100644 (file)
index 0000000..c8ae28d
--- /dev/null
@@ -0,0 +1,492 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+    FFT code from Don Cross's public domain FFT implementation.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "vamp-sdk/PluginHostAdapter.h"
+#include "vamp-sdk/hostext/PluginChannelAdapter.h"
+#include "vamp-sdk/hostext/PluginInputDomainAdapter.h"
+#include "vamp-sdk/hostext/PluginLoader.h"
+#include "vamp/vamp.h"
+
+#include <iostream>
+#include <fstream>
+#include <sndfile.h>
+
+#include "system.h"
+
+#include <cmath>
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::string;
+using std::vector;
+using std::ofstream;
+using std::ios;
+
+using Vamp::HostExt::PluginLoader;
+
+#define HOST_VERSION "1.1"
+
+void printFeatures(int, int, int, Vamp::Plugin::FeatureSet, ofstream *);
+void transformInput(float *, size_t);
+void fft(unsigned int, bool, double *, double *, double *, double *);
+void printPluginPath(bool verbose);
+void enumeratePlugins();
+void listPluginsInLibrary(string soname);
+int runPlugin(string myname, string soname, string id, string output,
+              int outputNo, string inputFile, string outfilename);
+
+void usage(const char *name)
+{
+    cerr << "\n"
+         << name << ": A simple Vamp plugin host.\n\n"
+        "Centre for Digital Music, Queen Mary, University of London.\n"
+        "Copyright 2006-2007 Chris Cannam and QMUL.\n"
+        "Freely redistributable; published under a BSD-style license.\n\n"
+        "Usage:\n\n"
+        "  " << name << " pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin[:output] file.wav [-o outfile.txt]\n"
+        "  " << name << " pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin file.wav [outputno] [-o outfile.txt]\n\n"
+        "    -- Load plugin id \"plugin\" from \"pluginlibrary\" and run it on the\n"
+        "       audio data in \"file.wav\", retrieving the named \"output\", or output\n"
+        "       number \"outputno\" (the first output by default) and dumping it to\n"
+        "       standard output, or to \"outfile.txt\" if the -o option is given.\n\n"
+        "       \"pluginlibrary\" should be a library name, not a file path; the\n"
+        "       standard Vamp library search path will be used to locate it.  If\n"
+        "       a file path is supplied, the directory part(s) will be ignored.\n\n"
+        "  " << name << " -l\n\n"
+        "    -- List the plugin libraries and Vamp plugins in the library search path.\n\n"
+        "  " << name << " -p\n\n"
+        "    -- Print out the Vamp library search path.\n\n"
+        "  " << name << " -v\n\n"
+        "    -- Display version information only.\n\n"
+         << endl;
+    exit(2);
+}
+
+int main(int argc, char **argv)
+{
+    char *scooter = argv[0];
+    char *name = 0;
+    while (scooter && *scooter) {
+        if (*scooter == '/' || *scooter == '\\') name = ++scooter;
+        else ++scooter;
+    }
+    if (!name || !*name) name = argv[0];
+    
+    if (argc < 2) usage(name);
+
+    if (argc == 2) {
+
+        if (!strcmp(argv[1], "-v")) {
+
+            cout << "Simple Vamp plugin host version: " << HOST_VERSION << endl
+                 << "Vamp API version: " << VAMP_API_VERSION << endl
+                 << "Vamp SDK version: " << VAMP_SDK_VERSION << endl;
+            return 0;
+
+        } else if (!strcmp(argv[1], "-l")) {
+
+            printPluginPath(true);
+            enumeratePlugins();
+            return 0;
+
+        } else if (!strcmp(argv[1], "-p")) {
+
+            printPluginPath(false);
+            return 0;
+
+        } else usage(name);
+    }
+
+    if (argc < 3) usage(name);
+
+    string soname = argv[1];
+    string wavname = argv[2];
+    string plugid = "";
+    string output = "";
+    int outputNo = -1;
+    string outfilename;
+
+    if (argc >= 4) {
+
+        int idx = 3;
+
+        if (isdigit(*argv[idx])) {
+            outputNo = atoi(argv[idx++]);
+        }
+
+        if (argc == idx + 2) {
+            if (!strcmp(argv[idx], "-o")) {
+                outfilename = argv[idx+1];
+            } else usage(name);
+        } else if (argc != idx) {
+            (usage(name));
+        }
+    }
+
+    cerr << endl << name << ": Running..." << endl;
+
+    cerr << "Reading file: \"" << wavname << "\", writing to ";
+    if (outfilename == "") {
+        cerr << "standard output" << endl;
+    } else {
+        cerr << "\"" << outfilename << "\"" << endl;
+    }
+
+    string::size_type sep = soname.find(':');
+
+    if (sep != string::npos) {
+        plugid = soname.substr(sep + 1);
+        soname = soname.substr(0, sep);
+
+        sep = plugid.find(':');
+        if (sep != string::npos) {
+            output = plugid.substr(sep + 1);
+            plugid = plugid.substr(0, sep);
+        }
+    }
+
+    if (plugid == "") {
+        usage(name);
+    }
+
+    if (output != "" && outputNo != -1) {
+        usage(name);
+    }
+
+    if (output == "" && outputNo == -1) {
+        outputNo = 0;
+    }
+
+    return runPlugin(name, soname, plugid, output, outputNo,
+                     wavname, outfilename);
+}
+
+
+int runPlugin(string myname, string soname, string id,
+              string output, int outputNo, string wavname,
+              string outfilename)
+{
+    PluginLoader *loader = PluginLoader::getInstance();
+
+    PluginLoader::PluginKey key = loader->composePluginKey(soname, id);
+    
+    SNDFILE *sndfile;
+    SF_INFO sfinfo;
+    memset(&sfinfo, 0, sizeof(SF_INFO));
+
+    sndfile = sf_open(wavname.c_str(), SFM_READ, &sfinfo);
+    if (!sndfile) {
+       cerr << myname << ": ERROR: Failed to open input file \""
+             << wavname << "\": " << sf_strerror(sndfile) << endl;
+       return 1;
+    }
+
+    ofstream *out = 0;
+    if (outfilename != "") {
+        out = new ofstream(outfilename.c_str(), ios::out);
+        if (!*out) {
+            cerr << myname << ": ERROR: Failed to open output file \""
+                 << outfilename << "\" for writing" << endl;
+            delete out;
+            return 1;
+        }
+    }
+
+    Vamp::Plugin *plugin = loader->loadPlugin
+        (key, sfinfo.samplerate, PluginLoader::ADAPT_ALL);
+    if (!plugin) {
+        cerr << myname << ": ERROR: Failed to load plugin \"" << id
+             << "\" from library \"" << soname << "\"" << endl;
+        sf_close(sndfile);
+        if (out) {
+            out->close();
+            delete out;
+        }
+        return 1;
+    }
+
+    cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl;
+
+    int blockSize = plugin->getPreferredBlockSize();
+    int stepSize = plugin->getPreferredStepSize();
+
+    if (blockSize == 0) blockSize = 1024;
+    if (stepSize == 0) {
+        if (plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) {
+            stepSize = blockSize/2;
+        } else {
+            stepSize = blockSize;
+        }
+    }
+
+    int channels = sfinfo.channels;
+
+    float *filebuf = new float[blockSize * channels];
+    float **plugbuf = new float*[channels];
+    for (int c = 0; c < channels; ++c) plugbuf[c] = new float[blockSize + 2];
+
+    cerr << "Using block size = " << blockSize << ", step size = "
+              << stepSize << endl;
+
+    int minch = plugin->getMinChannelCount();
+    int maxch = plugin->getMaxChannelCount();
+    cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl;
+    cerr << "Sound file has " << channels << " (will mix/augment if necessary)" << endl;
+
+    Vamp::Plugin::OutputList outputs = plugin->getOutputDescriptors();
+    Vamp::Plugin::OutputDescriptor od;
+
+    int returnValue = 1;
+    int progress = 0;
+
+    if (outputs.empty()) {
+       cerr << "ERROR: Plugin has no outputs!" << endl;
+        goto done;
+    }
+
+    if (outputNo < 0) {
+
+        for (size_t oi = 0; oi < outputs.size(); ++oi) {
+            if (outputs[oi].identifier == output) {
+                outputNo = oi;
+                break;
+            }
+        }
+
+        if (outputNo < 0) {
+            cerr << "ERROR: Non-existent output \"" << output << "\" requested" << endl;
+            goto done;
+        }
+
+    } else {
+
+        if (int(outputs.size()) <= outputNo) {
+            cerr << "ERROR: Output " << outputNo << " requested, but plugin has only " << outputs.size() << " output(s)" << endl;
+            goto done;
+        }        
+    }
+
+    od = outputs[outputNo];
+    cerr << "Output is: \"" << od.identifier << "\"" << endl;
+
+    if (!plugin->initialise(channels, stepSize, blockSize)) {
+        cerr << "ERROR: Plugin initialise (channels = " << channels
+             << ", stepSize = " << stepSize << ", blockSize = "
+             << blockSize << ") failed." << endl;
+        goto done;
+    }
+
+    for (size_t i = 0; i < sfinfo.frames; i += stepSize) {
+
+        int count;
+
+        if (sf_seek(sndfile, i, SEEK_SET) < 0) {
+            cerr << "ERROR: sf_seek failed: " << sf_strerror(sndfile) << endl;
+            break;
+        }
+        
+        if ((count = sf_readf_float(sndfile, filebuf, blockSize)) < 0) {
+            cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl;
+            break;
+        }
+
+        for (int c = 0; c < channels; ++c) {
+            int j = 0;
+            while (j < count) {
+                plugbuf[c][j] = filebuf[j * sfinfo.channels + c];
+                ++j;
+            }
+            while (j < blockSize) {
+                plugbuf[c][j] = 0.0f;
+                ++j;
+            }
+        }
+
+        printFeatures
+            (i, sfinfo.samplerate, outputNo, plugin->process
+             (plugbuf, Vamp::RealTime::frame2RealTime(i, sfinfo.samplerate)),
+             out);
+
+        int pp = progress;
+        progress = lrintf((float(i) / sfinfo.frames) * 100.f);
+        if (progress != pp && out) {
+            cerr << "\r" << progress << "%";
+        }
+    }
+    if (out) cerr << "\rDone" << endl;
+
+    printFeatures(sfinfo.frames, sfinfo.samplerate, outputNo,
+                  plugin->getRemainingFeatures(), out);
+
+    returnValue = 0;
+
+done:
+    delete plugin;
+    if (out) {
+        out->close();
+        delete out;
+    }
+    sf_close(sndfile);
+    return returnValue;
+}
+
+void
+printPluginPath(bool verbose)
+{
+    if (verbose) {
+        cout << "\nVamp plugin search path: ";
+    }
+
+    vector<string> path = Vamp::PluginHostAdapter::getPluginPath();
+    for (size_t i = 0; i < path.size(); ++i) {
+        if (verbose) {
+            cout << "[" << path[i] << "]";
+        } else {
+            cout << path[i] << endl;
+        }
+    }
+
+    if (verbose) cout << endl;
+}
+
+void
+enumeratePlugins()
+{
+    PluginLoader *loader = PluginLoader::getInstance();
+
+    cout << "\nVamp plugin libraries found in search path:" << endl;
+
+    std::vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
+    typedef std::multimap<std::string, PluginLoader::PluginKey>
+        LibraryMap;
+    LibraryMap libraryMap;
+
+    for (size_t i = 0; i < plugins.size(); ++i) {
+        std::string path = loader->getLibraryPathForPlugin(plugins[i]);
+        libraryMap.insert(LibraryMap::value_type(path, plugins[i]));
+    }
+
+    std::string prevPath = "";
+    int index = 0;
+
+    for (LibraryMap::iterator i = libraryMap.begin();
+         i != libraryMap.end(); ++i) {
+        
+        std::string path = i->first;
+        PluginLoader::PluginKey key = i->second;
+
+        if (path != prevPath) {
+            prevPath = path;
+            index = 0;
+            cout << "\n  " << path << ":" << endl;
+        }
+
+        Vamp::Plugin *plugin = loader->loadPlugin(key, 48000);
+        if (plugin) {
+
+            char c = char('A' + index);
+            if (c > 'Z') c = char('a' + (index - 26));
+
+            cout << "    [" << c << "] [v"
+                 << plugin->getVampApiVersion() << "] "
+                 << plugin->getName() << ", \""
+                 << plugin->getIdentifier() << "\"" << " ["
+                 << plugin->getMaker() << "]" << endl;
+
+            PluginLoader::PluginCategoryHierarchy category =
+                loader->getPluginCategory(key);
+            if (!category.empty()) {
+                cout << "       ";
+                for (size_t ci = 0; ci < category.size(); ++ci) {
+                    cout << " > " << category[ci];
+                }
+                cout << endl;
+            }
+
+            if (plugin->getDescription() != "") {
+                cout << "        - " << plugin->getDescription() << endl;
+            }
+
+            Vamp::Plugin::OutputList outputs =
+                plugin->getOutputDescriptors();
+
+            if (outputs.size() > 1) {
+                for (size_t j = 0; j < outputs.size(); ++j) {
+                    cout << "         (" << j << ") "
+                         << outputs[j].name << ", \""
+                         << outputs[j].identifier << "\"" << endl;
+                    if (outputs[j].description != "") {
+                        cout << "             - " 
+                             << outputs[j].description << endl;
+                    }
+                }
+            }
+
+            ++index;
+
+            delete plugin;
+        }
+    }
+
+    cout << endl;
+}
+
+void
+printFeatures(int frame, int sr, int output,
+              Vamp::Plugin::FeatureSet features, ofstream *out)
+{
+    for (unsigned int i = 0; i < features[output].size(); ++i) {
+
+        Vamp::RealTime rt = Vamp::RealTime::frame2RealTime(frame, sr);
+
+        if (features[output][i].hasTimestamp) {
+            rt = features[output][i].timestamp;
+        }
+
+        (out ? *out : cout) << rt.toString() << ":";
+
+        for (unsigned int j = 0; j < features[output][i].values.size(); ++j) {
+            (out ? *out : cout) << " " << features[output][i].values[j];
+        }
+
+        (out ? *out : cout) << endl;
+    }
+}
+
+
+        
diff --git a/libs/vamp-sdk/vamp-sdk/Plugin.h b/libs/vamp-sdk/vamp-sdk/Plugin.h
new file mode 100644 (file)
index 0000000..159bf4f
--- /dev/null
@@ -0,0 +1,405 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_H_
+#define _VAMP_PLUGIN_H_
+
+#include "PluginBase.h"
+#include "RealTime.h"
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace Vamp {
+
+/**
+ * \class Plugin Plugin.h <vamp-sdk/Plugin.h>
+ * 
+ * Vamp::Plugin is a base class for plugin instance classes
+ * that provide feature extraction from audio or related data.
+ *
+ * In most cases, the input will be audio and the output will be a
+ * stream of derived data at a lower sampling resolution than the
+ * input.
+ *
+ * Note that this class inherits several abstract methods from
+ * PluginBase.  These must be implemented by the subclass.
+ * 
+ * 
+ * PLUGIN LIFECYCLE
+ *
+ * Feature extraction plugins are managed differently from real-time
+ * plugins (such as VST effects).  The main difference is that the
+ * parameters for a feature extraction plugin are configured before
+ * the plugin is used, and do not change during use.
+ *
+ * 1. Host constructs the plugin, passing it the input sample rate.
+ * The plugin may do basic initialisation, but should not do anything
+ * computationally expensive at this point.  You must make sure your
+ * plugin is cheap to construct, otherwise you'll seriously affect the
+ * startup performance of almost all hosts.  If you have serious
+ * initialisation to do, the proper place is in initialise() (step 5).
+ *
+ * 2. Host may query the plugin's available outputs.
+ *
+ * 3. Host queries programs and parameter descriptors, and may set
+ * some or all of them.  Parameters that are not explicitly set should
+ * take their default values as specified in the parameter descriptor.
+ * When a program is set, the parameter values may change and the host
+ * will re-query them to check.
+ *
+ * 4. Host queries the preferred step size, block size and number of
+ * channels.  These may all vary depending on the parameter values.
+ * (Note however that you cannot make the number of distinct outputs
+ * dependent on parameter values.)
+ *
+ * 5. Plugin is properly initialised with a call to initialise.  This
+ * fixes the step size, block size, and number of channels, as well as
+ * all of the parameter and program settings.  If the values passed in
+ * to initialise do not match the plugin's advertised preferred values
+ * from step 4, the plugin may refuse to initialise and return false
+ * (although if possible it should accept the new values).  Any
+ * computationally expensive setup code should take place here.
+ *
+ * 6. Host finally checks the number of values, resolution, extents
+ * etc per output (which may vary depending on the number of channels,
+ * step size and block size as well as the parameter values).
+ *
+ * 7. Host will repeatedly call the process method to pass in blocks
+ * of input data.  This method may return features extracted from that
+ * data (if the plugin is causal).
+ *
+ * 8. Host will call getRemainingFeatures exactly once, after all the
+ * input data has been processed.  This may return any non-causal or
+ * leftover features.
+ *
+ * 9. At any point after initialise was called, the host may
+ * optionally call the reset method and restart processing.  (This
+ * does not mean it can change the parameters, which are fixed from
+ * initialise until destruction.)
+ *
+ * A plugin does not need to handle the case where setParameter or
+ * selectProgram is called after initialise has been called.  It's the
+ * host's responsibility not to do that.  Similarly, the plugin may
+ * safely assume that initialise is called no more than once.
+ */
+
+class Plugin : public PluginBase
+{
+public:
+    virtual ~Plugin() { }
+
+    /**
+     * Initialise a plugin to prepare it for use with the given number
+     * of input channels, step size (window increment, in sample
+     * frames) and block size (window size, in sample frames).
+     *
+     * The input sample rate should have been already specified at
+     * construction time.
+     * 
+     * Return true for successful initialisation, false if the number
+     * of input channels, step size and/or block size cannot be
+     * supported.
+     */
+    virtual bool initialise(size_t inputChannels,
+                           size_t stepSize,
+                           size_t blockSize) = 0;
+
+    /**
+     * Reset the plugin after use, to prepare it for another clean
+     * run.  Not called for the first initialisation (i.e. initialise
+     * must also do a reset).
+     */
+    virtual void reset() = 0;
+
+    enum InputDomain { TimeDomain, FrequencyDomain };
+    
+    /**
+     * Get the plugin's required input domain.  If this is TimeDomain,
+     * the samples provided to the process() function (below) will be
+     * in the time domain, as for a traditional audio processing
+     * plugin.  If this is FrequencyDomain, the host will carry out a
+     * windowed FFT of size equal to the negotiated block size on the
+     * data before passing the frequency bin data in to process().
+     * The plugin does not get to choose the window type -- the host
+     * will either let the user do so, or will use a Hanning window.
+     */
+    virtual InputDomain getInputDomain() const = 0;
+
+    /**
+     * Get the preferred block size (window size -- the number of
+     * sample frames passed in each block to the process() function).
+     * This should be called before initialise().
+     *
+     * A plugin that can handle any block size may return 0.  The
+     * final block size will be set in the initialise() call.
+     */
+    virtual size_t getPreferredBlockSize() const { return 0; }
+
+    /**
+     * Get the preferred step size (window increment -- the distance
+     * in sample frames between the start frames of consecutive blocks
+     * passed to the process() function) for the plugin.  This should
+     * be called before initialise().
+     *
+     * A plugin may return 0 if it has no particular interest in the
+     * step size.  In this case, the host should make the step size
+     * equal to the block size if the plugin is accepting input in the
+     * time domain.  If the plugin is accepting input in the frequency
+     * domain, the host may use any step size.  The final step size
+     * will be set in the initialise() call.
+     */
+    virtual size_t getPreferredStepSize() const { return 0; }
+
+    /**
+     * Get the minimum supported number of input channels.
+     */
+    virtual size_t getMinChannelCount() const { return 1; }
+
+    /**
+     * Get the maximum supported number of input channels.
+     */
+    virtual size_t getMaxChannelCount() const { return 1; }
+
+    struct OutputDescriptor
+    {
+       /**
+        * The name of the output, in computer-usable form.  Should be
+        * reasonably short and without whitespace or punctuation, using
+         * the characters [a-zA-Z0-9_] only.
+         * Example: "zero_crossing_count"
+        */
+       std::string identifier;
+
+       /**
+        * The human-readable name of the output.
+         * Example: "Zero Crossing Counts"
+        */
+       std::string name;
+
+       /**
+        * A human-readable short text describing the output.  May be
+         * empty if the name has said it all already.
+         * Example: "The number of zero crossing points per processing block"
+        */
+       std::string description;
+
+       /**
+        * The unit of the output, in human-readable form.
+        */
+       std::string unit;
+
+       /**
+        * True if the output has the same number of values per sample
+        * for every output sample.  Outputs for which this is false
+        * are unlikely to be very useful in a general-purpose host.
+        */
+       bool hasFixedBinCount;
+
+       /**
+        * The number of values per result of the output.  Undefined
+        * if hasFixedBinCount is false.  If this is zero, the output
+        * is point data (i.e. only the time of each output is of
+        * interest, the value list will be empty).
+        */
+       size_t binCount;
+
+       /**
+        * The (human-readable) names of each of the bins, if
+        * appropriate.  This is always optional.
+        */
+       std::vector<std::string> binNames;
+
+       /**
+        * True if the results in each output bin fall within a fixed
+        * numeric range (minimum and maximum values).  Undefined if
+        * binCount is zero.
+        */
+       bool hasKnownExtents;
+
+       /**
+        * Minimum value of the results in the output.  Undefined if
+        * hasKnownExtents is false or binCount is zero.
+        */
+       float minValue;
+
+       /**
+        * Maximum value of the results in the output.  Undefined if
+        * hasKnownExtents is false or binCount is zero.
+        */
+       float maxValue;
+
+       /**
+        * True if the output values are quantized to a particular
+        * resolution.  Undefined if binCount is zero.
+        */
+       bool isQuantized;
+
+       /**
+        * Quantization resolution of the output values (e.g. 1.0 if
+        * they are all integers).  Undefined if isQuantized is false
+        * or binCount is zero.
+        */
+       float quantizeStep;
+
+       enum SampleType {
+
+           /// Results from each process() align with that call's block start
+           OneSamplePerStep,
+
+           /// Results are evenly spaced in time (sampleRate specified below)
+           FixedSampleRate,
+
+           /// Results are unevenly spaced and have individual timestamps
+           VariableSampleRate
+       };
+
+       /**
+        * Positioning in time of the output results.
+        */
+       SampleType sampleType;
+
+       /**
+        * Sample rate of the output results, as samples per second.
+        * Undefined if sampleType is OneSamplePerStep.
+        *
+        * If sampleType is VariableSampleRate and this value is
+        * non-zero, then it may be used to calculate a resolution for
+        * the output (i.e. the "duration" of each sample, in time,
+        * will be 1/sampleRate seconds).  It's recommended to set
+        * this to zero if that behaviour is not desired.
+        */
+       float sampleRate;
+    };
+
+    typedef std::vector<OutputDescriptor> OutputList;
+
+    /**
+     * Get the outputs of this plugin.  An output's index in this list
+     * is used as its numeric index when looking it up in the
+     * FeatureSet returned from the process() call.
+     */
+    virtual OutputList getOutputDescriptors() const = 0;
+
+    struct Feature
+    {
+       /**
+        * True if an output feature has its own timestamp.  This is
+        * mandatory if the output has VariableSampleRate, and is
+        * likely to be disregarded otherwise.
+        */
+       bool hasTimestamp;
+
+       /**
+        * Timestamp of the output feature.  This is mandatory if the
+        * output has VariableSampleRate, and is likely to be
+        * disregarded otherwise.  Undefined if hasTimestamp is false.
+        */
+       RealTime timestamp;
+       
+       /**
+        * Results for a single sample of this feature.  If the output
+        * hasFixedBinCount, there must be the same number of values
+        * as the output's binCount count.
+        */
+       std::vector<float> values;
+
+       /**
+        * Label for the sample of this feature.
+        */
+       std::string label;
+    };
+
+    typedef std::vector<Feature> FeatureList;
+    typedef std::map<int, FeatureList> FeatureSet; // key is output no
+
+    /**
+     * Process a single block of input data.
+     * 
+     * If the plugin's inputDomain is TimeDomain, inputBuffers will
+     * point to one array of floats per input channel, and each of
+     * these arrays will contain blockSize consecutive audio samples
+     * (the host will zero-pad as necessary).  The timestamp will be
+     * the real time in seconds of the start of the supplied block of
+     * samples.
+     *
+     * If the plugin's inputDomain is FrequencyDomain, inputBuffers
+     * will point to one array of floats per input channel, and each
+     * of these arrays will contain blockSize/2+1 consecutive pairs of
+     * real and imaginary component floats corresponding to bins
+     * 0..(blockSize/2) of the FFT output.  That is, bin 0 (the first
+     * pair of floats) contains the DC output, up to bin blockSize/2
+     * which contains the Nyquist-frequency output.  There will
+     * therefore be blockSize+2 floats per channel in total.  The
+     * timestamp will be the real time in seconds of the centre of the
+     * FFT input window (i.e. the very first block passed to process
+     * might contain the FFT of half a block of zero samples and the
+     * first half-block of the actual data, with a timestamp of zero).
+     *
+     * Return any features that have become available after this
+     * process call.  (These do not necessarily have to fall within
+     * the process block, except for OneSamplePerStep outputs.)
+     */
+    virtual FeatureSet process(const float *const *inputBuffers,
+                              RealTime timestamp) = 0;
+
+    /**
+     * After all blocks have been processed, calculate and return any
+     * remaining features derived from the complete input.
+     */
+    virtual FeatureSet getRemainingFeatures() = 0;
+
+    /**
+     * Used to distinguish between Vamp::Plugin and other potential
+     * sibling subclasses of PluginBase.  Do not reimplement this
+     * function in your subclass.
+     */
+    virtual std::string getType() const { return "Feature Extraction Plugin"; }
+
+protected:
+    Plugin(float inputSampleRate) :
+       m_inputSampleRate(inputSampleRate) { }
+
+    float m_inputSampleRate;
+};
+
+}
+
+#endif
+
+
+
diff --git a/libs/vamp-sdk/vamp-sdk/PluginAdapter.cpp b/libs/vamp-sdk/vamp-sdk/PluginAdapter.cpp
new file mode 100644 (file)
index 0000000..1549b4f
--- /dev/null
@@ -0,0 +1,851 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "PluginAdapter.h"
+
+//#define DEBUG_PLUGIN_ADAPTER 1
+
+
+namespace Vamp {
+
+class PluginAdapterBase::Impl
+{
+public:
+    Impl(PluginAdapterBase *);
+    ~Impl();
+
+    const VampPluginDescriptor *getDescriptor();
+
+protected:
+    PluginAdapterBase *m_base;
+
+    static VampPluginHandle vampInstantiate(const VampPluginDescriptor *desc,
+                                          float inputSampleRate);
+
+    static void vampCleanup(VampPluginHandle handle);
+
+    static int vampInitialise(VampPluginHandle handle, unsigned int channels,
+                             unsigned int stepSize, unsigned int blockSize);
+
+    static void vampReset(VampPluginHandle handle);
+
+    static float vampGetParameter(VampPluginHandle handle, int param);
+    static void vampSetParameter(VampPluginHandle handle, int param, float value);
+
+    static unsigned int vampGetCurrentProgram(VampPluginHandle handle);
+    static void vampSelectProgram(VampPluginHandle handle, unsigned int program);
+
+    static unsigned int vampGetPreferredStepSize(VampPluginHandle handle);
+    static unsigned int vampGetPreferredBlockSize(VampPluginHandle handle);
+    static unsigned int vampGetMinChannelCount(VampPluginHandle handle);
+    static unsigned int vampGetMaxChannelCount(VampPluginHandle handle);
+
+    static unsigned int vampGetOutputCount(VampPluginHandle handle);
+
+    static VampOutputDescriptor *vampGetOutputDescriptor(VampPluginHandle handle,
+                                                       unsigned int i);
+
+    static void vampReleaseOutputDescriptor(VampOutputDescriptor *desc);
+
+    static VampFeatureList *vampProcess(VampPluginHandle handle,
+                                        const float *const *inputBuffers,
+                                        int sec,
+                                        int nsec);
+
+    static VampFeatureList *vampGetRemainingFeatures(VampPluginHandle handle);
+
+    static void vampReleaseFeatureSet(VampFeatureList *fs);
+
+    void cleanup(Plugin *plugin);
+    void checkOutputMap(Plugin *plugin);
+    unsigned int getOutputCount(Plugin *plugin);
+    VampOutputDescriptor *getOutputDescriptor(Plugin *plugin,
+                                             unsigned int i);
+    VampFeatureList *process(Plugin *plugin,
+                             const float *const *inputBuffers,
+                             int sec, int nsec);
+    VampFeatureList *getRemainingFeatures(Plugin *plugin);
+    VampFeatureList *convertFeatures(Plugin *plugin,
+                                     const Plugin::FeatureSet &features);
+    
+    // maps both plugins and descriptors to adapters
+    typedef std::map<const void *, Impl *> AdapterMap;
+    static AdapterMap *m_adapterMap;
+    static Impl *lookupAdapter(VampPluginHandle);
+
+    bool m_populated;
+    VampPluginDescriptor m_descriptor;
+    Plugin::ParameterList m_parameters;
+    Plugin::ProgramList m_programs;
+    
+    typedef std::map<Plugin *, Plugin::OutputList *> OutputMap;
+    OutputMap m_pluginOutputs;
+
+    std::map<Plugin *, VampFeatureList *> m_fs;
+    std::map<Plugin *, std::vector<size_t> > m_fsizes;
+    std::map<Plugin *, std::vector<std::vector<size_t> > > m_fvsizes;
+    void resizeFS(Plugin *plugin, int n);
+    void resizeFL(Plugin *plugin, int n, size_t sz);
+    void resizeFV(Plugin *plugin, int n, int j, size_t sz);
+};
+
+PluginAdapterBase::PluginAdapterBase()
+{
+    m_impl = new Impl(this);
+}
+
+PluginAdapterBase::~PluginAdapterBase()
+{
+    delete m_impl;
+}
+
+const VampPluginDescriptor *
+PluginAdapterBase::getDescriptor()
+{
+    return m_impl->getDescriptor();
+}
+
+PluginAdapterBase::Impl::Impl(PluginAdapterBase *base) :
+    m_base(base),
+    m_populated(false)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl[" << this << "]::Impl" << std::endl;
+#endif
+}
+
+const VampPluginDescriptor *
+PluginAdapterBase::Impl::getDescriptor()
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl[" << this << "]::getDescriptor" << std::endl;
+#endif
+
+    if (m_populated) return &m_descriptor;
+
+    Plugin *plugin = m_base->createPlugin(48000);
+
+    if (plugin->getVampApiVersion() != VAMP_API_VERSION) {
+        std::cerr << "Vamp::PluginAdapterBase::Impl::getDescriptor: ERROR: "
+                  << "Plugin object API version "
+                  << plugin->getVampApiVersion()
+                  << " does not match actual API version "
+                  << VAMP_API_VERSION << std::endl;
+        delete plugin;
+        return 0;
+    }
+
+    m_parameters = plugin->getParameterDescriptors();
+    m_programs = plugin->getPrograms();
+
+    m_descriptor.vampApiVersion = plugin->getVampApiVersion();
+    m_descriptor.identifier = strdup(plugin->getIdentifier().c_str());
+    m_descriptor.name = strdup(plugin->getName().c_str());
+    m_descriptor.description = strdup(plugin->getDescription().c_str());
+    m_descriptor.maker = strdup(plugin->getMaker().c_str());
+    m_descriptor.pluginVersion = plugin->getPluginVersion();
+    m_descriptor.copyright = strdup(plugin->getCopyright().c_str());
+    
+    m_descriptor.parameterCount = m_parameters.size();
+    m_descriptor.parameters = (const VampParameterDescriptor **)
+        malloc(m_parameters.size() * sizeof(VampParameterDescriptor));
+
+    unsigned int i;
+    
+    for (i = 0; i < m_parameters.size(); ++i) {
+        VampParameterDescriptor *desc = (VampParameterDescriptor *)
+            malloc(sizeof(VampParameterDescriptor));
+        desc->identifier = strdup(m_parameters[i].identifier.c_str());
+        desc->name = strdup(m_parameters[i].name.c_str());
+        desc->description = strdup(m_parameters[i].description.c_str());
+        desc->unit = strdup(m_parameters[i].unit.c_str());
+        desc->minValue = m_parameters[i].minValue;
+        desc->maxValue = m_parameters[i].maxValue;
+        desc->defaultValue = m_parameters[i].defaultValue;
+        desc->isQuantized = m_parameters[i].isQuantized;
+        desc->quantizeStep = m_parameters[i].quantizeStep;
+        desc->valueNames = 0;
+        if (desc->isQuantized && !m_parameters[i].valueNames.empty()) {
+            desc->valueNames = (const char **)
+                malloc((m_parameters[i].valueNames.size()+1) * sizeof(char *));
+            for (unsigned int j = 0; j < m_parameters[i].valueNames.size(); ++j) {
+                desc->valueNames[j] = strdup(m_parameters[i].valueNames[j].c_str());
+            }
+            desc->valueNames[m_parameters[i].valueNames.size()] = 0;
+        }
+        m_descriptor.parameters[i] = desc;
+    }
+    
+    m_descriptor.programCount = m_programs.size();
+    m_descriptor.programs = (const char **)
+        malloc(m_programs.size() * sizeof(const char *));
+    
+    for (i = 0; i < m_programs.size(); ++i) {
+        m_descriptor.programs[i] = strdup(m_programs[i].c_str());
+    }
+    
+    if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
+        m_descriptor.inputDomain = vampFrequencyDomain;
+    } else {
+        m_descriptor.inputDomain = vampTimeDomain;
+    }
+
+    m_descriptor.instantiate = vampInstantiate;
+    m_descriptor.cleanup = vampCleanup;
+    m_descriptor.initialise = vampInitialise;
+    m_descriptor.reset = vampReset;
+    m_descriptor.getParameter = vampGetParameter;
+    m_descriptor.setParameter = vampSetParameter;
+    m_descriptor.getCurrentProgram = vampGetCurrentProgram;
+    m_descriptor.selectProgram = vampSelectProgram;
+    m_descriptor.getPreferredStepSize = vampGetPreferredStepSize;
+    m_descriptor.getPreferredBlockSize = vampGetPreferredBlockSize;
+    m_descriptor.getMinChannelCount = vampGetMinChannelCount;
+    m_descriptor.getMaxChannelCount = vampGetMaxChannelCount;
+    m_descriptor.getOutputCount = vampGetOutputCount;
+    m_descriptor.getOutputDescriptor = vampGetOutputDescriptor;
+    m_descriptor.releaseOutputDescriptor = vampReleaseOutputDescriptor;
+    m_descriptor.process = vampProcess;
+    m_descriptor.getRemainingFeatures = vampGetRemainingFeatures;
+    m_descriptor.releaseFeatureSet = vampReleaseFeatureSet;
+    
+    if (!m_adapterMap) {
+        m_adapterMap = new AdapterMap;
+    }
+    (*m_adapterMap)[&m_descriptor] = this;
+
+    delete plugin;
+
+    m_populated = true;
+    return &m_descriptor;
+}
+
+PluginAdapterBase::Impl::~Impl()
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl[" << this << "]::~Impl" << std::endl;
+#endif
+
+    if (!m_populated) return;
+
+    free((void *)m_descriptor.identifier);
+    free((void *)m_descriptor.name);
+    free((void *)m_descriptor.description);
+    free((void *)m_descriptor.maker);
+    free((void *)m_descriptor.copyright);
+        
+    for (unsigned int i = 0; i < m_descriptor.parameterCount; ++i) {
+        const VampParameterDescriptor *desc = m_descriptor.parameters[i];
+        free((void *)desc->identifier);
+        free((void *)desc->name);
+        free((void *)desc->description);
+        free((void *)desc->unit);
+        if (desc->valueNames) {
+            for (unsigned int j = 0; desc->valueNames[j]; ++j) {
+                free((void *)desc->valueNames[j]);
+            }
+            free((void *)desc->valueNames);
+        }
+    }
+    free((void *)m_descriptor.parameters);
+
+    for (unsigned int i = 0; i < m_descriptor.programCount; ++i) {
+        free((void *)m_descriptor.programs[i]);
+    }
+    free((void *)m_descriptor.programs);
+
+    if (m_adapterMap) {
+        
+        m_adapterMap->erase(&m_descriptor);
+
+        if (m_adapterMap->empty()) {
+            delete m_adapterMap;
+            m_adapterMap = 0;
+        }
+    }
+}
+
+PluginAdapterBase::Impl *
+PluginAdapterBase::Impl::lookupAdapter(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::lookupAdapter(" << handle << ")" << std::endl;
+#endif
+
+    if (!m_adapterMap) return 0;
+    AdapterMap::const_iterator i = m_adapterMap->find(handle);
+    if (i == m_adapterMap->end()) return 0;
+    return i->second;
+}
+
+VampPluginHandle
+PluginAdapterBase::Impl::vampInstantiate(const VampPluginDescriptor *desc,
+                                   float inputSampleRate)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << ")" << std::endl;
+#endif
+
+    if (!m_adapterMap) {
+        m_adapterMap = new AdapterMap();
+    }
+
+    if (m_adapterMap->find(desc) == m_adapterMap->end()) {
+        std::cerr << "WARNING: PluginAdapterBase::Impl::vampInstantiate: Descriptor " << desc << " not in adapter map" << std::endl;
+        return 0;
+    }
+
+    Impl *adapter = (*m_adapterMap)[desc];
+    if (desc != &adapter->m_descriptor) return 0;
+
+    Plugin *plugin = adapter->m_base->createPlugin(inputSampleRate);
+    if (plugin) {
+        (*m_adapterMap)[plugin] = adapter;
+    }
+
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << "): returning handle " << plugin << std::endl;
+#endif
+
+    return plugin;
+}
+
+void
+PluginAdapterBase::Impl::vampCleanup(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampCleanup(" << handle << ")" << std::endl;
+#endif
+
+    Impl *adapter = lookupAdapter(handle);
+    if (!adapter) {
+        delete ((Plugin *)handle);
+        return;
+    }
+    adapter->cleanup(((Plugin *)handle));
+}
+
+int
+PluginAdapterBase::Impl::vampInitialise(VampPluginHandle handle,
+                                  unsigned int channels,
+                                  unsigned int stepSize,
+                                  unsigned int blockSize)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampInitialise(" << handle << ", " << channels << ", " << stepSize << ", " << blockSize << ")" << std::endl;
+#endif
+
+    bool result = ((Plugin *)handle)->initialise
+        (channels, stepSize, blockSize);
+    return result ? 1 : 0;
+}
+
+void
+PluginAdapterBase::Impl::vampReset(VampPluginHandle handle) 
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampReset(" << handle << ")" << std::endl;
+#endif
+
+    ((Plugin *)handle)->reset();
+}
+
+float
+PluginAdapterBase::Impl::vampGetParameter(VampPluginHandle handle,
+                                    int param) 
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampGetParameter(" << handle << ", " << param << ")" << std::endl;
+#endif
+
+    Impl *adapter = lookupAdapter(handle);
+    if (!adapter) return 0.0;
+    Plugin::ParameterList &list = adapter->m_parameters;
+    return ((Plugin *)handle)->getParameter(list[param].identifier);
+}
+
+void
+PluginAdapterBase::Impl::vampSetParameter(VampPluginHandle handle,
+                                    int param, float value)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampSetParameter(" << handle << ", " << param << ", " << value << ")" << std::endl;
+#endif
+
+    Impl *adapter = lookupAdapter(handle);
+    if (!adapter) return;
+    Plugin::ParameterList &list = adapter->m_parameters;
+    ((Plugin *)handle)->setParameter(list[param].identifier, value);
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetCurrentProgram(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampGetCurrentProgram(" << handle << ")" << std::endl;
+#endif
+
+    Impl *adapter = lookupAdapter(handle);
+    if (!adapter) return 0;
+    Plugin::ProgramList &list = adapter->m_programs;
+    std::string program = ((Plugin *)handle)->getCurrentProgram();
+    for (unsigned int i = 0; i < list.size(); ++i) {
+        if (list[i] == program) return i;
+    }
+    return 0;
+}
+
+void
+PluginAdapterBase::Impl::vampSelectProgram(VampPluginHandle handle,
+                                     unsigned int program)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampSelectProgram(" << handle << ", " << program << ")" << std::endl;
+#endif
+
+    Impl *adapter = lookupAdapter(handle);
+    if (!adapter) return;
+    Plugin::ProgramList &list = adapter->m_programs;
+    ((Plugin *)handle)->selectProgram(list[program]);
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetPreferredStepSize(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampGetPreferredStepSize(" << handle << ")" << std::endl;
+#endif
+
+    return ((Plugin *)handle)->getPreferredStepSize();
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetPreferredBlockSize(VampPluginHandle handle) 
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampGetPreferredBlockSize(" << handle << ")" << std::endl;
+#endif
+
+    return ((Plugin *)handle)->getPreferredBlockSize();
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetMinChannelCount(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampGetMinChannelCount(" << handle << ")" << std::endl;
+#endif
+
+    return ((Plugin *)handle)->getMinChannelCount();
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetMaxChannelCount(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampGetMaxChannelCount(" << handle << ")" << std::endl;
+#endif
+
+    return ((Plugin *)handle)->getMaxChannelCount();
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetOutputCount(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampGetOutputCount(" << handle << ")" << std::endl;
+#endif
+
+    Impl *adapter = lookupAdapter(handle);
+
+//    std::cerr << "vampGetOutputCount: handle " << handle << " -> adapter "<< adapter << std::endl;
+
+    if (!adapter) return 0;
+    return adapter->getOutputCount((Plugin *)handle);
+}
+
+VampOutputDescriptor *
+PluginAdapterBase::Impl::vampGetOutputDescriptor(VampPluginHandle handle,
+                                           unsigned int i)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampGetOutputDescriptor(" << handle << ", " << i << ")" << std::endl;
+#endif
+
+    Impl *adapter = lookupAdapter(handle);
+
+//    std::cerr << "vampGetOutputDescriptor: handle " << handle << " -> adapter "<< adapter << std::endl;
+
+    if (!adapter) return 0;
+    return adapter->getOutputDescriptor((Plugin *)handle, i);
+}
+
+void
+PluginAdapterBase::Impl::vampReleaseOutputDescriptor(VampOutputDescriptor *desc)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampReleaseOutputDescriptor(" << desc << ")" << std::endl;
+#endif
+
+    if (desc->identifier) free((void *)desc->identifier);
+    if (desc->name) free((void *)desc->name);
+    if (desc->description) free((void *)desc->description);
+    if (desc->unit) free((void *)desc->unit);
+    if (desc->hasFixedBinCount && desc->binNames) {
+        for (unsigned int i = 0; i < desc->binCount; ++i) {
+            if (desc->binNames[i]) {
+                free((void *)desc->binNames[i]);
+            }
+        }
+    }
+    if (desc->binNames) free((void *)desc->binNames);
+    free((void *)desc);
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::vampProcess(VampPluginHandle handle,
+                               const float *const *inputBuffers,
+                               int sec,
+                               int nsec)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampProcess(" << handle << ", " << sec << ", " << nsec << ")" << std::endl;
+#endif
+
+    Impl *adapter = lookupAdapter(handle);
+    if (!adapter) return 0;
+    return adapter->process((Plugin *)handle,
+                            inputBuffers, sec, nsec);
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::vampGetRemainingFeatures(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampGetRemainingFeatures(" << handle << ")" << std::endl;
+#endif
+
+    Impl *adapter = lookupAdapter(handle);
+    if (!adapter) return 0;
+    return adapter->getRemainingFeatures((Plugin *)handle);
+}
+
+void
+PluginAdapterBase::Impl::vampReleaseFeatureSet(VampFeatureList *fs)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+    std::cerr << "PluginAdapterBase::Impl::vampReleaseFeatureSet" << std::endl;
+#endif
+}
+
+void 
+PluginAdapterBase::Impl::cleanup(Plugin *plugin)
+{
+    if (m_fs.find(plugin) != m_fs.end()) {
+        size_t outputCount = 0;
+        if (m_pluginOutputs[plugin]) {
+            outputCount = m_pluginOutputs[plugin]->size();
+        }
+        VampFeatureList *list = m_fs[plugin];
+        for (unsigned int i = 0; i < outputCount; ++i) {
+            for (unsigned int j = 0; j < m_fsizes[plugin][i]; ++j) {
+                if (list[i].features[j].label) {
+                    free(list[i].features[j].label);
+                }
+                if (list[i].features[j].values) {
+                    free(list[i].features[j].values);
+                }
+            }
+            if (list[i].features) free(list[i].features);
+        }
+        m_fs.erase(plugin);
+        m_fsizes.erase(plugin);
+        m_fvsizes.erase(plugin);
+    }
+
+    if (m_pluginOutputs.find(plugin) != m_pluginOutputs.end()) {
+        delete m_pluginOutputs[plugin];
+        m_pluginOutputs.erase(plugin);
+    }
+
+    if (m_adapterMap) {
+        m_adapterMap->erase(plugin);
+
+        if (m_adapterMap->empty()) {
+            delete m_adapterMap;
+            m_adapterMap = 0;
+        }
+    }
+
+    delete ((Plugin *)plugin);
+}
+
+void 
+PluginAdapterBase::Impl::checkOutputMap(Plugin *plugin)
+{
+    if (m_pluginOutputs.find(plugin) == m_pluginOutputs.end() ||
+        !m_pluginOutputs[plugin]) {
+        m_pluginOutputs[plugin] = new Plugin::OutputList
+            (plugin->getOutputDescriptors());
+//        std::cerr << "PluginAdapterBase::Impl::checkOutputMap: Have " << m_pluginOutputs[plugin]->size() << " outputs for plugin " << plugin->getIdentifier() << std::endl;
+    }
+}
+
+unsigned int 
+PluginAdapterBase::Impl::getOutputCount(Plugin *plugin)
+{
+    checkOutputMap(plugin);
+    return m_pluginOutputs[plugin]->size();
+}
+
+VampOutputDescriptor *
+PluginAdapterBase::Impl::getOutputDescriptor(Plugin *plugin,
+                                       unsigned int i)
+{
+    checkOutputMap(plugin);
+    Plugin::OutputDescriptor &od =
+        (*m_pluginOutputs[plugin])[i];
+
+    VampOutputDescriptor *desc = (VampOutputDescriptor *)
+        malloc(sizeof(VampOutputDescriptor));
+
+    desc->identifier = strdup(od.identifier.c_str());
+    desc->name = strdup(od.name.c_str());
+    desc->description = strdup(od.description.c_str());
+    desc->unit = strdup(od.unit.c_str());
+    desc->hasFixedBinCount = od.hasFixedBinCount;
+    desc->binCount = od.binCount;
+
+    if (od.hasFixedBinCount && od.binCount > 0) {
+        desc->binNames = (const char **)
+            malloc(od.binCount * sizeof(const char *));
+        
+        for (unsigned int i = 0; i < od.binCount; ++i) {
+            if (i < od.binNames.size()) {
+                desc->binNames[i] = strdup(od.binNames[i].c_str());
+            } else {
+                desc->binNames[i] = 0;
+            }
+        }
+    } else {
+        desc->binNames = 0;
+    }
+
+    desc->hasKnownExtents = od.hasKnownExtents;
+    desc->minValue = od.minValue;
+    desc->maxValue = od.maxValue;
+    desc->isQuantized = od.isQuantized;
+    desc->quantizeStep = od.quantizeStep;
+
+    switch (od.sampleType) {
+    case Plugin::OutputDescriptor::OneSamplePerStep:
+        desc->sampleType = vampOneSamplePerStep; break;
+    case Plugin::OutputDescriptor::FixedSampleRate:
+        desc->sampleType = vampFixedSampleRate; break;
+    case Plugin::OutputDescriptor::VariableSampleRate:
+        desc->sampleType = vampVariableSampleRate; break;
+    }
+
+    desc->sampleRate = od.sampleRate;
+
+    return desc;
+}
+    
+VampFeatureList *
+PluginAdapterBase::Impl::process(Plugin *plugin,
+                           const float *const *inputBuffers,
+                           int sec, int nsec)
+{
+//    std::cerr << "PluginAdapterBase::Impl::process" << std::endl;
+    RealTime rt(sec, nsec);
+    checkOutputMap(plugin);
+    return convertFeatures(plugin, plugin->process(inputBuffers, rt));
+}
+    
+VampFeatureList *
+PluginAdapterBase::Impl::getRemainingFeatures(Plugin *plugin)
+{
+//    std::cerr << "PluginAdapterBase::Impl::getRemainingFeatures" << std::endl;
+    checkOutputMap(plugin);
+    return convertFeatures(plugin, plugin->getRemainingFeatures());
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::convertFeatures(Plugin *plugin,
+                                   const Plugin::FeatureSet &features)
+{
+    int lastN = -1;
+
+    int outputCount = 0;
+    if (m_pluginOutputs[plugin]) outputCount = m_pluginOutputs[plugin]->size();
+    
+    resizeFS(plugin, outputCount);
+    VampFeatureList *fs = m_fs[plugin];
+
+    for (Plugin::FeatureSet::const_iterator fi = features.begin();
+         fi != features.end(); ++fi) {
+
+        int n = fi->first;
+        
+//        std::cerr << "PluginAdapterBase::Impl::convertFeatures: n = " << n << std::endl;
+
+        if (n >= int(outputCount)) {
+            std::cerr << "WARNING: PluginAdapterBase::Impl::convertFeatures: Too many outputs from plugin (" << n+1 << ", only should be " << outputCount << ")" << std::endl;
+            continue;
+        }
+
+        if (n > lastN + 1) {
+            for (int i = lastN + 1; i < n; ++i) {
+                fs[i].featureCount = 0;
+            }
+        }
+
+        const Plugin::FeatureList &fl = fi->second;
+
+        size_t sz = fl.size();
+        if (sz > m_fsizes[plugin][n]) resizeFL(plugin, n, sz);
+        fs[n].featureCount = sz;
+        
+        for (size_t j = 0; j < sz; ++j) {
+
+//            std::cerr << "PluginAdapterBase::Impl::convertFeatures: j = " << j << std::endl;
+
+            VampFeature *feature = &fs[n].features[j];
+
+            feature->hasTimestamp = fl[j].hasTimestamp;
+            feature->sec = fl[j].timestamp.sec;
+            feature->nsec = fl[j].timestamp.nsec;
+            feature->valueCount = fl[j].values.size();
+
+            if (feature->label) free(feature->label);
+
+            if (fl[j].label.empty()) {
+                feature->label = 0;
+            } else {
+                feature->label = strdup(fl[j].label.c_str());
+            }
+
+            if (feature->valueCount > m_fvsizes[plugin][n][j]) {
+                resizeFV(plugin, n, j, feature->valueCount);
+            }
+
+            for (unsigned int k = 0; k < feature->valueCount; ++k) {
+//                std::cerr << "PluginAdapterBase::Impl::convertFeatures: k = " << k << std::endl;
+                feature->values[k] = fl[j].values[k];
+            }
+        }
+
+        lastN = n;
+    }
+
+    if (lastN == -1) return 0;
+
+    if (int(outputCount) > lastN + 1) {
+        for (int i = lastN + 1; i < int(outputCount); ++i) {
+            fs[i].featureCount = 0;
+        }
+    }
+
+    return fs;
+}
+
+void
+PluginAdapterBase::Impl::resizeFS(Plugin *plugin, int n)
+{
+//    std::cerr << "PluginAdapterBase::Impl::resizeFS(" << plugin << ", " << n << ")" << std::endl;
+
+    int i = m_fsizes[plugin].size();
+    if (i >= n) return;
+
+//    std::cerr << "resizing from " << i << std::endl;
+
+    m_fs[plugin] = (VampFeatureList *)realloc
+        (m_fs[plugin], n * sizeof(VampFeatureList));
+
+    while (i < n) {
+        m_fs[plugin][i].featureCount = 0;
+        m_fs[plugin][i].features = 0;
+        m_fsizes[plugin].push_back(0);
+        m_fvsizes[plugin].push_back(std::vector<size_t>());
+        i++;
+    }
+}
+
+void
+PluginAdapterBase::Impl::resizeFL(Plugin *plugin, int n, size_t sz)
+{
+//    std::cerr << "PluginAdapterBase::Impl::resizeFL(" << plugin << ", " << n << ", "
+//              << sz << ")" << std::endl;
+
+    size_t i = m_fsizes[plugin][n];
+    if (i >= sz) return;
+
+//    std::cerr << "resizing from " << i << std::endl;
+
+    m_fs[plugin][n].features = (VampFeature *)realloc
+        (m_fs[plugin][n].features, sz * sizeof(VampFeature));
+
+    while (m_fsizes[plugin][n] < sz) {
+        m_fs[plugin][n].features[m_fsizes[plugin][n]].valueCount = 0;
+        m_fs[plugin][n].features[m_fsizes[plugin][n]].values = 0;
+        m_fs[plugin][n].features[m_fsizes[plugin][n]].label = 0;
+        m_fvsizes[plugin][n].push_back(0);
+        m_fsizes[plugin][n]++;
+    }
+}
+
+void
+PluginAdapterBase::Impl::resizeFV(Plugin *plugin, int n, int j, size_t sz)
+{
+//    std::cerr << "PluginAdapterBase::Impl::resizeFV(" << plugin << ", " << n << ", "
+//              << j << ", " << sz << ")" << std::endl;
+
+    size_t i = m_fvsizes[plugin][n][j];
+    if (i >= sz) return;
+
+//    std::cerr << "resizing from " << i << std::endl;
+
+    m_fs[plugin][n].features[j].values = (float *)realloc
+        (m_fs[plugin][n].features[j].values, sz * sizeof(float));
+
+    m_fvsizes[plugin][n][j] = sz;
+}
+  
+PluginAdapterBase::Impl::AdapterMap *
+PluginAdapterBase::Impl::m_adapterMap = 0;
+
+}
+
diff --git a/libs/vamp-sdk/vamp-sdk/PluginAdapter.h b/libs/vamp-sdk/vamp-sdk/PluginAdapter.h
new file mode 100644 (file)
index 0000000..bfc9750
--- /dev/null
@@ -0,0 +1,117 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_ADAPTER_H_
+#define _VAMP_PLUGIN_ADAPTER_H_
+
+#include <vamp/vamp.h>
+
+#include "Plugin.h"
+
+#include <map>
+
+namespace Vamp {
+
+/**
+ * \class PluginAdapterBase PluginAdapter.h <vamp-sdk/PluginAdapter.h>
+ * 
+ * PluginAdapter and PluginAdapterBase provide a wrapper class that a
+ * plugin library can use to make its C++ Vamp::Plugin objects
+ * available through the Vamp C API.
+ * 
+ * Almost all Vamp plugin libraries will want to make use of this.  To
+ * do so, all they need to do is declare a PluginAdapter<T> for each
+ * plugin class T in their library.  It's very simple, and you need to
+ * know absolutely nothing about how it works in order to use it.
+ * Just cut and paste from an existing plugin's discovery function.
+ * \see vampGetPluginDescriptor
+ */
+
+class PluginAdapterBase
+{
+public:
+    virtual ~PluginAdapterBase();
+
+    /**
+     * Return a VampPluginDescriptor describing the plugin that is
+     * wrapped by this adapter.
+     */
+    const VampPluginDescriptor *getDescriptor();
+
+protected:
+    PluginAdapterBase();
+
+    virtual Plugin *createPlugin(float inputSampleRate) = 0;
+
+    class Impl;
+    Impl *m_impl;
+};
+
+/**
+ * \class PluginAdapter PluginAdapter.h <vamp-sdk/PluginAdapter.h>
+ * 
+ * PluginAdapter turns a PluginAdapterBase into a specific wrapper for
+ * a particular plugin implementation.
+ *
+ * See PluginAdapterBase.
+ */
+
+template <typename P>
+class PluginAdapter : public PluginAdapterBase
+{
+public:
+    PluginAdapter() : PluginAdapterBase() { }
+    virtual ~PluginAdapter() { }
+
+protected:
+    Plugin *createPlugin(float inputSampleRate) {
+        P *p = new P(inputSampleRate);
+        Plugin *plugin = dynamic_cast<Plugin *>(p);
+        if (!plugin) {
+            std::cerr << "ERROR: PluginAdapter::createPlugin: "
+                      << "Template type is not a plugin!"
+                      << std::endl;
+            delete p;
+            return 0;
+        }
+        return plugin;
+    }
+};
+    
+}
+
+#endif
+
diff --git a/libs/vamp-sdk/vamp-sdk/PluginBase.h b/libs/vamp-sdk/vamp-sdk/PluginBase.h
new file mode 100644 (file)
index 0000000..38d2b49
--- /dev/null
@@ -0,0 +1,252 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_BASE_H_
+#define _VAMP_PLUGIN_BASE_H_
+
+#include <string>
+#include <vector>
+
+#define VAMP_SDK_VERSION "1.1"
+
+namespace Vamp {
+
+/**
+ * A base class for plugins with optional configurable parameters,
+ * programs, etc.  The Vamp::Plugin is derived from this, and
+ * individual Vamp plugins should derive from that.
+ *
+ * This class does not provide the necessary interfaces to instantiate
+ * or run a plugin.  It only specifies an interface for retrieving
+ * those controls that the host may wish to show to the user for
+ * editing.  It could meaningfully be subclassed by real-time plugins
+ * or other sorts of plugin as well as Vamp plugins.
+ */
+
+class PluginBase 
+{
+public:
+    virtual ~PluginBase() { }
+
+    /**
+     * Get the Vamp API compatibility level of the plugin.
+     */
+    virtual unsigned int getVampApiVersion() const { return 1; }
+
+    /**
+     * Get the computer-usable name of the plugin.  This should be
+     * reasonably short and contain no whitespace or punctuation
+     * characters.  It may only contain the characters [a-zA-Z0-9_].
+     * This is the authoritative way for a program to identify a
+     * plugin within a given library.
+     *
+     * This text may be visible to the user, but it should not be the
+     * main text used to identify a plugin to the user (that will be
+     * the name, below).
+     *
+     * Example: "zero_crossings"
+     */
+    virtual std::string getIdentifier() const = 0;
+
+    /**
+     * Get a human-readable name or title of the plugin.  This
+     * should be brief and self-contained, as it may be used to
+     * identify the plugin to the user in isolation (i.e. without also
+     * showing the plugin's "identifier").
+     *
+     * Example: "Zero Crossings"
+     */
+    virtual std::string getName() const = 0;
+
+    /**
+     * Get a human-readable description for the plugin, typically
+     * a line of text that may optionally be displayed in addition
+     * to the plugin's "name".  May be empty if the name has said
+     * it all already.
+     *
+     * Example: "Detect and count zero crossing points"
+     */
+    virtual std::string getDescription() const = 0;
+    
+    /**
+     * Get the name of the author or vendor of the plugin in
+     * human-readable form.  This should be a short identifying text,
+     * as it may be used to label plugins from the same source in a
+     * menu or similar.
+     */
+    virtual std::string getMaker() const = 0;
+
+    /**
+     * Get the copyright statement or licensing summary for the
+     * plugin.  This can be an informative text, without the same
+     * presentation constraints as mentioned for getMaker above.
+     */
+    virtual std::string getCopyright() const = 0;
+
+    /**
+     * Get the version number of the plugin.
+     */
+    virtual int getPluginVersion() const = 0;
+
+
+    struct ParameterDescriptor
+    {
+       /**
+        * The name of the parameter, in computer-usable form.  Should
+        * be reasonably short, and may only contain the characters
+        * [a-zA-Z0-9_].
+        */
+       std::string identifier;
+
+       /**
+        * The human-readable name of the parameter.
+        */
+       std::string name;
+
+       /**
+        * A human-readable short text describing the parameter.  May be
+         * empty if the name has said it all already.
+        */
+       std::string description;
+
+       /**
+        * The unit of the parameter, in human-readable form.
+        */
+       std::string unit;
+
+       /**
+        * The minimum value of the parameter.
+        */
+       float minValue;
+
+       /**
+        * The maximum value of the parameter.
+        */
+       float maxValue;
+
+       /**
+        * The default value of the parameter.  The plugin should
+        * ensure that parameters have this value on initialisation
+        * (i.e. the host is not required to explicitly set parameters
+        * if it wants to use their default values).
+        */
+       float defaultValue;
+       
+       /**
+        * True if the parameter values are quantized to a particular
+        * resolution.
+        */
+       bool isQuantized;
+
+       /**
+        * Quantization resolution of the parameter values (e.g. 1.0
+        * if they are all integers).  Undefined if isQuantized is
+        * false.
+        */
+       float quantizeStep;
+
+        /**
+         * Names for the quantized values.  If isQuantized is true,
+         * this may either be empty or contain one string for each of
+         * the quantize steps from minValue up to maxValue inclusive.
+         * Undefined if isQuantized is false.
+         *
+         * If these names are provided, they should be shown to the
+         * user in preference to the values themselves.  The user may
+         * never see the actual numeric values unless they are also
+         * encoded in the names.
+         */
+        std::vector<std::string> valueNames;
+    };
+
+    typedef std::vector<ParameterDescriptor> ParameterList;
+
+    /**
+     * Get the controllable parameters of this plugin.
+     */
+    virtual ParameterList getParameterDescriptors() const {
+       return ParameterList();
+    }
+
+    /**
+     * Get the value of a named parameter.  The argument is the identifier
+     * field from that parameter's descriptor.
+     */
+    virtual float getParameter(std::string) const { return 0.0; }
+
+    /**
+     * Set a named parameter.  The first argument is the identifier field
+     * from that parameter's descriptor.
+     */
+    virtual void setParameter(std::string, float) { } 
+
+    
+    typedef std::vector<std::string> ProgramList;
+
+    /**
+     * Get the program settings available in this plugin.  A program
+     * is a named shorthand for a set of parameter values; changing
+     * the program may cause the plugin to alter the values of its
+     * published parameters (and/or non-public internal processing
+     * parameters).  The host should re-read the plugin's parameter
+     * values after setting a new program.
+     *
+     * The programs must have unique names.
+     */
+    virtual ProgramList getPrograms() const { return ProgramList(); }
+
+    /**
+     * Get the current program.
+     */
+    virtual std::string getCurrentProgram() const { return ""; }
+
+    /**
+     * Select a program.  (If the given program name is not one of the
+     * available programs, do nothing.)
+     */
+    virtual void selectProgram(std::string) { }
+
+    /**
+     * Get the type of plugin.  This is to be implemented by the
+     * immediate subclass, not by actual plugins.  Do not attempt to
+     * implement this in plugin code.
+     */
+    virtual std::string getType() const = 0;
+};
+
+}
+
+#endif
diff --git a/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.cpp b/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.cpp
new file mode 100644 (file)
index 0000000..12e1539
--- /dev/null
@@ -0,0 +1,418 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "PluginHostAdapter.h"
+
+namespace Vamp
+{
+
+PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor,
+                                     float inputSampleRate) :
+    Plugin(inputSampleRate),
+    m_descriptor(descriptor)
+{
+//    std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl;
+    m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
+    if (!m_handle) {
+//        std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl;
+    }
+}
+
+PluginHostAdapter::~PluginHostAdapter()
+{
+//    std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
+    if (m_handle) m_descriptor->cleanup(m_handle);
+}
+
+std::vector<std::string>
+PluginHostAdapter::getPluginPath()
+{
+    std::vector<std::string> path;
+    std::string envPath;
+
+    char *cpath = getenv("VAMP_PATH");
+    if (cpath) envPath = cpath;
+
+#ifdef _WIN32
+#define PATH_SEPARATOR ';'
+#define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins"
+#else
+#define PATH_SEPARATOR ':'
+#ifdef __APPLE__
+#define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"
+#else
+#define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
+#endif
+#endif
+
+    if (envPath == "") {
+        envPath = DEFAULT_VAMP_PATH;
+        char *chome = getenv("HOME");
+        if (chome) {
+            std::string home(chome);
+            std::string::size_type f;
+            while ((f = envPath.find("$HOME")) != std::string::npos &&
+                    f < envPath.length()) {
+                envPath.replace(f, 5, home);
+            }
+        }
+#ifdef _WIN32
+        char *cpfiles = getenv("ProgramFiles");
+        if (!cpfiles) cpfiles = "C:\\Program Files";
+        std::string pfiles(cpfiles);
+        std::string::size_type f;
+        while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
+               f < envPath.length()) {
+            envPath.replace(f, 14, pfiles);
+        }
+#endif
+    }
+
+    std::string::size_type index = 0, newindex = 0;
+
+    while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) {
+       path.push_back(envPath.substr(index, newindex - index));
+       index = newindex + 1;
+    }
+    
+    path.push_back(envPath.substr(index));
+
+    return path;
+}
+
+bool
+PluginHostAdapter::initialise(size_t channels,
+                              size_t stepSize,
+                              size_t blockSize)
+{
+    if (!m_handle) return false;
+    return m_descriptor->initialise(m_handle, channels, stepSize, blockSize) ?
+        true : false;
+}
+
+void
+PluginHostAdapter::reset()
+{
+    if (!m_handle) return;
+    m_descriptor->reset(m_handle);
+}
+
+PluginHostAdapter::InputDomain
+PluginHostAdapter::getInputDomain() const
+{
+    if (m_descriptor->inputDomain == vampFrequencyDomain) {
+        return FrequencyDomain;
+    } else {
+        return TimeDomain;
+    }
+}
+
+unsigned int
+PluginHostAdapter::getVampApiVersion() const
+{
+    return m_descriptor->vampApiVersion;
+}
+
+std::string
+PluginHostAdapter::getIdentifier() const
+{
+    return m_descriptor->identifier;
+}
+
+std::string
+PluginHostAdapter::getName() const
+{
+    return m_descriptor->name;
+}
+
+std::string
+PluginHostAdapter::getDescription() const
+{
+    return m_descriptor->description;
+}
+
+std::string
+PluginHostAdapter::getMaker() const
+{
+    return m_descriptor->maker;
+}
+
+int
+PluginHostAdapter::getPluginVersion() const
+{
+    return m_descriptor->pluginVersion;
+}
+
+std::string
+PluginHostAdapter::getCopyright() const
+{
+    return m_descriptor->copyright;
+}
+
+PluginHostAdapter::ParameterList
+PluginHostAdapter::getParameterDescriptors() const
+{
+    ParameterList list;
+    for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
+        const VampParameterDescriptor *spd = m_descriptor->parameters[i];
+        ParameterDescriptor pd;
+        pd.identifier = spd->identifier;
+        pd.name = spd->name;
+        pd.description = spd->description;
+        pd.unit = spd->unit;
+        pd.minValue = spd->minValue;
+        pd.maxValue = spd->maxValue;
+        pd.defaultValue = spd->defaultValue;
+        pd.isQuantized = spd->isQuantized;
+        pd.quantizeStep = spd->quantizeStep;
+        if (pd.isQuantized && spd->valueNames) {
+            for (unsigned int j = 0; spd->valueNames[j]; ++j) {
+                pd.valueNames.push_back(spd->valueNames[j]);
+            }
+        }
+        list.push_back(pd);
+    }
+    return list;
+}
+
+float
+PluginHostAdapter::getParameter(std::string param) const
+{
+    if (!m_handle) return 0.0;
+
+    for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
+        if (param == m_descriptor->parameters[i]->identifier) {
+            return m_descriptor->getParameter(m_handle, i);
+        }
+    }
+
+    return 0.0;
+}
+
+void
+PluginHostAdapter::setParameter(std::string param, 
+                                float value)
+{
+    if (!m_handle) return;
+
+    for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
+        if (param == m_descriptor->parameters[i]->identifier) {
+            m_descriptor->setParameter(m_handle, i, value);
+            return;
+        }
+    }
+}
+
+PluginHostAdapter::ProgramList
+PluginHostAdapter::getPrograms() const
+{
+    ProgramList list;
+    
+    for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
+        list.push_back(m_descriptor->programs[i]);
+    }
+    
+    return list;
+}
+
+std::string
+PluginHostAdapter::getCurrentProgram() const
+{
+    if (!m_handle) return "";
+
+    int pn = m_descriptor->getCurrentProgram(m_handle);
+    return m_descriptor->programs[pn];
+}
+
+void
+PluginHostAdapter::selectProgram(std::string program)
+{
+    if (!m_handle) return;
+
+    for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
+        if (program == m_descriptor->programs[i]) {
+            m_descriptor->selectProgram(m_handle, i);
+            return;
+        }
+    }
+}
+
+size_t
+PluginHostAdapter::getPreferredStepSize() const
+{
+    if (!m_handle) return 0;
+    return m_descriptor->getPreferredStepSize(m_handle);
+}
+
+size_t
+PluginHostAdapter::getPreferredBlockSize() const
+{
+    if (!m_handle) return 0;
+    return m_descriptor->getPreferredBlockSize(m_handle);
+}
+
+size_t
+PluginHostAdapter::getMinChannelCount() const
+{
+    if (!m_handle) return 0;
+    return m_descriptor->getMinChannelCount(m_handle);
+}
+
+size_t
+PluginHostAdapter::getMaxChannelCount() const
+{
+    if (!m_handle) return 0;
+    return m_descriptor->getMaxChannelCount(m_handle);
+}
+
+PluginHostAdapter::OutputList
+PluginHostAdapter::getOutputDescriptors() const
+{
+    OutputList list;
+    if (!m_handle) {
+//        std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
+        return list;
+    }
+
+    unsigned int count = m_descriptor->getOutputCount(m_handle);
+
+    for (unsigned int i = 0; i < count; ++i) {
+        VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
+        OutputDescriptor d;
+        d.identifier = sd->identifier;
+        d.name = sd->name;
+        d.description = sd->description;
+        d.unit = sd->unit;
+        d.hasFixedBinCount = sd->hasFixedBinCount;
+        d.binCount = sd->binCount;
+        if (d.hasFixedBinCount) {
+            for (unsigned int j = 0; j < sd->binCount; ++j) {
+                d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
+            }
+        }
+        d.hasKnownExtents = sd->hasKnownExtents;
+        d.minValue = sd->minValue;
+        d.maxValue = sd->maxValue;
+        d.isQuantized = sd->isQuantized;
+        d.quantizeStep = sd->quantizeStep;
+
+        switch (sd->sampleType) {
+        case vampOneSamplePerStep:
+            d.sampleType = OutputDescriptor::OneSamplePerStep; break;
+        case vampFixedSampleRate:
+            d.sampleType = OutputDescriptor::FixedSampleRate; break;
+        case vampVariableSampleRate:
+            d.sampleType = OutputDescriptor::VariableSampleRate; break;
+        }
+
+        d.sampleRate = sd->sampleRate;
+
+        list.push_back(d);
+
+        m_descriptor->releaseOutputDescriptor(sd);
+    }
+
+    return list;
+}
+
+PluginHostAdapter::FeatureSet
+PluginHostAdapter::process(const float *const *inputBuffers,
+                           RealTime timestamp)
+{
+    FeatureSet fs;
+    if (!m_handle) return fs;
+
+    int sec = timestamp.sec;
+    int nsec = timestamp.nsec;
+    
+    VampFeatureList *features = m_descriptor->process(m_handle,
+                                                      inputBuffers,
+                                                      sec, nsec);
+    
+    convertFeatures(features, fs);
+    m_descriptor->releaseFeatureSet(features);
+    return fs;
+}
+
+PluginHostAdapter::FeatureSet
+PluginHostAdapter::getRemainingFeatures()
+{
+    FeatureSet fs;
+    if (!m_handle) return fs;
+    
+    VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle); 
+
+    convertFeatures(features, fs);
+    m_descriptor->releaseFeatureSet(features);
+    return fs;
+}
+
+void
+PluginHostAdapter::convertFeatures(VampFeatureList *features,
+                                   FeatureSet &fs)
+{
+    if (!features) return;
+
+    unsigned int outputs = m_descriptor->getOutputCount(m_handle);
+
+    for (unsigned int i = 0; i < outputs; ++i) {
+        
+        VampFeatureList &list = features[i];
+
+        if (list.featureCount > 0) {
+
+            for (unsigned int j = 0; j < list.featureCount; ++j) {
+                
+                Feature feature;
+                feature.hasTimestamp = list.features[j].hasTimestamp;
+                feature.timestamp = RealTime(list.features[j].sec,
+                                             list.features[j].nsec);
+
+                for (unsigned int k = 0; k < list.features[j].valueCount; ++k) {
+                    feature.values.push_back(list.features[j].values[k]);
+                }
+
+                if (list.features[j].label) {
+                    feature.label = list.features[j].label;
+                }
+
+                fs[i].push_back(feature);
+            }
+        }
+    }
+}
+
+}
diff --git a/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.h b/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.h
new file mode 100644 (file)
index 0000000..80ae620
--- /dev/null
@@ -0,0 +1,117 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_HOST_ADAPTER_H_
+#define _VAMP_PLUGIN_HOST_ADAPTER_H_
+
+#include <vamp/vamp.h>
+#include <vamp-sdk/Plugin.h>
+
+#include <vector>
+
+namespace Vamp {
+
+/**
+ * \class PluginHostAdapter PluginHostAdapter.h <vamp-sdk/PluginHostAdapter.h>
+ * 
+ * PluginHostAdapter is a wrapper class that a Vamp host can use to
+ * make the C-language VampPluginDescriptor object appear as a C++
+ * Vamp::Plugin object.
+ *
+ * The Vamp API is defined in vamp/vamp.h as a C API.  The C++ objects
+ * used for convenience by plugins and hosts actually communicate
+ * using the C low-level API, but the details of this communication
+ * are handled seamlessly by the Vamp SDK implementation provided the
+ * plugin and host use the proper C++ wrapper objects.
+ *
+ * See also PluginAdapter, the plugin-side wrapper that makes a C++
+ * plugin object available using the C query API.
+ */
+
+class PluginHostAdapter : public Plugin
+{
+public:
+    PluginHostAdapter(const VampPluginDescriptor *descriptor,
+                      float inputSampleRate);
+    virtual ~PluginHostAdapter();
+    
+    static std::vector<std::string> getPluginPath();
+
+    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+    void reset();
+
+    InputDomain getInputDomain() const;
+
+    unsigned int getVampApiVersion() const;
+    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);
+
+    size_t getPreferredStepSize() const;
+    size_t getPreferredBlockSize() const;
+
+    size_t getMinChannelCount() const;
+    size_t getMaxChannelCount() const;
+
+    OutputList getOutputDescriptors() const;
+
+    FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+    FeatureSet getRemainingFeatures();
+
+protected:
+    void convertFeatures(VampFeatureList *, FeatureSet &);
+
+    const VampPluginDescriptor *m_descriptor;
+    VampPluginHandle m_handle;
+};
+
+}
+
+#endif
+
+
diff --git a/libs/vamp-sdk/vamp-sdk/RealTime.cpp b/libs/vamp-sdk/vamp-sdk/RealTime.cpp
new file mode 100644 (file)
index 0000000..0b541cc
--- /dev/null
@@ -0,0 +1,254 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+/*
+   This is a modified version of a source file from the 
+   Rosegarden MIDI and audio sequencer and notation editor.
+   This file copyright 2000-2006 Chris Cannam.
+   Relicensed by the author as detailed above.
+*/
+
+#include <iostream>
+
+#if (__GNUC__ < 3)
+#include <strstream>
+#define stringstream strstream
+#else
+#include <sstream>
+#endif
+
+using std::cerr;
+using std::endl;
+
+#include "RealTime.h"
+
+#ifndef _WIN32
+#include <sys/time.h>
+#endif
+
+namespace Vamp {
+
+// A RealTime consists of two ints that must be at least 32 bits each.
+// A signed 32-bit int can store values exceeding +/- 2 billion.  This
+// means we can safely use our lower int for nanoseconds, as there are
+// 1 billion nanoseconds in a second and we need to handle double that
+// because of the implementations of addition etc that we use.
+//
+// The maximum valid RealTime on a 32-bit system is somewhere around
+// 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
+
+#define ONE_BILLION 1000000000
+
+RealTime::RealTime(int s, int n) :
+    sec(s), nsec(n)
+{
+    if (sec == 0) {
+       while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
+       while (nsec >=  ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
+    } else if (sec < 0) {
+       while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
+       while (nsec > 0)             { nsec -= ONE_BILLION; ++sec; }
+    } else { 
+       while (nsec >=  ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
+       while (nsec < 0)             { nsec += ONE_BILLION; --sec; }
+    }
+}
+
+RealTime
+RealTime::fromSeconds(double sec)
+{
+    return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5));
+}
+
+RealTime
+RealTime::fromMilliseconds(int msec)
+{
+    return RealTime(msec / 1000, (msec % 1000) * 1000000);
+}
+
+#ifndef _WIN32
+RealTime
+RealTime::fromTimeval(const struct timeval &tv)
+{
+    return RealTime(tv.tv_sec, tv.tv_usec * 1000);
+}
+#endif
+
+std::ostream &operator<<(std::ostream &out, const RealTime &rt)
+{
+    if (rt < RealTime::zeroTime) {
+       out << "-";
+    } else {
+       out << " ";
+    }
+
+    int s = (rt.sec < 0 ? -rt.sec : rt.sec);
+    int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
+
+    out << s << ".";
+
+    int nn(n);
+    if (nn == 0) out << "00000000";
+    else while (nn < (ONE_BILLION / 10)) {
+       out << "0";
+       nn *= 10;
+    }
+    
+    out << n << "R";
+    return out;
+}
+
+std::string
+RealTime::toString() const
+{
+    std::stringstream out;
+    out << *this;
+    
+#if (__GNUC__ < 3)
+    out << std::ends;
+#endif
+
+    std::string s = out.str();
+
+    // remove trailing R
+    return s.substr(0, s.length() - 1);
+}
+
+std::string
+RealTime::toText(bool fixedDp) const
+{
+    if (*this < RealTime::zeroTime) return "-" + (-*this).toText();
+
+    std::stringstream out;
+
+    if (sec >= 3600) {
+       out << (sec / 3600) << ":";
+    }
+
+    if (sec >= 60) {
+       out << (sec % 3600) / 60 << ":";
+    }
+
+    if (sec >= 10) {
+       out << ((sec % 60) / 10);
+    }
+
+    out << (sec % 10);
+    
+    int ms = msec();
+
+    if (ms != 0) {
+       out << ".";
+       out << (ms / 100);
+       ms = ms % 100;
+       if (ms != 0) {
+           out << (ms / 10);
+           ms = ms % 10;
+       } else if (fixedDp) {
+           out << "0";
+       }
+       if (ms != 0) {
+           out << ms;
+       } else if (fixedDp) {
+           out << "0";
+       }
+    } else if (fixedDp) {
+       out << ".000";
+    }
+       
+#if (__GNUC__ < 3)
+    out << std::ends;
+#endif
+
+    std::string s = out.str();
+
+    return s;
+}
+
+
+RealTime
+RealTime::operator/(int d) const
+{
+    int secdiv = sec / d;
+    int secrem = sec % d;
+
+    double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
+    
+    return RealTime(secdiv, int(nsecdiv + 0.5));
+}
+
+double 
+RealTime::operator/(const RealTime &r) const
+{
+    double lTotal = double(sec) * ONE_BILLION + double(nsec);
+    double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
+    
+    if (rTotal == 0) return 0.0;
+    else return lTotal/rTotal;
+}
+
+long
+RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
+{
+    if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
+
+    // We like integers.  The last term is always zero unless the
+    // sample rate is greater than 1MHz, but hell, you never know...
+
+    long frame =
+       time.sec * sampleRate +
+       (time.msec() * sampleRate) / 1000 +
+       ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 +
+       ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000;
+
+    return frame;
+}
+
+RealTime
+RealTime::frame2RealTime(long frame, unsigned int sampleRate)
+{
+    if (frame < 0) return -frame2RealTime(-frame, sampleRate);
+
+    RealTime rt;
+    rt.sec = frame / long(sampleRate);
+    frame -= rt.sec * long(sampleRate);
+    rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000);
+    return rt;
+}
+
+const RealTime RealTime::zeroTime(0,0);
+
+}
diff --git a/libs/vamp-sdk/vamp-sdk/RealTime.h b/libs/vamp-sdk/vamp-sdk/RealTime.h
new file mode 100644 (file)
index 0000000..4dd78fd
--- /dev/null
@@ -0,0 +1,154 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+/*
+   This is a modified version of a source file from the 
+   Rosegarden MIDI and audio sequencer and notation editor.
+   This file copyright 2000-2006 Chris Cannam.
+   Relicensed by the author as detailed above.
+*/
+
+#ifndef _VAMP_REAL_TIME_H_
+#define _VAMP_REAL_TIME_H_
+
+#include <iostream>
+#include <string>
+
+#ifndef _WIN32
+struct timeval;
+#endif
+
+namespace Vamp {
+
+/**
+ * \class RealTime RealTime.h <vamp-sdk/RealTime.h>
+ * 
+ * RealTime represents time values to nanosecond precision
+ * with accurate arithmetic and frame-rate conversion functions.
+ */
+
+struct RealTime
+{
+    int sec;
+    int nsec;
+
+    int usec() const { return nsec / 1000; }
+    int msec() const { return nsec / 1000000; }
+
+    RealTime(): sec(0), nsec(0) {}
+    RealTime(int s, int n);
+
+    RealTime(const RealTime &r) :
+       sec(r.sec), nsec(r.nsec) { }
+
+    static RealTime fromSeconds(double sec);
+    static RealTime fromMilliseconds(int msec);
+
+#ifndef _WIN32
+    static RealTime fromTimeval(const struct timeval &);
+#endif
+
+    RealTime &operator=(const RealTime &r) {
+       sec = r.sec; nsec = r.nsec; return *this;
+    }
+
+    RealTime operator+(const RealTime &r) const {
+       return RealTime(sec + r.sec, nsec + r.nsec);
+    }
+    RealTime operator-(const RealTime &r) const {
+       return RealTime(sec - r.sec, nsec - r.nsec);
+    }
+    RealTime operator-() const {
+       return RealTime(-sec, -nsec);
+    }
+
+    bool operator <(const RealTime &r) const {
+       if (sec == r.sec) return nsec < r.nsec;
+       else return sec < r.sec;
+    }
+
+    bool operator >(const RealTime &r) const {
+       if (sec == r.sec) return nsec > r.nsec;
+       else return sec > r.sec;
+    }
+
+    bool operator==(const RealTime &r) const {
+        return (sec == r.sec && nsec == r.nsec);
+    }
+    bool operator!=(const RealTime &r) const {
+        return !(r == *this);
+    }
+    bool operator>=(const RealTime &r) const {
+        if (sec == r.sec) return nsec >= r.nsec;
+        else return sec >= r.sec;
+    }
+
+    bool operator<=(const RealTime &r) const {
+        if (sec == r.sec) return nsec <= r.nsec;
+        else return sec <= r.sec;
+    }
+
+    RealTime operator/(int d) const;
+
+    // Find the fractional difference between times
+    //
+    double operator/(const RealTime &r) const;
+
+    // Return a human-readable debug-type string to full precision
+    // (probably not a format to show to a user directly)
+    // 
+    std::string toString() const;
+
+    // Return a user-readable string to the nearest millisecond
+    // in a form like HH:MM:SS.mmm
+    //
+    std::string toText(bool fixedDp = false) const;
+
+    // Convenience functions for handling sample frames
+    //
+    static long realTime2Frame(const RealTime &r, unsigned int sampleRate);
+    static RealTime frame2RealTime(long frame, unsigned int sampleRate);
+
+    static const RealTime zeroTime;
+};
+
+std::ostream &operator<<(std::ostream &out, const RealTime &rt);
+
+}
+    
+#endif
diff --git a/libs/vamp-sdk/vamp-sdk/doc-overview b/libs/vamp-sdk/vamp-sdk/doc-overview
new file mode 100644 (file)
index 0000000..4beb698
--- /dev/null
@@ -0,0 +1,120 @@
+
+/** \mainpage Vamp Plugin SDK
+
+\section about About Vamp
+
+Vamp is an API for C and C++ plugins that process sampled audio data
+to produce descriptive output (measurements or semantic observations).
+Find more information at http://www.vamp-plugins.org/ .
+
+Although the official API for Vamp plugins is defined in C for maximum
+binary compatibility, we strongly recommend using the provided C++
+classes in the SDK to implement your own plugins and hosts.
+
+\section plugins For Plugins
+
+Plugins should subclass Vamp::Plugin, and then use a
+Vamp::PluginAdapter to expose the correct C API for the plugin.  Read
+the documentation for Vamp::PluginBase and Vamp::Plugin before
+starting.
+
+Plugins should be compiled and linked into dynamic libraries using the
+usual convention for your platform, and should link (preferably
+statically) with -lvamp-sdk.  Any number of plugins can reside in a
+single dynamic library.  See plugins.cpp in the example plugins
+directory for the sort of code that will need to accompany your plugin
+class or classes, to make it possible for a host to look up your
+plugins properly.
+
+The following example plugins are provided:
+
+ - ZeroCrossing calculates the positions and density of zero-crossing
+ points in an audio waveform.
+
+ - SpectralCentroid calculates the centre of gravity of the frequency
+ domain representation of each block of audio.
+
+ - AmplitudeFollower is an implementation of SuperCollider's
+ amplitude-follower algorithm as a simple Vamp plugin.
+
+ - PercussionOnsetDetector estimates the locations of percussive
+ onsets using a simple method described in "Drum Source Separation
+ using Percussive Feature Detection and Spectral Modulation" by Dan
+ Barry, Derry Fitzgerald, Eugene Coyle and Bob Lawlor, ISSC 2005.
+
+\section hosts For Hosts
+
+Hosts will normally use a Vamp::PluginHostAdapter to convert each
+plugin's exposed C API back into a useful Vamp::Plugin C++ object.
+
+Starting with version 1.1 of the Vamp SDK, there are several classes
+in the Vamp::HostExt namespace that aim to make the host's life as
+easy as possible:
+
+ - Vamp::HostExt::PluginLoader provides a very simple interface for a
+ host to discover, load, and find out category information about the
+ available plugins.  Most "casual" Vamp hosts will probably want to
+ use this class.
+
+ - Vamp::HostExt::PluginInputDomainAdapter provides a simple means for
+ hosts to handle plugins that expect frequency-domain input, without
+ having to convert the input themselves.
+
+ - Vamp::HostExt::PluginChannelAdapter provides a simple means for
+ hosts to use plugins that do not necessarily support the same number
+ of audio channels as they have available, without having to apply a
+ channel management / mixdown policy themselves.
+
+The PluginLoader class can also use the input domain and channel
+adapters automatically to make the entire conversion process
+transparent to the host if required.
+
+Hosts should link with -lvamp-hostsdk.
+
+(The following notes in this section are mostly relevant for
+developers that are not using the HostExt classes, or that wish to
+know more about the policy they implement.)
+
+The Vamp API does not officially specify how to load plugin libraries
+or where to find them.  However, the SDK does include a function
+(Vamp::PluginHostAdapter::getPluginPath()) that returns a recommended
+directory search path that hosts may use for plugin libraries.
+
+Our suggestion for a host is to search each directory in this path for
+.DLL (on Windows), .so (on Linux, Solaris, BSD etc) or .dylib (on
+OS/X) files, then to load each one and perform a dynamic name lookup
+on the vampGetPluginDescriptor function to enumerate the plugins in
+the library.  The example host has some code that may help, but this
+operation will necessarily be system-dependent.
+
+Vamp also has an informal convention for sorting plugins into
+functional categories.  In addition to the library file itself, a
+plugin library may install a category file with the same name as the
+library but .cat extension.  The existence and format of this file are
+not specified by the Vamp API, but by convention the file may contain
+lines of the format
+
+\code
+vamp:pluginlibrary:pluginname::General Category > Specific Category
+\endcode
+
+which a host may read and use to assign plugins a location within a
+category tree for display to the user.  The expectation is that
+advanced users may also choose to set up their own preferred category
+trees, which is why this information is not queried as part of the
+Vamp API itself.
+
+There is an example host in the "host" directory from which code may
+be drawn.
+
+\section license License
+
+This plugin SDK is freely redistributable under a "new-style BSD"
+licence.  See the file COPYING for more details.  In short, you may
+modify and redistribute the SDK and example plugins within any
+commercial or non-commercial, proprietary or open-source plugin or
+application under almost any conditions, with no obligation to provide
+source code, provided you retain the original copyright note.
+
+
+*/
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.cpp b/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.cpp
new file mode 100644 (file)
index 0000000..3ce51ce
--- /dev/null
@@ -0,0 +1,228 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006-2007 Chris Cannam and QMUL.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "PluginChannelAdapter.h"
+
+namespace Vamp {
+
+namespace HostExt {
+
+class PluginChannelAdapter::Impl
+{
+public:
+    Impl(Plugin *plugin);
+    ~Impl();
+
+    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+
+    FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+protected:
+    Plugin *m_plugin;
+    size_t m_blockSize;
+    size_t m_inputChannels;
+    size_t m_pluginChannels;
+    float **m_buffer;
+    const float **m_forwardPtrs;
+};
+
+PluginChannelAdapter::PluginChannelAdapter(Plugin *plugin) :
+    PluginWrapper(plugin)
+{
+    m_impl = new Impl(plugin);
+}
+
+PluginChannelAdapter::~PluginChannelAdapter()
+{
+    delete m_impl;
+}
+
+bool
+PluginChannelAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    return m_impl->initialise(channels, stepSize, blockSize);
+}
+
+PluginChannelAdapter::FeatureSet
+PluginChannelAdapter::process(const float *const *inputBuffers,
+                              RealTime timestamp)
+{
+    return m_impl->process(inputBuffers, timestamp);
+}
+
+PluginChannelAdapter::Impl::Impl(Plugin *plugin) :
+    m_plugin(plugin),
+    m_blockSize(0),
+    m_inputChannels(0),
+    m_pluginChannels(0),
+    m_buffer(0),
+    m_forwardPtrs(0)
+{
+}
+
+PluginChannelAdapter::Impl::~Impl()
+{
+    // the adapter will delete the plugin
+
+    if (m_buffer) {
+        if (m_inputChannels > m_pluginChannels) {
+            delete[] m_buffer[0];
+        } else {
+            for (size_t i = 0; i < m_pluginChannels - m_inputChannels; ++i) {
+                delete[] m_buffer[i];
+            }
+        }
+        delete[] m_buffer;
+        m_buffer = 0;
+    }
+
+    if (m_forwardPtrs) {
+        delete[] m_forwardPtrs;
+        m_forwardPtrs = 0;
+    }
+}
+
+bool
+PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    m_blockSize = blockSize;
+
+    size_t minch = m_plugin->getMinChannelCount();
+    size_t maxch = m_plugin->getMaxChannelCount();
+
+    m_inputChannels = channels;
+
+    if (m_inputChannels < minch) {
+
+        m_forwardPtrs = new const float *[minch];
+
+        if (m_inputChannels > 1) {
+            // We need a set of zero-valued buffers to add to the
+            // forwarded pointers
+            m_buffer = new float*[minch - channels];
+            for (size_t i = 0; i < minch; ++i) {
+                m_buffer[i] = new float[blockSize];
+                for (size_t j = 0; j < blockSize; ++j) {
+                    m_buffer[i][j] = 0.f;
+                }
+            }
+        }
+
+        m_pluginChannels = minch;
+
+        std::cerr << "PluginChannelAdapter::initialise: expanding " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
+
+    } else if (m_inputChannels > maxch) {
+
+        // We only need m_buffer if we are mixing down to a single
+        // channel -- otherwise we can just forward the same float* as
+        // passed in to process(), expecting the excess to be ignored
+
+        if (maxch == 1) {
+            m_buffer = new float *[1];
+            m_buffer[0] = new float[blockSize];
+
+            std::cerr << "PluginChannelAdapter::initialise: mixing " << m_inputChannels << " to mono for plugin" << std::endl;
+
+        } else {
+            
+            std::cerr << "PluginChannelAdapter::initialise: reducing " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
+        }
+
+        m_pluginChannels = maxch;
+
+    } else {
+        std::cerr << "PluginChannelAdapter::initialise: accepting given number of channels (" << m_inputChannels << ")" << std::endl;
+        m_pluginChannels = m_inputChannels;
+    }
+
+    return m_plugin->initialise(m_pluginChannels, stepSize, blockSize);
+}
+
+PluginChannelAdapter::FeatureSet
+PluginChannelAdapter::Impl::process(const float *const *inputBuffers,
+                                    RealTime timestamp)
+{
+//    std::cerr << "PluginChannelAdapter::process: " << m_inputChannels << " -> " << m_pluginChannels << " channels" << std::endl;
+
+    if (m_inputChannels < m_pluginChannels) {
+
+        if (m_inputChannels == 1) {
+            for (size_t i = 0; i < m_pluginChannels; ++i) {
+                m_forwardPtrs[i] = inputBuffers[0];
+            }
+        } else {
+            for (size_t i = 0; i < m_inputChannels; ++i) {
+                m_forwardPtrs[i] = inputBuffers[i];
+            }
+            for (size_t i = m_inputChannels; i < m_pluginChannels; ++i) {
+                m_forwardPtrs[i] = m_buffer[i - m_inputChannels];
+            }
+        }
+
+        return m_plugin->process(m_forwardPtrs, timestamp);
+
+    } else if (m_inputChannels > m_pluginChannels) {
+
+        if (m_pluginChannels == 1) {
+            for (size_t j = 0; j < m_blockSize; ++j) {
+                m_buffer[0][j] = inputBuffers[0][j];
+            }
+            for (size_t i = 1; i < m_inputChannels; ++i) {
+                for (size_t j = 0; j < m_blockSize; ++j) {
+                    m_buffer[0][j] += inputBuffers[i][j];
+                }
+            }
+            for (size_t j = 0; j < m_blockSize; ++j) {
+                m_buffer[0][j] /= m_inputChannels;
+            }
+            return m_plugin->process(m_buffer, timestamp);
+        } else {
+            return m_plugin->process(inputBuffers, timestamp);
+        }
+
+    } else {
+
+        return m_plugin->process(inputBuffers, timestamp);
+    }
+}
+
+}
+
+}
+
+
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.h b/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.h
new file mode 100644 (file)
index 0000000..a2b4d89
--- /dev/null
@@ -0,0 +1,128 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006-2007 Chris Cannam and QMUL.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_CHANNEL_ADAPTER_H_
+#define _VAMP_PLUGIN_CHANNEL_ADAPTER_H_
+
+#include "PluginWrapper.h"
+
+namespace Vamp {
+
+namespace HostExt {
+
+/**
+ * \class PluginChannelAdapter PluginChannelAdapter.h <vamp-sdk/hostext/PluginChannelAdapter.h>
+ *
+ * PluginChannelAdapter is a Vamp plugin adapter that implements a
+ * policy for management of plugins that expect a different number of
+ * input channels from the number actually available in the source
+ * audio data.
+ *
+ * A host using PluginChannelAdapter may ignore the getMinChannelCount
+ * and getMaxChannelCount reported by the plugin, and still expect the
+ * plugin to run.
+ *
+ * PluginChannelAdapter implements the following policy:
+ *
+ *  - If the plugin supports the provided number of channels directly,
+ *  PluginChannelAdapter will just run the plugin as normal.
+ *
+ *  - If the plugin only supports exactly one channel but more than
+ *  one channel is provided, PluginChannelAdapter will use the mean of
+ *  the channels.  This ensures that the resulting values remain
+ *  within the same magnitude range as expected for mono data.
+ *
+ *  - If the plugin requires more than one channel but exactly one is
+ *  provided, the provided channel will be duplicated across all the
+ *  plugin input channels.
+ *
+ * If none of the above apply:
+ * 
+ *  - If the plugin requires more channels than are provided, the
+ *  minimum acceptable number of channels will be produced by adding
+ *  empty (zero valued) channels to those provided.
+ *
+ *  - If the plugin requires fewer channels than are provided, the
+ *  maximum acceptable number of channels will be produced by
+ *  discarding the excess channels.
+ *
+ * Hosts requiring a different channel policy from the above will need
+ * to implement it themselves, instead of using PluginChannelAdapter.
+ *
+ * Note that PluginChannelAdapter does not override the minimum and
+ * maximum channel counts returned by the wrapped plugin.  The host
+ * will need to be aware that it is using a PluginChannelAdapter, and
+ * be prepared to ignore these counts as necessary.  (This contrasts
+ * with the approach used in PluginInputDomainAdapter, which aims to
+ * make the host completely unaware of which underlying input domain
+ * is in fact in use.)
+ * 
+ * (The rationale for this is that a host may wish to use the
+ * PluginChannelAdapter but still discriminate in some way on the
+ * basis of the number of channels actually supported.  For example, a
+ * simple stereo audio host may prefer to reject plugins that require
+ * more than two channels on the grounds that doesn't actually
+ * understand what they are for, rather than allow the channel adapter
+ * to make a potentially meaningless channel conversion for them.)
+ *
+ * In every respect other than its management of channels, the
+ * PluginChannelAdapter behaves identically to the plugin that it
+ * wraps.  The wrapped plugin will be deleted when the wrapper is
+ * deleted.
+ *
+ * \note This class was introduced in version 1.1 of the Vamp plugin SDK.
+ */
+
+class PluginChannelAdapter : public PluginWrapper
+{
+public:
+    PluginChannelAdapter(Plugin *plugin); // I take ownership of plugin
+    virtual ~PluginChannelAdapter();
+
+    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+
+    FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+protected:
+    class Impl;
+    Impl *m_impl;
+};
+
+}
+
+}
+
+#endif
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.cpp b/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.cpp
new file mode 100644 (file)
index 0000000..3fc0d74
--- /dev/null
@@ -0,0 +1,458 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006-2007 Chris Cannam and QMUL.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "PluginInputDomainAdapter.h"
+
+#include <cmath>
+
+namespace Vamp {
+
+namespace HostExt {
+
+class PluginInputDomainAdapter::Impl
+{
+public:
+    Impl(Plugin *plugin, float inputSampleRate);
+    ~Impl();
+    
+    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+
+    size_t getPreferredStepSize() const;
+    size_t getPreferredBlockSize() const;
+
+    FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+protected:
+    Plugin *m_plugin;
+    float m_inputSampleRate;
+    size_t m_channels;
+    size_t m_blockSize;
+    float **m_freqbuf;
+    double *m_ri;
+    double *m_ro;
+    double *m_io;
+
+    void fft(unsigned int n, bool inverse,
+             double *ri, double *ii, double *ro, double *io);
+
+    size_t makeBlockSizeAcceptable(size_t) const;
+};
+
+PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
+    PluginWrapper(plugin)
+{
+    m_impl = new Impl(plugin, m_inputSampleRate);
+}
+
+PluginInputDomainAdapter::~PluginInputDomainAdapter()
+{
+    delete m_impl;
+}
+  
+bool
+PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    return m_impl->initialise(channels, stepSize, blockSize);
+}
+
+Plugin::InputDomain
+PluginInputDomainAdapter::getInputDomain() const
+{
+    return TimeDomain;
+}
+
+size_t
+PluginInputDomainAdapter::getPreferredStepSize() const
+{
+    return m_impl->getPreferredStepSize();
+}
+
+size_t
+PluginInputDomainAdapter::getPreferredBlockSize() const
+{
+    return m_impl->getPreferredBlockSize();
+}
+
+Plugin::FeatureSet
+PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime timestamp)
+{
+    return m_impl->process(inputBuffers, timestamp);
+}
+
+    PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
+    m_plugin(plugin),
+    m_inputSampleRate(inputSampleRate),
+    m_channels(0),
+    m_blockSize(0),
+    m_freqbuf(0)
+{
+}
+
+PluginInputDomainAdapter::Impl::~Impl()
+{
+    // the adapter will delete the plugin
+
+    if (m_channels > 0) {
+        for (size_t c = 0; c < m_channels; ++c) {
+            delete[] m_freqbuf[c];
+        }
+        delete[] m_freqbuf;
+        delete[] m_ri;
+        delete[] m_ro;
+        delete[] m_io;
+    }
+}
+    
+bool
+PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    if (m_plugin->getInputDomain() == TimeDomain) {
+
+        m_blockSize = blockSize;
+        m_channels = channels;
+
+        return m_plugin->initialise(channels, stepSize, blockSize);
+    }
+
+    if (blockSize < 2) {
+        std::cerr << "ERROR: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: blocksize < 2 not supported" << std::endl;
+        return false;
+    }                
+        
+    if (blockSize & (blockSize-1)) {
+        std::cerr << "ERROR: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: non-power-of-two\nblocksize " << blockSize << " not supported" << std::endl;
+        return false;
+    }
+
+    if (m_channels > 0) {
+        for (size_t c = 0; c < m_channels; ++c) {
+            delete[] m_freqbuf[c];
+        }
+        delete[] m_freqbuf;
+        delete[] m_ri;
+        delete[] m_ro;
+        delete[] m_io;
+    }
+
+    m_blockSize = blockSize;
+    m_channels = channels;
+
+    m_freqbuf = new float *[m_channels];
+    for (size_t c = 0; c < m_channels; ++c) {
+        m_freqbuf[c] = new float[m_blockSize + 2];
+    }
+    m_ri = new double[m_blockSize];
+    m_ro = new double[m_blockSize];
+    m_io = new double[m_blockSize];
+
+    return m_plugin->initialise(channels, stepSize, blockSize);
+}
+
+size_t
+PluginInputDomainAdapter::Impl::getPreferredStepSize() const
+{
+    size_t step = m_plugin->getPreferredStepSize();
+
+    if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
+        step = getPreferredBlockSize() / 2;
+    }
+
+    return step;
+}
+
+size_t
+PluginInputDomainAdapter::Impl::getPreferredBlockSize() const
+{
+    size_t block = m_plugin->getPreferredBlockSize();
+
+    if (m_plugin->getInputDomain() == FrequencyDomain) {
+        if (block == 0) {
+            block = 1024;
+        } else {
+            block = makeBlockSizeAcceptable(block);
+        }
+    }
+
+    return block;
+}
+
+size_t
+PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
+{
+    if (blockSize < 2) {
+
+        std::cerr << "WARNING: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: blocksize < 2 not" << std::endl
+                  << "supported, increasing from " << blockSize << " to 2" << std::endl;
+        blockSize = 2;
+        
+    } else if (blockSize & (blockSize-1)) {
+            
+        // not a power of two, can't handle that with our current fft
+        // implementation
+
+        size_t nearest = blockSize;
+        size_t power = 0;
+        while (nearest > 1) {
+            nearest >>= 1;
+            ++power;
+        }
+        nearest = 1;
+        while (power) {
+            nearest <<= 1;
+            --power;
+        }
+        
+        if (blockSize - nearest > (nearest*2) - blockSize) {
+            nearest = nearest*2;
+        }
+        
+        std::cerr << "WARNING: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: non-power-of-two\nblocksize " << blockSize << " not supported, using blocksize " << nearest << " instead" << std::endl;
+        blockSize = nearest;
+    }
+
+    return blockSize;
+}
+
+// for some visual studii apparently
+#ifndef M_PI
+#define M_PI 3.14159265358979232846
+#endif
+
+Plugin::FeatureSet
+PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
+                                        RealTime timestamp)
+{
+    if (m_plugin->getInputDomain() == TimeDomain) {
+        return m_plugin->process(inputBuffers, timestamp);
+    }
+
+    // The timestamp supplied should be (according to the Vamp::Plugin
+    // spec) the time of the start of the time-domain input block.
+    // However, we want to pass to the plugin an FFT output calculated
+    // from the block of samples _centred_ on that timestamp.
+    // 
+    // We have two options:
+    // 
+    // 1. Buffer the input, calculating the fft of the values at the
+    // passed-in block minus blockSize/2 rather than starting at the
+    // passed-in block.  So each time we call process on the plugin,
+    // we are passing in the same timestamp as was passed to our own
+    // process plugin, but not (the frequency domain representation
+    // of) the same set of samples.  Advantages: avoids confusion in
+    // the host by ensuring the returned values have timestamps
+    // comparable with that passed in to this function (in fact this
+    // is pretty much essential for one-value-per-block outputs);
+    // consistent with hosts such as SV that deal with the
+    // frequency-domain transform themselves.  Disadvantages: means
+    // making the not necessarily correct assumption that the samples
+    // preceding the first official block are all zero (or some other
+    // known value).
+    //
+    // 2. Increase the passed-in timestamps by half the blocksize.  So
+    // when we call process, we are passing in the frequency domain
+    // representation of the same set of samples as passed to us, but
+    // with a different timestamp.  Advantages: simplicity; avoids
+    // iffy assumption mentioned above.  Disadvantages: inconsistency
+    // with SV in cases where stepSize != blockSize/2; potential
+    // confusion arising from returned timestamps being calculated
+    // from the adjusted input timestamps rather than the original
+    // ones (and inaccuracy where the returned timestamp is implied,
+    // as in one-value-per-block).
+    //
+    // Neither way is ideal, but I don't think either is strictly
+    // incorrect either.  I think this is just a case where the same
+    // plugin can legitimately produce differing results from the same
+    // input data, depending on how that data is packaged.
+    // 
+    // We'll go for option 2, adjusting the timestamps.  Note in
+    // particular that this means some results can differ from those
+    // produced by SV.
+
+//    std::cerr << "PluginInputDomainAdapter: sampleRate " << m_inputSampleRate << ", blocksize " << m_blockSize << ", adjusting time from " << timestamp;
+
+    timestamp = timestamp + RealTime::frame2RealTime
+        (m_blockSize/2, int(m_inputSampleRate + 0.5));
+
+//    std::cerr << " to " << timestamp << std::endl;
+
+    for (size_t c = 0; c < m_channels; ++c) {
+
+        for (size_t i = 0; i < m_blockSize; ++i) {
+            // Hanning window
+            m_ri[i] = double(inputBuffers[c][i])
+                * (0.50 - 0.50 * cos((2 * M_PI * i)
+                                     / m_blockSize));
+        }
+
+        for (size_t i = 0; i < m_blockSize/2; ++i) {
+            // FFT shift
+            double value = m_ri[i];
+            m_ri[i] = m_ri[i + m_blockSize/2];
+            m_ri[i + m_blockSize/2] = value;
+        }
+
+        fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
+
+        for (size_t i = 0; i <= m_blockSize/2; ++i) {
+            m_freqbuf[c][i * 2] = m_ro[i];
+            m_freqbuf[c][i * 2 + 1] = m_io[i];
+        }
+    }
+
+    return m_plugin->process(m_freqbuf, timestamp);
+}
+
+void
+PluginInputDomainAdapter::Impl::fft(unsigned int n, bool inverse,
+                                    double *ri, double *ii, double *ro, double *io)
+{
+    if (!ri || !ro || !io) return;
+
+    unsigned int bits;
+    unsigned int i, j, k, m;
+    unsigned int blockSize, blockEnd;
+
+    double tr, ti;
+
+    if (n < 2) return;
+    if (n & (n-1)) return;
+
+    double angle = 2.0 * M_PI;
+    if (inverse) angle = -angle;
+
+    for (i = 0; ; ++i) {
+       if (n & (1 << i)) {
+           bits = i;
+           break;
+       }
+    }
+
+    static unsigned int tableSize = 0;
+    static int *table = 0;
+
+    if (tableSize != n) {
+
+       delete[] table;
+
+       table = new int[n];
+
+       for (i = 0; i < n; ++i) {
+       
+           m = i;
+
+           for (j = k = 0; j < bits; ++j) {
+               k = (k << 1) | (m & 1);
+               m >>= 1;
+           }
+
+           table[i] = k;
+       }
+
+       tableSize = n;
+    }
+
+    if (ii) {
+       for (i = 0; i < n; ++i) {
+           ro[table[i]] = ri[i];
+           io[table[i]] = ii[i];
+       }
+    } else {
+       for (i = 0; i < n; ++i) {
+           ro[table[i]] = ri[i];
+           io[table[i]] = 0.0;
+       }
+    }
+
+    blockEnd = 1;
+
+    for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
+
+       double delta = angle / (double)blockSize;
+       double sm2 = -sin(-2 * delta);
+       double sm1 = -sin(-delta);
+       double cm2 = cos(-2 * delta);
+       double cm1 = cos(-delta);
+       double w = 2 * cm1;
+       double ar[3], ai[3];
+
+       for (i = 0; i < n; i += blockSize) {
+
+           ar[2] = cm2;
+           ar[1] = cm1;
+
+           ai[2] = sm2;
+           ai[1] = sm1;
+
+           for (j = i, m = 0; m < blockEnd; j++, m++) {
+
+               ar[0] = w * ar[1] - ar[2];
+               ar[2] = ar[1];
+               ar[1] = ar[0];
+
+               ai[0] = w * ai[1] - ai[2];
+               ai[2] = ai[1];
+               ai[1] = ai[0];
+
+               k = j + blockEnd;
+               tr = ar[0] * ro[k] - ai[0] * io[k];
+               ti = ar[0] * io[k] + ai[0] * ro[k];
+
+               ro[k] = ro[j] - tr;
+               io[k] = io[j] - ti;
+
+               ro[j] += tr;
+               io[j] += ti;
+           }
+       }
+
+       blockEnd = blockSize;
+    }
+
+    if (inverse) {
+
+       double denom = (double)n;
+
+       for (i = 0; i < n; i++) {
+           ro[i] /= denom;
+           io[i] /= denom;
+       }
+    }
+}
+
+}
+        
+}
+
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.h b/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.h
new file mode 100644 (file)
index 0000000..73da053
--- /dev/null
@@ -0,0 +1,103 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006-2007 Chris Cannam and QMUL.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_INPUT_DOMAIN_ADAPTER_H_
+#define _VAMP_PLUGIN_INPUT_DOMAIN_ADAPTER_H_
+
+#include "PluginWrapper.h"
+
+namespace Vamp {
+
+namespace HostExt {
+
+/**
+ * \class PluginInputDomainAdapter PluginInputDomainAdapter.h <vamp-sdk/hostext/PluginInputDomainAdapter.h>
+ * 
+ * PluginInputDomainAdapter is a Vamp plugin adapter that converts
+ * time-domain input into frequency-domain input for plugins that need
+ * it.  This permits a host to use time- and frequency-domain plugins
+ * interchangeably without needing to handle the conversion itself.
+ *
+ * This adapter uses a basic Hanning windowed FFT that supports
+ * power-of-two block sizes only.  If a frequency domain plugin
+ * requests a non-power-of-two blocksize, the adapter will adjust it
+ * to a nearby power of two instead.  Thus, getPreferredBlockSize()
+ * will always return a power of two if the wrapped plugin is a
+ * frequency domain one.  If the plugin doesn't accept the adjusted
+ * power of two block size, initialise() will fail.
+ *
+ * The adapter provides no way for the host to discover whether the
+ * underlying plugin is actually a time or frequency domain plugin
+ * (except that if the preferred block size is not a power of two, it
+ * must be a time domain plugin).
+ *
+ * The FFT implementation is simple and self-contained, but unlikely
+ * to be the fastest available: a host can usually do better if it
+ * cares enough.
+ *
+ * In every respect other than its input domain handling, the
+ * PluginInputDomainAdapter behaves identically to the plugin that it
+ * wraps.  The wrapped plugin will be deleted when the wrapper is
+ * deleted.
+ *
+ * \note This class was introduced in version 1.1 of the Vamp plugin SDK.
+ */
+
+class PluginInputDomainAdapter : public PluginWrapper
+{
+public:
+    PluginInputDomainAdapter(Plugin *plugin); // I take ownership of plugin
+    virtual ~PluginInputDomainAdapter();
+    
+    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+
+    InputDomain getInputDomain() const;
+
+    size_t getPreferredStepSize() const;
+    size_t getPreferredBlockSize() const;
+
+    FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+protected:
+    class Impl;
+    Impl *m_impl;
+};
+
+}
+
+}
+
+#endif
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp b/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp
new file mode 100644 (file)
index 0000000..cb71fc4
--- /dev/null
@@ -0,0 +1,601 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006-2007 Chris Cannam and QMUL.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "vamp-sdk/PluginHostAdapter.h"
+#include "PluginLoader.h"
+#include "PluginInputDomainAdapter.h"
+#include "PluginChannelAdapter.h"
+
+#include <fstream>
+#include <cctype> // tolower
+
+#ifdef _WIN32
+
+#include <windows.h>
+#include <tchar.h>
+#define PLUGIN_SUFFIX "dll"
+
+#else /* ! _WIN32 */
+
+#include <dirent.h>
+#include <dlfcn.h>
+
+#ifdef __APPLE__
+#define PLUGIN_SUFFIX "dylib"
+#else /* ! __APPLE__ */
+#define PLUGIN_SUFFIX "so"
+#endif /* ! __APPLE__ */
+
+#endif /* ! _WIN32 */
+
+using namespace std;
+
+namespace Vamp {
+       
+namespace HostExt {
+
+class PluginLoader::Impl
+{
+public:
+    Impl();
+    virtual ~Impl();
+
+    PluginKeyList listPlugins();
+
+    Plugin *loadPlugin(PluginKey key,
+                       float inputSampleRate,
+                       int adapterFlags);
+
+    PluginKey composePluginKey(string libraryName, string identifier);
+
+    PluginCategoryHierarchy getPluginCategory(PluginKey key);
+
+    string getLibraryPathForPlugin(PluginKey key);
+
+protected:
+    class PluginDeletionNotifyAdapter : public PluginWrapper {
+    public:
+        PluginDeletionNotifyAdapter(Plugin *plugin, Impl *loader);
+        virtual ~PluginDeletionNotifyAdapter();
+    protected:
+        Impl *m_loader;
+    };
+
+    virtual void pluginDeleted(PluginDeletionNotifyAdapter *adapter);
+
+    map<PluginKey, string> m_pluginLibraryNameMap;
+    bool m_allPluginsEnumerated;
+    void enumeratePlugins(PluginKey forPlugin = "");
+
+    map<PluginKey, PluginCategoryHierarchy> m_taxonomy;
+    void generateTaxonomy();
+
+    map<Plugin *, void *> m_pluginLibraryHandleMap;
+
+    bool decomposePluginKey(PluginKey key,
+                            string &libraryName, string &identifier);
+
+    void *loadLibrary(string path);
+    void unloadLibrary(void *handle);
+    void *lookupInLibrary(void *handle, const char *symbol);
+
+    string splicePath(string a, string b);
+    vector<string> listFiles(string dir, string ext);
+};
+
+PluginLoader *
+PluginLoader::m_instance = 0;
+
+PluginLoader::PluginLoader()
+{
+    m_impl = new Impl();
+}
+
+PluginLoader::~PluginLoader()
+{
+    delete m_impl;
+}
+
+PluginLoader *
+PluginLoader::getInstance()
+{
+    if (!m_instance) m_instance = new PluginLoader();
+    return m_instance;
+}
+
+vector<PluginLoader::PluginKey>
+PluginLoader::listPlugins() 
+{
+    return m_impl->listPlugins();
+}
+
+Plugin *
+PluginLoader::loadPlugin(PluginKey key,
+                         float inputSampleRate,
+                         int adapterFlags)
+{
+    return m_impl->loadPlugin(key, inputSampleRate, adapterFlags);
+}
+
+PluginLoader::PluginKey
+PluginLoader::composePluginKey(string libraryName, string identifier) 
+{
+    return m_impl->composePluginKey(libraryName, identifier);
+}
+
+PluginLoader::PluginCategoryHierarchy
+PluginLoader::getPluginCategory(PluginKey key)
+{
+    return m_impl->getPluginCategory(key);
+}
+
+string
+PluginLoader::getLibraryPathForPlugin(PluginKey key)
+{
+    return m_impl->getLibraryPathForPlugin(key);
+}
+PluginLoader::Impl::Impl() :
+    m_allPluginsEnumerated(false)
+{
+}
+
+PluginLoader::Impl::~Impl()
+{
+}
+
+vector<PluginLoader::PluginKey>
+PluginLoader::Impl::listPlugins() 
+{
+    if (!m_allPluginsEnumerated) enumeratePlugins();
+
+    vector<PluginKey> plugins;
+    for (map<PluginKey, string>::iterator mi = m_pluginLibraryNameMap.begin();
+         mi != m_pluginLibraryNameMap.end(); ++mi) {
+        plugins.push_back(mi->first);
+    }
+
+    return plugins;
+}
+
+void
+PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin)
+{
+    vector<string> path = PluginHostAdapter::getPluginPath();
+
+    string libraryName, identifier;
+    if (forPlugin != "") {
+        if (!decomposePluginKey(forPlugin, libraryName, identifier)) {
+            std::cerr << "WARNING: Vamp::HostExt::PluginLoader: Invalid plugin key \""
+                      << forPlugin << "\" in enumerate" << std::endl;
+            return;
+        }
+    }
+
+    for (size_t i = 0; i < path.size(); ++i) {
+        
+        vector<string> files = listFiles(path[i], PLUGIN_SUFFIX);
+
+        for (vector<string>::iterator fi = files.begin();
+             fi != files.end(); ++fi) {
+            
+            if (libraryName != "") {
+                // libraryName is lowercased and lacking an extension,
+                // as it came from the plugin key
+                string temp = *fi;
+                for (size_t i = 0; i < temp.length(); ++i) {
+                    temp[i] = tolower(temp[i]);
+                }
+                string::size_type pi = temp.find('.');
+                if (pi == string::npos) {
+                    if (libraryName != temp) continue;
+                } else {
+                    if (libraryName != temp.substr(0, pi)) continue;
+                }
+            }
+
+            string fullPath = path[i];
+            fullPath = splicePath(fullPath, *fi);
+            void *handle = loadLibrary(fullPath);
+            if (!handle) continue;
+            
+            VampGetPluginDescriptorFunction fn =
+                (VampGetPluginDescriptorFunction)lookupInLibrary
+                (handle, "vampGetPluginDescriptor");
+            
+            if (!fn) {
+                unloadLibrary(handle);
+                continue;
+            }
+            
+            int index = 0;
+            const VampPluginDescriptor *descriptor = 0;
+            
+            while ((descriptor = fn(VAMP_API_VERSION, index))) {
+                ++index;
+                if (identifier != "") {
+                    if (descriptor->identifier != identifier) continue;
+                }
+                PluginKey key = composePluginKey(*fi, descriptor->identifier);
+//                std::cerr << "enumerate: " << key << " (path: " << fullPath << ")" << std::endl;
+                if (m_pluginLibraryNameMap.find(key) ==
+                    m_pluginLibraryNameMap.end()) {
+                    m_pluginLibraryNameMap[key] = fullPath;
+                }
+            }
+            
+            unloadLibrary(handle);
+        }
+    }
+
+    if (forPlugin == "") m_allPluginsEnumerated = true;
+}
+
+PluginLoader::PluginKey
+PluginLoader::Impl::composePluginKey(string libraryName, string identifier)
+{
+    string basename = libraryName;
+
+    string::size_type li = basename.rfind('/');
+    if (li != string::npos) basename = basename.substr(li + 1);
+
+    li = basename.find('.');
+    if (li != string::npos) basename = basename.substr(0, li);
+
+    for (size_t i = 0; i < basename.length(); ++i) {
+        basename[i] = tolower(basename[i]);
+    }
+
+    return basename + ":" + identifier;
+}
+
+bool
+PluginLoader::Impl::decomposePluginKey(PluginKey key,
+                                       string &libraryName,
+                                       string &identifier)
+{
+    string::size_type ki = key.find(':');
+    if (ki == string::npos) {
+        return false;
+    }
+
+    libraryName = key.substr(0, ki);
+    identifier = key.substr(ki + 1);
+    return true;
+}
+
+PluginLoader::PluginCategoryHierarchy
+PluginLoader::Impl::getPluginCategory(PluginKey plugin)
+{
+    if (m_taxonomy.empty()) generateTaxonomy();
+    if (m_taxonomy.find(plugin) == m_taxonomy.end()) {
+        return PluginCategoryHierarchy();
+    }
+    return m_taxonomy[plugin];
+}
+
+string
+PluginLoader::Impl::getLibraryPathForPlugin(PluginKey plugin)
+{
+    if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
+        if (m_allPluginsEnumerated) return "";
+        enumeratePlugins(plugin);
+    }
+    if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
+        return "";
+    }
+    return m_pluginLibraryNameMap[plugin];
+}    
+
+Plugin *
+PluginLoader::Impl::loadPlugin(PluginKey key,
+                               float inputSampleRate, int adapterFlags)
+{
+    string libname, identifier;
+    if (!decomposePluginKey(key, libname, identifier)) {
+        std::cerr << "Vamp::HostExt::PluginLoader: Invalid plugin key \""
+                  << key << "\" in loadPlugin" << std::endl;
+        return 0;
+    }
+        
+    string fullPath = getLibraryPathForPlugin(key);
+    if (fullPath == "") return 0;
+    
+    void *handle = loadLibrary(fullPath);
+    if (!handle) return 0;
+    
+    VampGetPluginDescriptorFunction fn =
+        (VampGetPluginDescriptorFunction)lookupInLibrary
+        (handle, "vampGetPluginDescriptor");
+
+    if (!fn) {
+        unloadLibrary(handle);
+        return 0;
+    }
+
+    int index = 0;
+    const VampPluginDescriptor *descriptor = 0;
+
+    while ((descriptor = fn(VAMP_API_VERSION, index))) {
+
+        if (string(descriptor->identifier) == identifier) {
+
+            Vamp::PluginHostAdapter *plugin =
+                new Vamp::PluginHostAdapter(descriptor, inputSampleRate);
+
+            Plugin *adapter = new PluginDeletionNotifyAdapter(plugin, this);
+
+            m_pluginLibraryHandleMap[adapter] = handle;
+
+            if (adapterFlags & ADAPT_INPUT_DOMAIN) {
+                if (adapter->getInputDomain() == Plugin::FrequencyDomain) {
+                    adapter = new PluginInputDomainAdapter(adapter);
+                }
+            }
+
+            if (adapterFlags & ADAPT_CHANNEL_COUNT) {
+                adapter = new PluginChannelAdapter(adapter);
+            }
+
+            return adapter;
+        }
+
+        ++index;
+    }
+
+    cerr << "Vamp::HostExt::PluginLoader: Plugin \""
+         << identifier << "\" not found in library \""
+         << fullPath << "\"" << endl;
+
+    return 0;
+}
+
+void
+PluginLoader::Impl::generateTaxonomy()
+{
+//    cerr << "PluginLoader::Impl::generateTaxonomy" << endl;
+
+    vector<string> path = PluginHostAdapter::getPluginPath();
+    string libfragment = "/lib/";
+    vector<string> catpath;
+
+    string suffix = "cat";
+
+    for (vector<string>::iterator i = path.begin();
+         i != path.end(); ++i) {
+
+        // It doesn't matter that we're using literal forward-slash in
+        // this bit, as it's only relevant if the path contains
+        // "/lib/", which is only meaningful and only plausible on
+        // systems with forward-slash delimiters
+        
+        string dir = *i;
+        string::size_type li = dir.find(libfragment);
+
+        if (li != string::npos) {
+            catpath.push_back
+                (dir.substr(0, li)
+                 + "/share/"
+                 + dir.substr(li + libfragment.length()));
+        }
+
+        catpath.push_back(dir);
+    }
+
+    char buffer[1024];
+
+    for (vector<string>::iterator i = catpath.begin();
+         i != catpath.end(); ++i) {
+        
+        vector<string> files = listFiles(*i, suffix);
+
+        for (vector<string>::iterator fi = files.begin();
+             fi != files.end(); ++fi) {
+
+            string filepath = splicePath(*i, *fi);
+            ifstream is(filepath.c_str(), ifstream::in | ifstream::binary);
+
+            if (is.fail()) {
+//                cerr << "failed to open: " << filepath << endl;
+                continue;
+            }
+
+//            cerr << "opened: " << filepath << endl;
+
+            while (!!is.getline(buffer, 1024)) {
+
+                string line(buffer);
+
+//                cerr << "line = " << line << endl;
+
+                string::size_type di = line.find("::");
+                if (di == string::npos) continue;
+
+                string id = line.substr(0, di);
+                string encodedCat = line.substr(di + 2);
+
+                if (id.substr(0, 5) != "vamp:") continue;
+                id = id.substr(5);
+
+                while (encodedCat.length() >= 1 &&
+                       encodedCat[encodedCat.length()-1] == '\r') {
+                    encodedCat = encodedCat.substr(0, encodedCat.length()-1);
+                }
+
+//                cerr << "id = " << id << ", cat = " << encodedCat << endl;
+
+                PluginCategoryHierarchy category;
+                string::size_type ai;
+                while ((ai = encodedCat.find(" > ")) != string::npos) {
+                    category.push_back(encodedCat.substr(0, ai));
+                    encodedCat = encodedCat.substr(ai + 3);
+                }
+                if (encodedCat != "") category.push_back(encodedCat);
+
+                m_taxonomy[id] = category;
+            }
+        }
+    }
+}    
+
+void *
+PluginLoader::Impl::loadLibrary(string path)
+{
+    void *handle = 0;
+#ifdef _WIN32
+    handle = LoadLibrary(path.c_str());
+    if (!handle) {
+        cerr << "Vamp::HostExt::PluginLoader: Unable to load library \""
+             << path << "\"" << endl;
+    }
+#else
+    handle = dlopen(path.c_str(), RTLD_LAZY);
+    if (!handle) {
+        cerr << "Vamp::HostExt::PluginLoader: Unable to load library \""
+             << path << "\": " << dlerror() << endl;
+    }
+#endif
+    return handle;
+}
+
+void
+PluginLoader::Impl::unloadLibrary(void *handle)
+{
+#ifdef _WIN32
+    FreeLibrary((HINSTANCE)handle);
+#else
+    dlclose(handle);
+#endif
+}
+
+void *
+PluginLoader::Impl::lookupInLibrary(void *handle, const char *symbol)
+{
+#ifdef _WIN32
+    return (void *)GetProcAddress((HINSTANCE)handle, symbol);
+#else
+    return (void *)dlsym(handle, symbol);
+#endif
+}
+
+string
+PluginLoader::Impl::splicePath(string a, string b)
+{
+#ifdef _WIN32
+    return a + "\\" + b;
+#else
+    return a + "/" + b;
+#endif
+}
+
+vector<string>
+PluginLoader::Impl::listFiles(string dir, string extension)
+{
+    vector<string> files;
+
+#ifdef _WIN32
+
+    string expression = dir + "\\*." + extension;
+    WIN32_FIND_DATA data;
+    HANDLE fh = FindFirstFile(expression.c_str(), &data);
+    if (fh == INVALID_HANDLE_VALUE) return files;
+
+    bool ok = true;
+    while (ok) {
+        files.push_back(data.cFileName);
+        ok = FindNextFile(fh, &data);
+    }
+
+    FindClose(fh);
+
+#else
+
+    size_t extlen = extension.length();
+    DIR *d = opendir(dir.c_str());
+    if (!d) return files;
+            
+    struct dirent *e = 0;
+    while ((e = readdir(d))) {
+        
+        if (!(e->d_type & DT_REG) || !e->d_name) continue;
+        
+        size_t len = strlen(e->d_name);
+        if (len < extlen + 2 ||
+            e->d_name + len - extlen - 1 != "." + extension) {
+            continue;
+        }
+
+        files.push_back(e->d_name);
+    }
+
+    closedir(d);
+#endif
+
+    return files;
+}
+
+void
+PluginLoader::Impl::pluginDeleted(PluginDeletionNotifyAdapter *adapter)
+{
+    void *handle = m_pluginLibraryHandleMap[adapter];
+    if (handle) unloadLibrary(handle);
+    m_pluginLibraryHandleMap.erase(adapter);
+}
+
+PluginLoader::Impl::PluginDeletionNotifyAdapter::PluginDeletionNotifyAdapter(Plugin *plugin,
+                                                                             Impl *loader) :
+    PluginWrapper(plugin),
+    m_loader(loader)
+{
+}
+
+PluginLoader::Impl::PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter()
+{
+    // We need to delete the plugin before calling pluginDeleted, as
+    // the delete call may require calling through to the descriptor
+    // (for e.g. cleanup) but pluginDeleted may unload the required
+    // library for the call.  To prevent a double deletion when our
+    // parent's destructor runs (after this one), be sure to set
+    // m_plugin to 0 after deletion.
+    delete m_plugin;
+    m_plugin = 0;
+
+    if (m_loader) m_loader->pluginDeleted(this);
+}
+
+}
+
+}
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.h b/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.h
new file mode 100644 (file)
index 0000000..82ae22b
--- /dev/null
@@ -0,0 +1,218 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006-2007 Chris Cannam and QMUL.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_LOADER_H_
+#define _VAMP_PLUGIN_LOADER_H_
+
+#include <vector>
+#include <string>
+#include <map>
+
+#include "PluginWrapper.h"
+
+namespace Vamp {
+
+class Plugin;
+
+namespace HostExt {
+
+/**
+ * \class PluginLoader PluginLoader.h <vamp-sdk/hostext/PluginLoader.h>
+ * 
+ * Vamp::HostExt::PluginLoader is a convenience class for discovering
+ * and loading Vamp plugins using the typical plugin-path, library
+ * naming, and categorisation conventions described in the Vamp SDK
+ * documentation.  This class is intended to greatly simplify the task
+ * of becoming a Vamp plugin host for any C++ application.
+ * 
+ * Hosts are not required by the Vamp specification to use the same
+ * plugin search path and naming conventions as implemented by this
+ * class, and are certainly not required to use this actual class.
+ * But we do strongly recommend it.
+ *
+ * \note This class was introduced in version 1.1 of the Vamp plugin SDK.
+ */
+
+class PluginLoader
+{
+public:
+    /**
+     * Obtain a pointer to the singleton instance of PluginLoader.
+     * Use this to obtain your loader object.
+     */
+    static PluginLoader *getInstance();
+
+    /**
+     * PluginKey is a string type that is used to identify a plugin
+     * uniquely within the scope of "the current system".  It consists
+     * of the lower-cased base name of the plugin library, a colon
+     * separator, and the identifier string for the plugin.  It is
+     * only meaningful in the context of a given plugin path (the one
+     * returned by PluginHostAdapter::getPluginPath()).
+     *
+     * Use composePluginKey() to construct a plugin key from a known
+     * plugin library name and identifier.
+     *
+     * Note: the fact that the library component of the key is
+     * lower-cased implies that library names are matched
+     * case-insensitively by the PluginLoader class, regardless of the
+     * case sensitivity of the underlying filesystem.  (Plugin
+     * identifiers _are_ case sensitive, however.)  Also, it is not
+     * possible to portably extract a working library name from a
+     * plugin key, as the result may fail on case-sensitive
+     * filesystems.  Use getLibraryPathForPlugin() instead.
+     */
+    typedef std::string PluginKey;
+
+    /**
+     * PluginKeyList is a sequence of plugin keys, such as returned by
+     * listPlugins().
+     */
+    typedef std::vector<PluginKey> PluginKeyList;
+
+    /**
+     * PluginCategoryHierarchy is a sequence of general->specific
+     * category names, as may be associated with a single plugin.
+     * This sequence describes the location of a plugin within a
+     * category forest, containing the human-readable names of the
+     * plugin's category tree root, followed by each of the nodes down
+     * to the leaf containing the plugin.
+     *
+     * \see getPluginCategory()
+     */
+    typedef std::vector<std::string> PluginCategoryHierarchy;
+
+    /**
+     * Search for all available Vamp plugins, and return a list of
+     * them in the order in which they were found.
+     */
+    PluginKeyList listPlugins();
+
+    /**
+     * AdapterFlags contains a set of values that may be OR'd together
+     * to indicate in which circumstances PluginLoader should use a
+     * plugin adapter to make a plugin easier to use for a host that
+     * does not want to cater for complex features.
+     *
+     * The available flags are:
+     * 
+     * ADAPT_INPUT_DOMAIN - If the plugin expects frequency domain
+     * input, wrap it in a PluginInputDomainAdapter that automatically
+     * converts the plugin to one that expects time-domain input.
+     * This enables a host to accommodate time- and frequency-domain
+     * plugins without needing to do any conversion itself.
+     *
+     * ADAPT_CHANNEL_COUNT - Wrap the plugin in a PluginChannelAdapter
+     * to handle any mismatch between the number of channels of audio
+     * the plugin can handle and the number available in the host.
+     * This enables a host to use plugins that may require the input
+     * to be mixed down to mono, etc., without having to worry about
+     * doing that itself.
+     *
+     * ADAPT_ALL - Perform all available adaptations, where meaningful.
+     * 
+     * See PluginInputDomainAdapter and PluginChannelAdapter for more
+     * details of the classes that the loader may use if these flags
+     * are set.
+     */
+    enum AdapterFlags {
+        ADAPT_INPUT_DOMAIN  = 0x01,
+        ADAPT_CHANNEL_COUNT = 0x02,
+        ADAPT_ALL           = 0xff
+    };
+
+    /**
+     * Load a Vamp plugin, given its identifying key.  If the plugin
+     * could not be loaded, returns 0.
+     *
+     * The returned plugin should be deleted (using the standard C++
+     * delete keyword) after use.
+     *
+     * \param adapterFlags a bitwise OR of the values in the AdapterFlags
+     * enumeration, indicating under which circumstances an adapter should be
+     * used to wrap the original plugin.  If adapterFlags is 0, no
+     * optional adapters will be used.  Otherwise, the returned plugin
+     * may be of an adapter class type which will behave identically
+     * to the original plugin, apart from any particular features
+     * implemented by the adapter itself.
+     * 
+     * \see AdapterFlags, PluginInputDomainAdapter, PluginChannelAdapter
+     */
+    Plugin *loadPlugin(PluginKey key,
+                       float inputSampleRate,
+                       int adapterFlags = 0);
+
+    /**
+     * Given a Vamp plugin library name and plugin identifier, return
+     * the corresponding plugin key in a form suitable for passing in to
+     * loadPlugin().
+     */
+    PluginKey composePluginKey(std::string libraryName,
+                               std::string identifier);
+
+    /**
+     * Return the category hierarchy for a Vamp plugin, given its
+     * identifying key.
+     *
+     * If the plugin has no category information, return an empty
+     * hierarchy.
+     *
+     * \see PluginCategoryHierarchy
+     */
+    PluginCategoryHierarchy getPluginCategory(PluginKey plugin);
+
+    /**
+     * Return the file path of the dynamic library from which the
+     * given plugin will be loaded (if available).
+     */
+    std::string getLibraryPathForPlugin(PluginKey plugin);
+
+protected:
+    PluginLoader();
+    virtual ~PluginLoader();
+
+    class Impl;
+    Impl *m_impl;
+
+    static PluginLoader *m_instance;
+};
+
+}
+
+}
+
+#endif
+
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.cpp b/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.cpp
new file mode 100644 (file)
index 0000000..dcbdf5b
--- /dev/null
@@ -0,0 +1,201 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006-2007 Chris Cannam and QMUL.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "PluginWrapper.h"
+
+namespace Vamp {
+
+namespace HostExt {
+
+class PluginRateExtractor : public Plugin
+{
+public:
+    PluginRateExtractor() : Plugin(0) { }
+    float getRate() const { return m_inputSampleRate; }
+};
+
+PluginWrapper::PluginWrapper(Plugin *plugin) :
+    Plugin(((PluginRateExtractor *)plugin)->getRate()),
+    m_plugin(plugin)
+{
+}
+
+PluginWrapper::~PluginWrapper()
+{
+    delete m_plugin;
+}
+
+bool
+PluginWrapper::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    return m_plugin->initialise(channels, stepSize, blockSize);
+}
+
+void
+PluginWrapper::reset()
+{
+    m_plugin->reset();
+}
+
+Plugin::InputDomain
+PluginWrapper::getInputDomain() const
+{
+    return m_plugin->getInputDomain();
+}
+
+unsigned int
+PluginWrapper::getVampApiVersion() const
+{
+    return m_plugin->getVampApiVersion();
+}
+
+std::string
+PluginWrapper::getIdentifier() const
+{
+    return m_plugin->getIdentifier();
+}
+
+std::string
+PluginWrapper::getName() const
+{
+    return m_plugin->getName();
+}
+
+std::string
+PluginWrapper::getDescription() const
+{
+    return m_plugin->getDescription();
+}
+
+std::string
+PluginWrapper::getMaker() const
+{
+    return m_plugin->getMaker();
+}
+
+int
+PluginWrapper::getPluginVersion() const
+{
+    return m_plugin->getPluginVersion();
+}
+
+std::string
+PluginWrapper::getCopyright() const
+{
+    return m_plugin->getCopyright();
+}
+
+PluginBase::ParameterList
+PluginWrapper::getParameterDescriptors() const
+{
+    return m_plugin->getParameterDescriptors();
+}
+
+float
+PluginWrapper::getParameter(std::string parameter) const
+{
+    return m_plugin->getParameter(parameter);
+}
+
+void
+PluginWrapper::setParameter(std::string parameter, float value)
+{
+    m_plugin->setParameter(parameter, value);
+}
+
+PluginBase::ProgramList
+PluginWrapper::getPrograms() const
+{
+    return m_plugin->getPrograms();
+}
+
+std::string
+PluginWrapper::getCurrentProgram() const
+{
+    return m_plugin->getCurrentProgram();
+}
+
+void
+PluginWrapper::selectProgram(std::string program)
+{
+    m_plugin->selectProgram(program);
+}
+
+size_t
+PluginWrapper::getPreferredStepSize() const
+{
+    return m_plugin->getPreferredStepSize();
+}
+
+size_t
+PluginWrapper::getPreferredBlockSize() const
+{
+    return m_plugin->getPreferredBlockSize();
+}
+
+size_t
+PluginWrapper::getMinChannelCount() const
+{
+    return m_plugin->getMinChannelCount();
+}
+
+size_t PluginWrapper::getMaxChannelCount() const
+{
+    return m_plugin->getMaxChannelCount();
+}
+
+Plugin::OutputList
+PluginWrapper::getOutputDescriptors() const
+{
+    return m_plugin->getOutputDescriptors();
+}
+
+Plugin::FeatureSet
+PluginWrapper::process(const float *const *inputBuffers, RealTime timestamp)
+{
+    return m_plugin->process(inputBuffers, timestamp);
+}
+
+Plugin::FeatureSet
+PluginWrapper::getRemainingFeatures()
+{
+    return m_plugin->getRemainingFeatures();
+}
+
+}
+
+}
+
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.h b/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.h
new file mode 100644 (file)
index 0000000..d5ec1da
--- /dev/null
@@ -0,0 +1,106 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006-2007 Chris Cannam and QMUL.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_WRAPPER_H_
+#define _VAMP_PLUGIN_WRAPPER_H_
+
+#include <vamp-sdk/Plugin.h>
+
+namespace Vamp {
+
+namespace HostExt {
+
+/**
+ * \class PluginWrapper PluginWrapper.h <vamp-sdk/hostext/PluginWrapper.h>
+ * 
+ * PluginWrapper is a simple base class for adapter plugins.  It takes
+ * a pointer to a "to be wrapped" Vamp plugin on construction, and
+ * provides implementations of all the Vamp plugin methods that simply
+ * delegate through to the wrapped plugin.  A subclass can therefore
+ * override only the methods that are meaningful for the particular
+ * adapter.
+ *
+ * \note This class was introduced in version 1.1 of the Vamp plugin SDK.
+ */
+
+class PluginWrapper : public Plugin
+{
+public:
+    virtual ~PluginWrapper();
+    
+    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+    void reset();
+
+    InputDomain getInputDomain() const;
+
+    unsigned int getVampApiVersion() const;
+    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);
+
+    size_t getPreferredStepSize() const;
+    size_t getPreferredBlockSize() const;
+
+    size_t getMinChannelCount() const;
+    size_t getMaxChannelCount() const;
+
+    OutputList getOutputDescriptors() const;
+
+    FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+    FeatureSet getRemainingFeatures();
+
+protected:
+    PluginWrapper(Plugin *plugin); // I take ownership of plugin
+    Plugin *m_plugin;
+};
+
+}
+
+}
+
+#endif
diff --git a/libs/vamp-sdk/vamp-sdk/libvamp-hostsdk.la.in b/libs/vamp-sdk/vamp-sdk/libvamp-hostsdk.la.in
new file mode 100644 (file)
index 0000000..83362dc
--- /dev/null
@@ -0,0 +1,9 @@
+dlname='%LINK_ABI%'
+library_names='%LIBNAME% %LINK_ABI% %LINK_DEV%'
+old_library='%STATIC%'
+dependency_libs=''
+current=2
+age=0
+revision=0
+installed=yes
+libdir='%LIBS%'
diff --git a/libs/vamp-sdk/vamp-sdk/libvamp-sdk.la.in b/libs/vamp-sdk/vamp-sdk/libvamp-sdk.la.in
new file mode 100644 (file)
index 0000000..1674afe
--- /dev/null
@@ -0,0 +1,9 @@
+dlname='%LINK_ABI%'
+library_names='%LIBNAME% %LINK_ABI% %LINK_DEV%'
+old_library='%STATIC%'
+dependency_libs=''
+current=1
+age=1
+revision=0
+installed=yes
+libdir='%LIBS%'
diff --git a/libs/vamp-sdk/vamp-sdk/vamp-hostsdk.pc.in b/libs/vamp-sdk/vamp-sdk/vamp-hostsdk.pc.in
new file mode 100644 (file)
index 0000000..d5432c0
--- /dev/null
@@ -0,0 +1,10 @@
+prefix=%PREFIX%
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: vamp-hostsdk
+Version: 1.1.0
+Description: Development library for Vamp audio analysis plugin hosts
+Libs: -L${libdir} -lvamp-hostsdk
+Cflags: -I${includedir} 
diff --git a/libs/vamp-sdk/vamp-sdk/vamp-sdk.pc.in b/libs/vamp-sdk/vamp-sdk/vamp-sdk.pc.in
new file mode 100644 (file)
index 0000000..22cea32
--- /dev/null
@@ -0,0 +1,10 @@
+prefix=%PREFIX%
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: vamp-sdk
+Version: 1.1.0
+Description: Development library for Vamp audio analysis plugins
+Libs: -L${libdir} -lvamp-sdk
+Cflags: -I${includedir} 
diff --git a/libs/vamp-sdk/vamp/vamp.h b/libs/vamp-sdk/vamp/vamp.h
new file mode 100644 (file)
index 0000000..4f0145a
--- /dev/null
@@ -0,0 +1,339 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006 Chris Cannam.
+  
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef VAMP_HEADER_INCLUDED
+#define VAMP_HEADER_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** 
+ * Plugin API version.  This is incremented when a change is made that
+ * changes the binary layout of the descriptor records.  When this
+ * happens, there should be a mechanism for retaining compatibility
+ * with older hosts and/or plugins.
+ *
+ * See also the vampApiVersion field in the plugin descriptor, and the
+ * hostApiVersion argument to the vampGetPluginDescriptor function.
+ */
+#define VAMP_API_VERSION 1
+
+/**
+ * C language API for Vamp plugins.
+ * 
+ * This is the formal plugin API for Vamp.  Plugin authors may prefer
+ * to use the C++ classes provided in the Vamp plugin SDK, instead of
+ * using this API directly.  There is an adapter class provided that
+ * makes C++ plugins available using this C API with relatively little
+ * work, and the C++ headers are more thoroughly documented.
+ *
+ * IMPORTANT: The comments in this file summarise the purpose of each
+ * of the declared fields and functions, but do not provide a complete
+ * guide to their permitted values and expected usage.  Please refer
+ * to the C++ headers in the Vamp plugin SDK for further details and
+ * plugin lifecycle documentation.
+ */
+
+typedef struct _VampParameterDescriptor
+{
+    /** Computer-usable name of the parameter. Must not change. [a-zA-Z0-9_] */
+    const char *identifier;
+
+    /** Human-readable name of the parameter. May be translatable. */
+    const char *name;
+
+    /** Human-readable short text about the parameter.  May be translatable. */
+    const char *description;
+
+    /** Human-readable unit of the parameter. */
+    const char *unit;
+
+    /** Minimum value. */
+    float minValue;
+
+    /** Maximum value. */
+    float maxValue;
+
+    /** Default value. Plugin is responsible for setting this on initialise. */
+    float defaultValue;
+
+    /** 1 if parameter values are quantized to a particular resolution. */
+    int isQuantized;
+
+    /** Quantization resolution, if isQuantized. */
+    float quantizeStep;
+
+    /** Human-readable names of the values, if isQuantized.  May be NULL. */
+    const char **valueNames;
+
+} VampParameterDescriptor;
+
+typedef enum
+{
+    /** Each process call returns results aligned with call's block start. */
+    vampOneSamplePerStep,
+
+    /** Returned results are evenly spaced at samplerate specified below. */
+    vampFixedSampleRate,
+
+    /** Returned results have their own individual timestamps. */
+    vampVariableSampleRate
+
+} VampSampleType;
+
+typedef struct _VampOutputDescriptor
+{
+    /** Computer-usable name of the output. Must not change. [a-zA-Z0-9_] */
+    const char *identifier;
+
+    /** Human-readable name of the output. May be translatable. */
+    const char *name;
+
+    /** Human-readable short text about the output. May be translatable. */
+    const char *description;
+
+    /** Human-readable name of the unit of the output. */
+    const char *unit;
+
+    /** 1 if output has equal number of values for each returned result. */
+    int hasFixedBinCount;
+
+    /** Number of values per result, if hasFixedBinCount. */
+    unsigned int binCount;
+
+    /** Names of returned value bins, if hasFixedBinCount.  May be NULL. */
+    const char **binNames;
+
+    /** 1 if each returned value falls within the same fixed min/max range. */
+    int hasKnownExtents;
+    
+    /** Minimum value for a returned result in any bin, if hasKnownExtents. */
+    float minValue;
+
+    /** Maximum value for a returned result in any bin, if hasKnownExtents. */
+    float maxValue;
+
+    /** 1 if returned results are quantized to a particular resolution. */
+    int isQuantized;
+
+    /** Quantization resolution for returned results, if isQuantized. */
+    float quantizeStep;
+
+    /** Time positioning method for returned results (see VampSampleType). */
+    VampSampleType sampleType;
+
+    /** Sample rate of returned results, if sampleType is vampFixedSampleRate.
+       "Resolution" of result, if sampleType is vampVariableSampleRate. */
+    float sampleRate;
+
+} VampOutputDescriptor;
+
+typedef struct _VampFeature
+{
+    /** 1 if the feature has a timestamp (i.e. if vampVariableSampleRate). */
+    int hasTimestamp;
+
+    /** Seconds component of timestamp. */
+    int sec;
+
+    /** Nanoseconds component of timestamp. */
+    int nsec;
+
+    /** Number of values.  Must be binCount if hasFixedBinCount. */
+    unsigned int valueCount;
+
+    /** Values for this returned sample. */
+    float *values;
+
+    /** Label for this returned sample.  May be NULL. */
+    char *label;
+
+} VampFeature;
+
+typedef struct _VampFeatureList
+{
+    /** Number of features in this feature list. */
+    unsigned int featureCount;
+
+    /** Features in this feature list.  May be NULL if featureCount is zero. */
+    VampFeature *features;
+
+} VampFeatureList;
+
+typedef enum
+{
+    vampTimeDomain,
+    vampFrequencyDomain
+
+} VampInputDomain;
+
+typedef void *VampPluginHandle;
+
+typedef struct _VampPluginDescriptor
+{
+    /** API version with which this descriptor is compatible. */
+    unsigned int vampApiVersion;
+
+    /** Computer-usable name of the plugin. Must not change. [a-zA-Z0-9_] */
+    const char *identifier;
+
+    /** Human-readable name of the plugin. May be translatable. */
+    const char *name;
+
+    /** Human-readable short text about the plugin. May be translatable. */
+    const char *description;
+
+    /** Human-readable name of plugin's author or vendor. */
+    const char *maker;
+
+    /** Version number of the plugin. */
+    int pluginVersion;
+
+    /** Human-readable summary of copyright or licensing for plugin. */
+    const char *copyright;
+
+    /** Number of parameter inputs. */
+    unsigned int parameterCount;
+
+    /** Fixed descriptors for parameter inputs. */
+    const VampParameterDescriptor **parameters;
+
+    /** Number of programs. */
+    unsigned int programCount;
+
+    /** Fixed names for programs. */
+    const char **programs;
+
+    /** Preferred input domain for audio input (time or frequency). */
+    VampInputDomain inputDomain;
+
+    /** Create and return a new instance of this plugin. */
+    VampPluginHandle (*instantiate)(const struct _VampPluginDescriptor *,
+                                   float inputSampleRate);
+
+    /** Destroy an instance of this plugin. */
+    void (*cleanup)(VampPluginHandle);
+
+    /** Initialise an instance following parameter configuration. */
+    int (*initialise)(VampPluginHandle,
+                      unsigned int inputChannels,
+                      unsigned int stepSize, 
+                      unsigned int blockSize);
+
+    /** Reset an instance, ready to use again on new input data. */
+    void (*reset)(VampPluginHandle);
+
+    /** Get a parameter value. */
+    float (*getParameter)(VampPluginHandle, int);
+
+    /** Set a parameter value. May only be called before initialise. */
+    void  (*setParameter)(VampPluginHandle, int, float);
+
+    /** Get the current program (if programCount > 0). */
+    unsigned int (*getCurrentProgram)(VampPluginHandle);
+
+    /** Set the current program. May only be called before initialise. */
+    void  (*selectProgram)(VampPluginHandle, unsigned int);
+    
+    /** Get the plugin's preferred processing window increment in samples. */
+    unsigned int (*getPreferredStepSize)(VampPluginHandle);
+
+    /** Get the plugin's preferred processing window size in samples. */
+    unsigned int (*getPreferredBlockSize)(VampPluginHandle);
+
+    /** Get the minimum number of input channels this plugin can handle. */
+    unsigned int (*getMinChannelCount)(VampPluginHandle);
+
+    /** Get the maximum number of input channels this plugin can handle. */
+    unsigned int (*getMaxChannelCount)(VampPluginHandle);
+
+    /** Get the number of feature outputs (distinct sets of results). */
+    unsigned int (*getOutputCount)(VampPluginHandle);
+
+    /** Get a descriptor for a given feature output. Returned pointer
+        is valid only until next call to getOutputDescriptor for this
+        handle, or releaseOutputDescriptor for this descriptor. Host
+        must call releaseOutputDescriptor after use. */
+    VampOutputDescriptor *(*getOutputDescriptor)(VampPluginHandle,
+                                                unsigned int);
+
+    /** Destroy a descriptor for a feature output. */
+    void (*releaseOutputDescriptor)(VampOutputDescriptor *);
+
+    /** Process an input block and return a set of features. Returned
+        pointer is valid only until next call to process,
+        getRemainingFeatures, or cleanup for this handle, or
+        releaseFeatureSet for this feature set. Host must call
+        releaseFeatureSet after use. */
+    VampFeatureList *(*process)(VampPluginHandle,
+                                const float *const *inputBuffers,
+                                int sec,
+                                int nsec);
+
+    /** Return any remaining features at the end of processing. */
+    VampFeatureList *(*getRemainingFeatures)(VampPluginHandle);
+
+    /** Release a feature set returned from process or getRemainingFeatures. */
+    void (*releaseFeatureSet)(VampFeatureList *);
+
+} VampPluginDescriptor;
+
+/** Get the descriptor for a given plugin index in this library.
+    Return NULL if the index is outside the range of valid indices for
+    this plugin library.
+
+    The hostApiVersion argument tells the library code the highest
+    Vamp API version supported by the host.  The function should
+    return a plugin descriptor compatible with the highest API version
+    supported by the library that is no higher than that supported by
+    the host.  Provided the descriptor has the correct vampApiVersion
+    field for its actual compatibility level, the host should be able
+    to do the right thing with it: use it if possible, discard it
+    otherwise.
+*/
+const VampPluginDescriptor *vampGetPluginDescriptor
+    (unsigned int hostApiVersion, unsigned int index);
+
+/** Function pointer type for vampGetPluginDescriptor. */
+typedef const VampPluginDescriptor *(*VampGetPluginDescriptorFunction)
+    (unsigned int, unsigned int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/vamp-sdk/vamp/vamp.pc.in b/libs/vamp-sdk/vamp/vamp.pc.in
new file mode 100644 (file)
index 0000000..82d4dec
--- /dev/null
@@ -0,0 +1,10 @@
+prefix=%PREFIX%
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: vamp
+Version: 1.0
+Description: An API for audio analysis and feature extraction plugins
+Libs: 
+Cflags: -I${includedir}