Remove unused bits from 3rdparty/chromaprint
This commit is contained in:
parent
e1804219dc
commit
665b721236
5
3rdparty/chromaprint/CHANGES.txt
vendored
5
3rdparty/chromaprint/CHANGES.txt
vendored
@ -1,5 +0,0 @@
|
|||||||
Version 0.1 (2010-10-30)
|
|
||||||
========================
|
|
||||||
|
|
||||||
- Initial release.
|
|
||||||
|
|
48
3rdparty/chromaprint/CMakeLists.txt
vendored
48
3rdparty/chromaprint/CMakeLists.txt
vendored
@ -39,29 +39,10 @@ set(BIN_INSTALL_DIR ${EXEC_INSTALL_PREFIX}/bin CACHE PATH "Installation prefix f
|
|||||||
set(LIB_INSTALL_DIR ${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX} CACHE PATH "Installation prefix for object code libraries" FORCE)
|
set(LIB_INSTALL_DIR ${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX} CACHE PATH "Installation prefix for object code libraries" FORCE)
|
||||||
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include CACHE PATH "Installation prefix for C header files" FORCE)
|
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include CACHE PATH "Installation prefix for C header files" FORCE)
|
||||||
|
|
||||||
if(APPLE)
|
|
||||||
option(BUILD_FRAMEWORK "Build an OS X framework" OFF)
|
|
||||||
set(FRAMEWORK_INSTALL_DIR "/Library/Frameworks" CACHE STRING "Directory to install frameworks to.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
|
|
||||||
option(BUILD_EXAMPLES "Build the examples" OFF)
|
|
||||||
option(BUILD_TESTS "Build the test suite" OFF)
|
|
||||||
option(BUILD_TOOLS "Build standard tools" OFF)
|
|
||||||
option(BUILD_EXTRA_TOOLS "Build extra tools (only useful for development of this library)" OFF)
|
|
||||||
|
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||||
endif()
|
endif()
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX AND BUILD_SHARED_LIBS)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden")
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT BUILD_SHARED_LIBS)
|
|
||||||
add_definitions(-DCHROMAPRINT_NODLL)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(WITH_AVFFT "Use FFmpeg for FFT calculations" OFF)
|
option(WITH_AVFFT "Use FFmpeg for FFT calculations" OFF)
|
||||||
option(WITH_FFTW3 "Use FFTW3 for FFT calculations" OFF)
|
option(WITH_FFTW3 "Use FFTW3 for FFT calculations" OFF)
|
||||||
@ -123,36 +104,7 @@ if(WITH_FFTW3)
|
|||||||
message(STATUS "Using FFTW3 for FFT calculations")
|
message(STATUS "Using FFTW3 for FFT calculations")
|
||||||
endif(WITH_FFTW3)
|
endif(WITH_FFTW3)
|
||||||
|
|
||||||
if(NOT APPLE AND NOT BUILD_FRAMEWORK)
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libchromaprint.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libchromaprint.pc)
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libchromaprint.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
||||||
if(BUILD_TOOLS_EXTRA)
|
|
||||||
find_package(PNG REQUIRED)
|
|
||||||
endif(BUILD_TOOLS_EXTRA)
|
|
||||||
|
|
||||||
find_package(Boost COMPONENTS system filesystem)
|
|
||||||
if(BUILD_TOOLS OR BUILD_TOOLS_EXTRA OR BUILD_EXAMPLES)
|
|
||||||
find_package(FFmpeg REQUIRED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(BUILD_EXAMPLES)
|
|
||||||
add_subdirectory(examples)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(BUILD_TOOLS OR BUILD_TOOLS_EXTRA)
|
|
||||||
find_package(Taglib REQUIRED)
|
|
||||||
add_subdirectory(tools)
|
|
||||||
endif(BUILD_TOOLS OR BUILD_TOOLS_EXTRA)
|
|
||||||
|
|
||||||
if(BUILD_TESTS)
|
|
||||||
find_package(Threads)
|
|
||||||
find_package(GTest REQUIRED)
|
|
||||||
add_subdirectory(tests)
|
|
||||||
endif(BUILD_TESTS)
|
|
||||||
|
|
||||||
|
44
3rdparty/chromaprint/NEWS.txt
vendored
44
3rdparty/chromaprint/NEWS.txt
vendored
@ -1,44 +0,0 @@
|
|||||||
Version 0.6 -- December 22, 2011
|
|
||||||
================================
|
|
||||||
|
|
||||||
- Support for 24-bit file formats in fpcalc.
|
|
||||||
- The fpcalc utility now uses 120 seconds of audio data by default.
|
|
||||||
- Python bindings moved to a separate project (pyacoustid).
|
|
||||||
|
|
||||||
Version 0.5 -- October 6, 2011
|
|
||||||
==============================
|
|
||||||
|
|
||||||
- Unicode command line handling in fpcalc.
|
|
||||||
- Fixed a crash in fpcalc when FFmpeg was not able to identify the codec.
|
|
||||||
- Added encode_fingerprint to the Python bindings.
|
|
||||||
|
|
||||||
Version 0.4 -- May 14, 2011
|
|
||||||
===========================
|
|
||||||
|
|
||||||
- Support for building a Mac OS X framework.
|
|
||||||
- Support for building a static library.
|
|
||||||
- Simple C example (fpcalc) that can be used from external applications for
|
|
||||||
fingerprint calculations.
|
|
||||||
|
|
||||||
Version 0.3 -- April 26, 2011
|
|
||||||
=============================
|
|
||||||
|
|
||||||
- Fixed compilation with MSVC 2010.
|
|
||||||
- Added support for calculating FFT using the Accelerate framework on
|
|
||||||
Mac OS X and iOS.
|
|
||||||
- Added Python bindings.
|
|
||||||
|
|
||||||
Version 0.2 -- January 26, 2011
|
|
||||||
===============================
|
|
||||||
|
|
||||||
- New public functions chromaprint_{encode,decode}_fingerprint to
|
|
||||||
encoding/decoding raw fingerprints.
|
|
||||||
- New public function chromaprint_dealloc that should be used for
|
|
||||||
releasing all memory allocated in Chromaprint functions.
|
|
||||||
- Extended fpcollect to allow processing files with MBIDs.
|
|
||||||
|
|
||||||
Version 0.1 -- October 30, 2010
|
|
||||||
===============================
|
|
||||||
|
|
||||||
- Initial release
|
|
||||||
|
|
96
3rdparty/chromaprint/README.txt
vendored
96
3rdparty/chromaprint/README.txt
vendored
@ -1,96 +0,0 @@
|
|||||||
Chromaprint
|
|
||||||
===========
|
|
||||||
|
|
||||||
Dependencies
|
|
||||||
------------
|
|
||||||
|
|
||||||
The library itself only depends on a FFT library, which at the moment can
|
|
||||||
be either FFmpeg [1] (at least r22291, 0.6 is fine), FFTW3 [2] or if you are
|
|
||||||
on iOS or OS X, you can use the Accelerate/vDSP framework. See the next
|
|
||||||
section for details.
|
|
||||||
|
|
||||||
The tools included in the package require FFmpeg (can be older), TagLib [3]
|
|
||||||
and Boost Filesystem [4].
|
|
||||||
|
|
||||||
In order to build the test suite, you will need the Google Test library [5].
|
|
||||||
|
|
||||||
[1] http://www.ffmpeg.org/
|
|
||||||
[2] http://www.fftw.org/
|
|
||||||
[3] http://developer.kde.org/~wheeler/taglib.html
|
|
||||||
[4] http://www.boost.org/
|
|
||||||
[5] http://code.google.com/p/googletest/
|
|
||||||
|
|
||||||
Installing
|
|
||||||
----------
|
|
||||||
|
|
||||||
The most common way to build Chromaprint is like this:
|
|
||||||
|
|
||||||
$ cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=ON .
|
|
||||||
$ make
|
|
||||||
$ sudo make install
|
|
||||||
|
|
||||||
This will build Chromaprint as a shared library and also include the fpcalc
|
|
||||||
utility (which is used by MusicBrainz Picard, for example).
|
|
||||||
|
|
||||||
See below for other options.
|
|
||||||
|
|
||||||
FFT Library
|
|
||||||
-----------
|
|
||||||
|
|
||||||
Chromaprint can use three FFT libraries, FFmpeg, FFTW3 and vDSP. FFmpeg is
|
|
||||||
preffered, as it's a little faster for our purposes and it's LGPL-licensed,
|
|
||||||
so it doesn't impact the license of Chromaprint. The FFT interface was added
|
|
||||||
only recently though, so it might not be available in Linux distributions yet.
|
|
||||||
FFTW3 can be used in this case, but this library is released under the GPL
|
|
||||||
license, which makes also the resulting Chromaprint binary GPL licensed.
|
|
||||||
|
|
||||||
If you run simple `cmake .`, it will try to find both FFmpeg and FFTW3 and
|
|
||||||
select the first one it finds. If you have new FFmpeg installed in a separate
|
|
||||||
location, you can let CMake know using the `FFMPEG_ROOT` option:
|
|
||||||
|
|
||||||
$ cmake -DFFMPEG_ROOT=/path/to/local/ffmpeg/install .
|
|
||||||
|
|
||||||
If you have new FFmpeg installed, but for some reason prefer to use FFTW3, you
|
|
||||||
can use the `WITH_FFTW3` option:
|
|
||||||
|
|
||||||
$ cmake -DWITH_FFTW3=ON .
|
|
||||||
|
|
||||||
There is also a `WITH_AVFFT` option, but the script will select the FFmpeg FFT
|
|
||||||
automatically if it's available, so it shouldn't be necessary to use it.
|
|
||||||
|
|
||||||
If you are on Mac, you can use the standard Accelerate framework with the vDSP
|
|
||||||
library. This requires you to install no external libraries. It will use
|
|
||||||
vDSP by default on OS X (but there still is a `WITH_VDSP` option).
|
|
||||||
|
|
||||||
Unit Tests
|
|
||||||
----------
|
|
||||||
|
|
||||||
The test suite can be built and run using the following commands:
|
|
||||||
|
|
||||||
$ cmake -DBUILD_TESTS=ON .
|
|
||||||
$ make check
|
|
||||||
|
|
||||||
Related Projects
|
|
||||||
----------------
|
|
||||||
|
|
||||||
* pyacoustid - https://github.com/sampsyo/pyacoustid
|
|
||||||
* gst-chromaprint - https://github.com/lalinsky/gst-chromaprint
|
|
||||||
|
|
||||||
Standing on the Shoulder of Giants
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
I've learned a lot while working on this project, which would not be possible
|
|
||||||
without having information from past research. I've read many papers, but the
|
|
||||||
concrete ideas implemented in this library are based on the following papers:
|
|
||||||
|
|
||||||
* Yan Ke, Derek Hoiem, Rahul Sukthankar. Computer Vision for Music
|
|
||||||
Identification, Proceedings of Computer Vision and Pattern Recognition,
|
|
||||||
2005. http://www.cs.cmu.edu/~yke/musicretrieval/
|
|
||||||
|
|
||||||
* Frank Kurth, Meinard Müller. Efficient Index-Based Audio Matching, 2008.
|
|
||||||
http://dx.doi.org/10.1109/TASL.2007.911552
|
|
||||||
|
|
||||||
* Dalwon Jang, Chang D. Yoo, Sunil Lee, Sungwoong Kim, Ton Kalker.
|
|
||||||
Pairwise Boosted Audio Fingerprint, 2009.
|
|
||||||
http://dx.doi.org/10.1109/TIFS.2009.2034452
|
|
||||||
|
|
39
3rdparty/chromaprint/examples/CMakeLists.txt
vendored
39
3rdparty/chromaprint/examples/CMakeLists.txt
vendored
@ -1,39 +0,0 @@
|
|||||||
set(EXTRA_LIBS)
|
|
||||||
if(APPLE)
|
|
||||||
set(EXTRA_LIBS ${EXTRA_LIBS} -lz)
|
|
||||||
endif()
|
|
||||||
if(UNIX)
|
|
||||||
set(EXTRA_LIBS ${EXTRA_LIBS} -lpthread)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES
|
|
||||||
${FFMPEG_LIBAVFORMAT_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVCODEC_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVUTIL_LIBRARIES}
|
|
||||||
${EXTRA_LIBS})
|
|
||||||
check_function_exists(av_audio_convert HAVE_AV_AUDIO_CONVERT)
|
|
||||||
|
|
||||||
if(HAVE_AV_AUDIO_CONVERT)
|
|
||||||
add_definitions(-DHAVE_AV_AUDIO_CONVERT)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include_directories(
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../src
|
|
||||||
${FFMPEG_LIBAVCODEC_INCLUDE_DIRS}
|
|
||||||
${FFMPEG_LIBAVFORMAT_INCLUDE_DIRS}
|
|
||||||
${FFMPEG_LIBAVUTIL_INCLUDE_DIRS}
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(fpcalc fpcalc.c)
|
|
||||||
|
|
||||||
|
|
||||||
target_link_libraries(fpcalc chromaprint
|
|
||||||
${FFMPEG_LIBAVFORMAT_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVCODEC_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVUTIL_LIBRARIES}
|
|
||||||
${EXTRA_LIBS})
|
|
||||||
|
|
||||||
install(TARGETS fpcalc
|
|
||||||
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
|
|
||||||
)
|
|
||||||
|
|
118
3rdparty/chromaprint/examples/ffmpeg/audioconvert.h
vendored
118
3rdparty/chromaprint/examples/ffmpeg/audioconvert.h
vendored
@ -1,118 +0,0 @@
|
|||||||
/*
|
|
||||||
* audio conversion
|
|
||||||
* Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
|
||||||
* Copyright (c) 2008 Peter Ross
|
|
||||||
*
|
|
||||||
* This file is part of FFmpeg.
|
|
||||||
*
|
|
||||||
* FFmpeg is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* FFmpeg is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with FFmpeg; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AVCODEC_AUDIOCONVERT_H
|
|
||||||
#define AVCODEC_AUDIOCONVERT_H
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Audio format conversion routines
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "libavcodec/avcodec.h"
|
|
||||||
#include "samplefmt.h"
|
|
||||||
|
|
||||||
#if FF_API_OLD_SAMPLE_FMT
|
|
||||||
/**
|
|
||||||
* @deprecated Use av_get_sample_fmt_string() instead.
|
|
||||||
*/
|
|
||||||
attribute_deprecated
|
|
||||||
void avcodec_sample_fmt_string(char *buf, int buf_size, int sample_fmt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use av_get_sample_fmt_name() instead.
|
|
||||||
*/
|
|
||||||
attribute_deprecated
|
|
||||||
const char *avcodec_get_sample_fmt_name(int sample_fmt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use av_get_sample_fmt() instead.
|
|
||||||
*/
|
|
||||||
attribute_deprecated
|
|
||||||
enum AVSampleFormat avcodec_get_sample_fmt(const char* name);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if FF_API_OLD_AUDIOCONVERT
|
|
||||||
/**
|
|
||||||
* @deprecated Use av_get_channel_layout() instead.
|
|
||||||
*/
|
|
||||||
attribute_deprecated
|
|
||||||
int64_t avcodec_get_channel_layout(const char *name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use av_get_channel_layout_string() instead.
|
|
||||||
*/
|
|
||||||
attribute_deprecated
|
|
||||||
void avcodec_get_channel_layout_string(char *buf, int buf_size, int nb_channels, int64_t channel_layout);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use av_get_channel_layout_nb_channels() instead.
|
|
||||||
*/
|
|
||||||
attribute_deprecated
|
|
||||||
int avcodec_channel_layout_num_channels(int64_t channel_layout);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Guess the channel layout
|
|
||||||
* @param nb_channels
|
|
||||||
* @param codec_id Codec identifier, or CODEC_ID_NONE if unknown
|
|
||||||
* @param fmt_name Format name, or NULL if unknown
|
|
||||||
* @return Channel layout mask
|
|
||||||
*/
|
|
||||||
uint64_t avcodec_guess_channel_layout(int nb_channels, enum CodecID codec_id, const char *fmt_name);
|
|
||||||
|
|
||||||
struct AVAudioConvert;
|
|
||||||
typedef struct AVAudioConvert AVAudioConvert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an audio sample format converter context
|
|
||||||
* @param out_fmt Output sample format
|
|
||||||
* @param out_channels Number of output channels
|
|
||||||
* @param in_fmt Input sample format
|
|
||||||
* @param in_channels Number of input channels
|
|
||||||
* @param[in] matrix Channel mixing matrix (of dimension in_channel*out_channels). Set to NULL to ignore.
|
|
||||||
* @param flags See AV_CPU_FLAG_xx
|
|
||||||
* @return NULL on error
|
|
||||||
*/
|
|
||||||
AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels,
|
|
||||||
enum AVSampleFormat in_fmt, int in_channels,
|
|
||||||
const float *matrix, int flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free audio sample format converter context
|
|
||||||
*/
|
|
||||||
void av_audio_convert_free(AVAudioConvert *ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert between audio sample formats
|
|
||||||
* @param[in] out array of output buffers for each channel. set to NULL to ignore processing of the given channel.
|
|
||||||
* @param[in] out_stride distance between consecutive output samples (measured in bytes)
|
|
||||||
* @param[in] in array of input buffers for each channel
|
|
||||||
* @param[in] in_stride distance between consecutive input samples (measured in bytes)
|
|
||||||
* @param len length of audio frame size (measured in samples)
|
|
||||||
*/
|
|
||||||
int av_audio_convert(AVAudioConvert *ctx,
|
|
||||||
void * const out[6], const int out_stride[6],
|
|
||||||
const void * const in[6], const int in_stride[6], int len);
|
|
||||||
|
|
||||||
#endif /* AVCODEC_AUDIOCONVERT_H */
|
|
156
3rdparty/chromaprint/examples/ffmpeg/samplefmt.h
vendored
156
3rdparty/chromaprint/examples/ffmpeg/samplefmt.h
vendored
@ -1,156 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of FFmpeg.
|
|
||||||
*
|
|
||||||
* FFmpeg is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* FFmpeg is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with FFmpeg; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AVUTIL_SAMPLEFMT_H
|
|
||||||
#define AVUTIL_SAMPLEFMT_H
|
|
||||||
|
|
||||||
#include "libavutil/avutil.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* all in native-endian format
|
|
||||||
*/
|
|
||||||
enum AVSampleFormat {
|
|
||||||
AV_SAMPLE_FMT_NONE = -1,
|
|
||||||
AV_SAMPLE_FMT_U8, ///< unsigned 8 bits
|
|
||||||
AV_SAMPLE_FMT_S16, ///< signed 16 bits
|
|
||||||
AV_SAMPLE_FMT_S32, ///< signed 32 bits
|
|
||||||
AV_SAMPLE_FMT_FLT, ///< float
|
|
||||||
AV_SAMPLE_FMT_DBL, ///< double
|
|
||||||
|
|
||||||
AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar
|
|
||||||
AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar
|
|
||||||
AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar
|
|
||||||
AV_SAMPLE_FMT_FLTP, ///< float, planar
|
|
||||||
AV_SAMPLE_FMT_DBLP, ///< double, planar
|
|
||||||
|
|
||||||
AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the name of sample_fmt, or NULL if sample_fmt is not
|
|
||||||
* recognized.
|
|
||||||
*/
|
|
||||||
const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a sample format corresponding to name, or AV_SAMPLE_FMT_NONE
|
|
||||||
* on error.
|
|
||||||
*/
|
|
||||||
enum AVSampleFormat av_get_sample_fmt(const char *name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the planar<->packed alternative form of the given sample format, or
|
|
||||||
* AV_SAMPLE_FMT_NONE on error. If the passed sample_fmt is already in the
|
|
||||||
* requested planar/packed format, the format returned is the same as the
|
|
||||||
* input.
|
|
||||||
*/
|
|
||||||
enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a string corresponding to the sample format with
|
|
||||||
* sample_fmt, or a header if sample_fmt is negative.
|
|
||||||
*
|
|
||||||
* @param buf the buffer where to write the string
|
|
||||||
* @param buf_size the size of buf
|
|
||||||
* @param sample_fmt the number of the sample format to print the
|
|
||||||
* corresponding info string, or a negative value to print the
|
|
||||||
* corresponding header.
|
|
||||||
* @return the pointer to the filled buffer or NULL if sample_fmt is
|
|
||||||
* unknown or in case of other errors
|
|
||||||
*/
|
|
||||||
char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt);
|
|
||||||
|
|
||||||
#if FF_API_GET_BITS_PER_SAMPLE_FMT
|
|
||||||
/**
|
|
||||||
* @deprecated Use av_get_bytes_per_sample() instead.
|
|
||||||
*/
|
|
||||||
attribute_deprecated
|
|
||||||
int av_get_bits_per_sample_fmt(enum AVSampleFormat sample_fmt);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return number of bytes per sample.
|
|
||||||
*
|
|
||||||
* @param sample_fmt the sample format
|
|
||||||
* @return number of bytes per sample or zero if unknown for the given
|
|
||||||
* sample format
|
|
||||||
*/
|
|
||||||
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the sample format is planar.
|
|
||||||
*
|
|
||||||
* @param sample_fmt the sample format to inspect
|
|
||||||
* @return 1 if the sample format is planar, 0 if it is interleaved
|
|
||||||
*/
|
|
||||||
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the required buffer size for the given audio parameters.
|
|
||||||
*
|
|
||||||
* @param[out] linesize calculated linesize, may be NULL
|
|
||||||
* @param nb_channels the number of channels
|
|
||||||
* @param nb_samples the number of samples in a single channel
|
|
||||||
* @param sample_fmt the sample format
|
|
||||||
* @return required buffer size, or negative error code on failure
|
|
||||||
*/
|
|
||||||
int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,
|
|
||||||
enum AVSampleFormat sample_fmt, int align);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fill channel data pointers and linesize for samples with sample
|
|
||||||
* format sample_fmt.
|
|
||||||
*
|
|
||||||
* The pointers array is filled with the pointers to the samples data:
|
|
||||||
* for planar, set the start point of each channel's data within the buffer,
|
|
||||||
* for packed, set the start point of the entire buffer only.
|
|
||||||
*
|
|
||||||
* The linesize array is filled with the aligned size of each channel's data
|
|
||||||
* buffer for planar layout, or the aligned size of the buffer for all channels
|
|
||||||
* for packed layout.
|
|
||||||
*
|
|
||||||
* @param[out] audio_data array to be filled with the pointer for each channel
|
|
||||||
* @param[out] linesize calculated linesize
|
|
||||||
* @param buf the pointer to a buffer containing the samples
|
|
||||||
* @param nb_channels the number of channels
|
|
||||||
* @param nb_samples the number of samples in a single channel
|
|
||||||
* @param sample_fmt the sample format
|
|
||||||
* @param align buffer size alignment (1 = no alignment required)
|
|
||||||
* @return 0 on success or a negative error code on failure
|
|
||||||
*/
|
|
||||||
int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, uint8_t *buf,
|
|
||||||
int nb_channels, int nb_samples,
|
|
||||||
enum AVSampleFormat sample_fmt, int align);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate a samples buffer for nb_samples samples, and fill data pointers and
|
|
||||||
* linesize accordingly.
|
|
||||||
* The allocated samples buffer can be freed by using av_freep(&audio_data[0])
|
|
||||||
*
|
|
||||||
* @param[out] audio_data array to be filled with the pointer for each channel
|
|
||||||
* @param[out] linesize aligned size for audio buffer(s)
|
|
||||||
* @param nb_channels number of audio channels
|
|
||||||
* @param nb_samples number of samples per channel
|
|
||||||
* @param align buffer size alignment (1 = no alignment required)
|
|
||||||
* @return 0 on success or a negative error code on failure
|
|
||||||
* @see av_samples_fill_arrays()
|
|
||||||
*/
|
|
||||||
int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels,
|
|
||||||
int nb_samples, enum AVSampleFormat sample_fmt, int align);
|
|
||||||
|
|
||||||
#endif /* AVUTIL_SAMPLEFMT_H */
|
|
303
3rdparty/chromaprint/examples/fpcalc.c
vendored
303
3rdparty/chromaprint/examples/fpcalc.c
vendored
@ -1,303 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <libavcodec/avcodec.h>
|
|
||||||
#include <libavformat/avformat.h>
|
|
||||||
#include <chromaprint.h>
|
|
||||||
#ifdef HAVE_AV_AUDIO_CONVERT
|
|
||||||
#include "ffmpeg/audioconvert.h"
|
|
||||||
#include "ffmpeg/samplefmt.h"
|
|
||||||
#endif
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
||||||
|
|
||||||
#define BUFFER_SIZE (AVCODEC_MAX_AUDIO_FRAME_SIZE * 2)
|
|
||||||
|
|
||||||
int decode_audio_file(ChromaprintContext *chromaprint_ctx, int16_t *buffer1, int16_t *buffer2, const char *file_name, int max_length, int *duration)
|
|
||||||
{
|
|
||||||
int i, ok = 0, remaining, length, consumed, buffer_size, codec_ctx_opened = 0;
|
|
||||||
AVFormatContext *format_ctx = NULL;
|
|
||||||
AVCodecContext *codec_ctx = NULL;
|
|
||||||
AVCodec *codec = NULL;
|
|
||||||
AVStream *stream = NULL;
|
|
||||||
AVPacket packet, packet_temp;
|
|
||||||
#ifdef HAVE_AV_AUDIO_CONVERT
|
|
||||||
AVAudioConvert *convert_ctx = NULL;
|
|
||||||
#endif
|
|
||||||
int16_t *buffer;
|
|
||||||
|
|
||||||
if (av_open_input_file(&format_ctx, file_name, NULL, 0, NULL) != 0) {
|
|
||||||
fprintf(stderr, "ERROR: couldn't open the file\n");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (av_find_stream_info(format_ctx) < 0) {
|
|
||||||
fprintf(stderr, "ERROR: couldn't find stream information in the file\n");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < format_ctx->nb_streams; i++) {
|
|
||||||
codec_ctx = format_ctx->streams[i]->codec;
|
|
||||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52, 64, 0)
|
|
||||||
if (codec_ctx && codec_ctx->codec_type == CODEC_TYPE_AUDIO) {
|
|
||||||
#else
|
|
||||||
if (codec_ctx && codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
|
|
||||||
#endif
|
|
||||||
stream = format_ctx->streams[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!stream) {
|
|
||||||
fprintf(stderr, "ERROR: couldn't find any audio stream in the file\n");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
codec = avcodec_find_decoder(codec_ctx->codec_id);
|
|
||||||
if (!codec) {
|
|
||||||
fprintf(stderr, "ERROR: unknown codec\n");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (avcodec_open(codec_ctx, codec) < 0) {
|
|
||||||
fprintf(stderr, "ERROR: couldn't open the codec\n");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
codec_ctx_opened = 1;
|
|
||||||
|
|
||||||
if (codec_ctx->channels <= 0) {
|
|
||||||
fprintf(stderr, "ERROR: no channels found in the audio stream\n");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (codec_ctx->sample_fmt != SAMPLE_FMT_S16) {
|
|
||||||
#ifdef HAVE_AV_AUDIO_CONVERT
|
|
||||||
convert_ctx = av_audio_convert_alloc(SAMPLE_FMT_S16, codec_ctx->channels,
|
|
||||||
codec_ctx->sample_fmt, codec_ctx->channels, NULL, 0);
|
|
||||||
if (!convert_ctx) {
|
|
||||||
fprintf(stderr, "ERROR: couldn't create sample format converter\n");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "ERROR: unsupported sample format\n");
|
|
||||||
goto done;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
*duration = stream->time_base.num * stream->duration / stream->time_base.den;
|
|
||||||
|
|
||||||
av_init_packet(&packet);
|
|
||||||
av_init_packet(&packet_temp);
|
|
||||||
|
|
||||||
remaining = max_length * codec_ctx->channels * codec_ctx->sample_rate;
|
|
||||||
chromaprint_start(chromaprint_ctx, codec_ctx->sample_rate, codec_ctx->channels);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
if (av_read_frame(format_ctx, &packet) < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
packet_temp.data = packet.data;
|
|
||||||
packet_temp.size = packet.size;
|
|
||||||
|
|
||||||
while (packet_temp.size > 0) {
|
|
||||||
buffer_size = BUFFER_SIZE;
|
|
||||||
#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(52, 25, 0)
|
|
||||||
consumed = avcodec_decode_audio2(codec_ctx,
|
|
||||||
buffer1, &buffer_size, packet_temp.data, packet_temp.size);
|
|
||||||
#else
|
|
||||||
consumed = avcodec_decode_audio3(codec_ctx,
|
|
||||||
buffer1, &buffer_size, &packet_temp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (consumed < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
packet_temp.data += consumed;
|
|
||||||
packet_temp.size -= consumed;
|
|
||||||
|
|
||||||
if (buffer_size <= 0) {
|
|
||||||
if (buffer_size < 0) {
|
|
||||||
fprintf(stderr, "WARNING: size returned from avcodec_decode_audioX is too small\n");
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (buffer_size > BUFFER_SIZE) {
|
|
||||||
fprintf(stderr, "WARNING: size returned from avcodec_decode_audioX is too large\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_AV_AUDIO_CONVERT
|
|
||||||
if (convert_ctx) {
|
|
||||||
const void *ibuf[6] = { buffer1 };
|
|
||||||
void *obuf[6] = { buffer2 };
|
|
||||||
int istride[6] = { av_get_bits_per_sample_format(codec_ctx->sample_fmt) / 8 };
|
|
||||||
int ostride[6] = { 2 };
|
|
||||||
int len = buffer_size / istride[0];
|
|
||||||
if (av_audio_convert(convert_ctx, obuf, ostride, ibuf, istride, len) < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buffer = buffer2;
|
|
||||||
buffer_size = len * ostride[0];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
buffer = buffer1;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
buffer = buffer1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
length = MIN(remaining, buffer_size / 2);
|
|
||||||
if (!chromaprint_feed(chromaprint_ctx, buffer, length)) {
|
|
||||||
fprintf(stderr, "ERROR: fingerprint calculation failed\n");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (max_length) {
|
|
||||||
remaining -= length;
|
|
||||||
if (remaining <= 0) {
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet.data) {
|
|
||||||
av_free_packet(&packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
finish:
|
|
||||||
if (!chromaprint_finish(chromaprint_ctx)) {
|
|
||||||
fprintf(stderr, "ERROR: fingerprint calculation failed\n");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = 1;
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (codec_ctx_opened) {
|
|
||||||
avcodec_close(codec_ctx);
|
|
||||||
}
|
|
||||||
if (format_ctx) {
|
|
||||||
av_close_input_file(format_ctx);
|
|
||||||
}
|
|
||||||
#ifdef HAVE_AV_AUDIO_CONVERT
|
|
||||||
if (convert_ctx) {
|
|
||||||
av_audio_convert_free(convert_ctx);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fpcalc_main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int i, j, max_length = 120, num_file_names = 0, raw = 0, raw_fingerprint_size, duration;
|
|
||||||
int16_t *buffer1, *buffer2;
|
|
||||||
int32_t *raw_fingerprint;
|
|
||||||
char *file_name, *fingerprint, **file_names;
|
|
||||||
ChromaprintContext *chromaprint_ctx;
|
|
||||||
|
|
||||||
file_names = malloc(argc * sizeof(char *));
|
|
||||||
for (i = 1; i < argc; i++) {
|
|
||||||
char *arg = argv[i];
|
|
||||||
if (!strcmp(arg, "-length") && i + 1 < argc) {
|
|
||||||
max_length = atoi(argv[++i]);
|
|
||||||
}
|
|
||||||
else if (!strcmp(arg, "-raw")) {
|
|
||||||
raw = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
file_names[num_file_names++] = argv[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!num_file_names) {
|
|
||||||
printf("usage: %s [OPTIONS] FILE...\n\n", argv[0]);
|
|
||||||
printf("Options:\n");
|
|
||||||
printf(" -length SECS length of the audio data used for fingerprint calculation (default 120)\n");
|
|
||||||
printf(" -raw output the raw uncompressed fingerprint\n");
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
av_register_all();
|
|
||||||
av_log_set_level(AV_LOG_ERROR);
|
|
||||||
|
|
||||||
buffer1 = av_malloc(BUFFER_SIZE + 16);
|
|
||||||
buffer2 = av_malloc(BUFFER_SIZE + 16);
|
|
||||||
chromaprint_ctx = chromaprint_new(CHROMAPRINT_ALGORITHM_DEFAULT);
|
|
||||||
|
|
||||||
for (i = 0; i < num_file_names; i++) {
|
|
||||||
file_name = file_names[i];
|
|
||||||
if (!decode_audio_file(chromaprint_ctx, buffer1, buffer2, file_name, max_length, &duration)) {
|
|
||||||
fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (i > 0) {
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
printf("FILE=%s\n", file_name);
|
|
||||||
printf("DURATION=%d\n", duration);
|
|
||||||
if (raw) {
|
|
||||||
if (!chromaprint_get_raw_fingerprint(chromaprint_ctx, (void **)&raw_fingerprint, &raw_fingerprint_size)) {
|
|
||||||
fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
printf("FINGERPRINT=");
|
|
||||||
for (j = 0; j < raw_fingerprint_size; j++) {
|
|
||||||
printf("%d%s", raw_fingerprint[j], j + 1 < raw_fingerprint_size ? "," : "\n");
|
|
||||||
}
|
|
||||||
chromaprint_dealloc(raw_fingerprint);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!chromaprint_get_fingerprint(chromaprint_ctx, &fingerprint)) {
|
|
||||||
fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
printf("FINGERPRINT=%s\n", fingerprint);
|
|
||||||
chromaprint_dealloc(fingerprint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chromaprint_free(chromaprint_ctx);
|
|
||||||
av_free(buffer1);
|
|
||||||
av_free(buffer2);
|
|
||||||
free(file_names);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
int main(int win32_argc, char **win32_argv)
|
|
||||||
{
|
|
||||||
int i, argc = 0, buffsize = 0, offset = 0;
|
|
||||||
char **utf8_argv, *utf8_argv_ptr;
|
|
||||||
wchar_t **argv;
|
|
||||||
|
|
||||||
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
|
||||||
|
|
||||||
buffsize = 0;
|
|
||||||
for (i = 0; i < argc; i++) {
|
|
||||||
buffsize += WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
utf8_argv = av_mallocz(sizeof(char *) * (argc + 1) + buffsize);
|
|
||||||
utf8_argv_ptr = (char *)utf8_argv + sizeof(char *) * (argc + 1);
|
|
||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
|
||||||
utf8_argv[i] = &utf8_argv_ptr[offset];
|
|
||||||
offset += WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, &utf8_argv_ptr[offset], buffsize - offset, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalFree(argv);
|
|
||||||
|
|
||||||
return fpcalc_main(argc, utf8_argv);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
return fpcalc_main(argc, argv);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
12
3rdparty/chromaprint/libchromaprint.pc.cmake
vendored
12
3rdparty/chromaprint/libchromaprint.pc.cmake
vendored
@ -1,12 +0,0 @@
|
|||||||
prefix=${CMAKE_INSTALL_PREFIX}
|
|
||||||
exec_prefix=${EXEC_INSTALL_PREFIX}
|
|
||||||
libdir=${LIB_INSTALL_DIR}
|
|
||||||
includedir=${INCLUDE_INSTALL_DIR}
|
|
||||||
|
|
||||||
Name: ${PROJECT_NAME}
|
|
||||||
Description: Audio fingerprint library
|
|
||||||
URL: http://wiki.acoustid.org/wiki/Chromaprint
|
|
||||||
Version: ${PROJECT_VERSION}
|
|
||||||
Libs: -L${LIB_INSTALL_DIR} -lchromaprint
|
|
||||||
Cflags: -I${INCLUDE_INSTALL_DIR}
|
|
||||||
|
|
41
3rdparty/chromaprint/tests/CMakeLists.txt
vendored
41
3rdparty/chromaprint/tests/CMakeLists.txt
vendored
@ -1,41 +0,0 @@
|
|||||||
include_directories(
|
|
||||||
${GTEST_INCLUDE_DIRS}
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../src
|
|
||||||
)
|
|
||||||
|
|
||||||
set(tests_SOURCES
|
|
||||||
main.cpp
|
|
||||||
test_api.cpp
|
|
||||||
test_combined_buffer.cpp
|
|
||||||
test_utils.cpp
|
|
||||||
test_quantizer.cpp
|
|
||||||
test_filter_utils.cpp
|
|
||||||
test_integral_image.cpp
|
|
||||||
test_lloyds.cpp
|
|
||||||
test_audio_processor.cpp
|
|
||||||
test_bit_string_reader.cpp
|
|
||||||
test_bit_string_writer.cpp
|
|
||||||
test_chromaprint.cpp
|
|
||||||
test_chroma.cpp
|
|
||||||
test_chroma_filter.cpp
|
|
||||||
test_chroma_resampler.cpp
|
|
||||||
test_fingerprint_compressor.cpp
|
|
||||||
test_fingerprint_decompressor.cpp
|
|
||||||
test_fingerprint_calculator.cpp
|
|
||||||
test_filter.cpp
|
|
||||||
test_silence_remover.cpp
|
|
||||||
test_base64.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(all_tests ${tests_SOURCES})
|
|
||||||
target_link_libraries(all_tests
|
|
||||||
${GTEST_BOTH_LIBRARIES}
|
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
|
||||||
chromaprint_p
|
|
||||||
)
|
|
||||||
|
|
||||||
add_custom_target(check
|
|
||||||
./all_tests $ENV{GTEST_FLAGS}
|
|
||||||
DEPENDS all_tests
|
|
||||||
)
|
|
||||||
|
|
21
3rdparty/chromaprint/tests/audio_buffer.h
vendored
21
3rdparty/chromaprint/tests/audio_buffer.h
vendored
@ -1,21 +0,0 @@
|
|||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include "audio_consumer.h"
|
|
||||||
|
|
||||||
class AudioBuffer : public Chromaprint::AudioConsumer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Consume(short *input, int length)
|
|
||||||
{
|
|
||||||
//cout << "AudioBuffer::Consume(" << length << ")\n";
|
|
||||||
int last_size = m_data.size();
|
|
||||||
//cout << "got " << input[0] << " at index " << last_size << "\n";
|
|
||||||
m_data.resize(last_size + length);
|
|
||||||
std::copy(input, input + length, m_data.begin() + last_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<short> &data() { return m_data; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<short> m_data;
|
|
||||||
};
|
|
BIN
3rdparty/chromaprint/tests/data/test_mono_11025.raw
vendored
BIN
3rdparty/chromaprint/tests/data/test_mono_11025.raw
vendored
Binary file not shown.
BIN
3rdparty/chromaprint/tests/data/test_mono_44100.raw
vendored
BIN
3rdparty/chromaprint/tests/data/test_mono_44100.raw
vendored
Binary file not shown.
BIN
3rdparty/chromaprint/tests/data/test_mono_8000.raw
vendored
BIN
3rdparty/chromaprint/tests/data/test_mono_8000.raw
vendored
Binary file not shown.
Binary file not shown.
8
3rdparty/chromaprint/tests/main.cpp
vendored
8
3rdparty/chromaprint/tests/main.cpp
vendored
@ -1,8 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
|
||||||
return RUN_ALL_TESTS();
|
|
||||||
}
|
|
||||||
|
|
99
3rdparty/chromaprint/tests/test_api.cpp
vendored
99
3rdparty/chromaprint/tests/test_api.cpp
vendored
@ -1,99 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include "chromaprint.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
TEST(API, Test2SilenceFp)
|
|
||||||
{
|
|
||||||
short zeroes[1024];
|
|
||||||
fill(zeroes, zeroes + 1024, 0);
|
|
||||||
|
|
||||||
ChromaprintContext *ctx = chromaprint_new(CHROMAPRINT_ALGORITHM_TEST2);
|
|
||||||
chromaprint_start(ctx, 44100, 1);
|
|
||||||
for (int i = 0; i < 130; i++) {
|
|
||||||
chromaprint_feed(ctx, zeroes, 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *fp;
|
|
||||||
|
|
||||||
chromaprint_finish(ctx);
|
|
||||||
chromaprint_get_fingerprint(ctx, &fp);
|
|
||||||
|
|
||||||
ASSERT_EQ(18, strlen(fp));
|
|
||||||
EXPECT_EQ(string("AQAAA0mUaEkSRZEGAA"), string(fp));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(API, Test2SilenceRawFp)
|
|
||||||
{
|
|
||||||
short zeroes[1024];
|
|
||||||
fill(zeroes, zeroes + 1024, 0);
|
|
||||||
|
|
||||||
ChromaprintContext *ctx = chromaprint_new(CHROMAPRINT_ALGORITHM_TEST2);
|
|
||||||
chromaprint_start(ctx, 44100, 1);
|
|
||||||
for (int i = 0; i < 130; i++) {
|
|
||||||
chromaprint_feed(ctx, zeroes, 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t *fp;
|
|
||||||
int length;
|
|
||||||
|
|
||||||
chromaprint_finish(ctx);
|
|
||||||
chromaprint_get_raw_fingerprint(ctx, (void **)&fp, &length);
|
|
||||||
|
|
||||||
ASSERT_EQ(3, length);
|
|
||||||
EXPECT_EQ(627964279, fp[0]);
|
|
||||||
EXPECT_EQ(627964279, fp[1]);
|
|
||||||
EXPECT_EQ(627964279, fp[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(API, TestEncodeFingerprint)
|
|
||||||
{
|
|
||||||
int32_t fingerprint[] = { 1, 0 };
|
|
||||||
char expected[] = { 55, 0, 0, 2, 65, 0 };
|
|
||||||
|
|
||||||
char *encoded;
|
|
||||||
int encoded_size;
|
|
||||||
chromaprint_encode_fingerprint(fingerprint, 2, 55, (void **)&encoded, &encoded_size, 0);
|
|
||||||
|
|
||||||
ASSERT_EQ(6, encoded_size);
|
|
||||||
for (int i = 0; i < encoded_size; i++) {
|
|
||||||
ASSERT_EQ(expected[i], encoded[i]) << "Different at " << i;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(encoded);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(API, TestEncodeFingerprintBase64)
|
|
||||||
{
|
|
||||||
int32_t fingerprint[] = { 1, 0 };
|
|
||||||
char expected[] = "NwAAAkEA";
|
|
||||||
|
|
||||||
char *encoded;
|
|
||||||
int encoded_size;
|
|
||||||
chromaprint_encode_fingerprint(fingerprint, 2, 55, (void **)&encoded, &encoded_size, 1);
|
|
||||||
|
|
||||||
ASSERT_EQ(8, encoded_size);
|
|
||||||
ASSERT_STREQ(expected, encoded);
|
|
||||||
|
|
||||||
free(encoded);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(API, TestDecodeFingerprint)
|
|
||||||
{
|
|
||||||
char data[] = { 55, 0, 0, 2, 65, 0 };
|
|
||||||
|
|
||||||
int32_t *fingerprint;
|
|
||||||
int size;
|
|
||||||
int algorithm;
|
|
||||||
chromaprint_decode_fingerprint(data, 6, (void **)&fingerprint, &size, &algorithm, 0);
|
|
||||||
|
|
||||||
ASSERT_EQ(2, size);
|
|
||||||
ASSERT_EQ(55, algorithm);
|
|
||||||
ASSERT_EQ(1, fingerprint[0]);
|
|
||||||
ASSERT_EQ(0, fingerprint[1]);
|
|
||||||
}
|
|
||||||
|
|
114
3rdparty/chromaprint/tests/test_audio_processor.cpp
vendored
114
3rdparty/chromaprint/tests/test_audio_processor.cpp
vendored
@ -1,114 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include "test_utils.h"
|
|
||||||
#include "audio_processor.h"
|
|
||||||
#include "audio_buffer.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(AudioProcessor, Accessors)
|
|
||||||
{
|
|
||||||
vector<short> data = LoadAudioFile("data/test_mono_44100.raw");
|
|
||||||
|
|
||||||
boost::scoped_ptr<AudioBuffer> buffer(new AudioBuffer());
|
|
||||||
boost::scoped_ptr<AudioBuffer> buffer2(new AudioBuffer());
|
|
||||||
boost::scoped_ptr<AudioProcessor> processor(new AudioProcessor(44100, buffer.get()));
|
|
||||||
|
|
||||||
EXPECT_EQ(44100, processor->target_sample_rate());
|
|
||||||
EXPECT_EQ(buffer.get(), processor->consumer());
|
|
||||||
|
|
||||||
processor->set_target_sample_rate(11025);
|
|
||||||
EXPECT_EQ(11025, processor->target_sample_rate());
|
|
||||||
|
|
||||||
processor->set_consumer(buffer2.get());
|
|
||||||
EXPECT_EQ(buffer2.get(), processor->consumer());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(AudioProcessor, PassThrough)
|
|
||||||
{
|
|
||||||
vector<short> data = LoadAudioFile("data/test_mono_44100.raw");
|
|
||||||
|
|
||||||
boost::scoped_ptr<AudioBuffer> buffer(new AudioBuffer());
|
|
||||||
boost::scoped_ptr<AudioProcessor> processor(new AudioProcessor(44100, buffer.get()));
|
|
||||||
processor->Reset(44100, 1);
|
|
||||||
processor->Consume(&data[0], data.size());
|
|
||||||
processor->Flush();
|
|
||||||
|
|
||||||
ASSERT_EQ(data.size(), buffer->data().size());
|
|
||||||
for (size_t i = 0; i < data.size(); i++) {
|
|
||||||
ASSERT_EQ(data[i], buffer->data()[i]) << "Signals differ at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(AudioProcessor, StereoToMono)
|
|
||||||
{
|
|
||||||
vector<short> data1 = LoadAudioFile("data/test_stereo_44100.raw");
|
|
||||||
vector<short> data2 = LoadAudioFile("data/test_mono_44100.raw");
|
|
||||||
|
|
||||||
boost::scoped_ptr<AudioBuffer> buffer(new AudioBuffer());
|
|
||||||
boost::scoped_ptr<AudioProcessor> processor(new AudioProcessor(44100, buffer.get()));
|
|
||||||
processor->Reset(44100, 2);
|
|
||||||
processor->Consume(&data1[0], data1.size());
|
|
||||||
processor->Flush();
|
|
||||||
|
|
||||||
ASSERT_EQ(data2.size(), buffer->data().size());
|
|
||||||
for (size_t i = 0; i < data2.size(); i++) {
|
|
||||||
ASSERT_EQ(data2[i], buffer->data()[i]) << "Signals differ at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(AudioProcessor, ResampleMono)
|
|
||||||
{
|
|
||||||
vector<short> data1 = LoadAudioFile("data/test_mono_44100.raw");
|
|
||||||
vector<short> data2 = LoadAudioFile("data/test_mono_11025.raw");
|
|
||||||
|
|
||||||
boost::scoped_ptr<AudioBuffer> buffer(new AudioBuffer());
|
|
||||||
boost::scoped_ptr<AudioProcessor> processor(new AudioProcessor(11025, buffer.get()));
|
|
||||||
processor->Reset(44100, 1);
|
|
||||||
processor->Consume(&data1[0], data1.size());
|
|
||||||
processor->Flush();
|
|
||||||
|
|
||||||
ASSERT_EQ(data2.size(), buffer->data().size());
|
|
||||||
for (size_t i = 0; i < data2.size(); i++) {
|
|
||||||
ASSERT_EQ(data2[i], buffer->data()[i]) << "Signals differ at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(AudioProcessor, ResampleMonoNonInteger)
|
|
||||||
{
|
|
||||||
vector<short> data1 = LoadAudioFile("data/test_mono_44100.raw");
|
|
||||||
vector<short> data2 = LoadAudioFile("data/test_mono_8000.raw");
|
|
||||||
|
|
||||||
boost::scoped_ptr<AudioBuffer> buffer(new AudioBuffer());
|
|
||||||
boost::scoped_ptr<AudioProcessor> processor(new AudioProcessor(8000, buffer.get()));
|
|
||||||
processor->Reset(44100, 1);
|
|
||||||
processor->Consume(&data1[0], data1.size());
|
|
||||||
processor->Flush();
|
|
||||||
|
|
||||||
ASSERT_EQ(data2.size(), buffer->data().size());
|
|
||||||
for (size_t i = 0; i < data2.size(); i++) {
|
|
||||||
ASSERT_EQ(data2[i], buffer->data()[i]) << "Signals differ at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(AudioProcessor, StereoToMonoAndResample)
|
|
||||||
{
|
|
||||||
vector<short> data1 = LoadAudioFile("data/test_stereo_44100.raw");
|
|
||||||
vector<short> data2 = LoadAudioFile("data/test_mono_11025.raw");
|
|
||||||
|
|
||||||
boost::scoped_ptr<AudioBuffer> buffer(new AudioBuffer());
|
|
||||||
boost::scoped_ptr<AudioProcessor> processor(new AudioProcessor(11025, buffer.get()));
|
|
||||||
processor->Reset(44100, 2);
|
|
||||||
processor->Consume(&data1[0], data1.size());
|
|
||||||
processor->Flush();
|
|
||||||
|
|
||||||
ASSERT_EQ(data2.size(), buffer->data().size());
|
|
||||||
for (size_t i = 0; i < data2.size(); i++) {
|
|
||||||
ASSERT_EQ(data2[i], buffer->data()[i]) << "Signals differ at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
56
3rdparty/chromaprint/tests/test_base64.cpp
vendored
56
3rdparty/chromaprint/tests/test_base64.cpp
vendored
@ -1,56 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include "base64.h"
|
|
||||||
#include "test_utils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(Base64, Base64Encode)
|
|
||||||
{
|
|
||||||
ASSERT_EQ("eA", Base64Encode("x"));
|
|
||||||
ASSERT_EQ("eHg", Base64Encode("xx"));
|
|
||||||
ASSERT_EQ("eHh4", Base64Encode("xxx"));
|
|
||||||
ASSERT_EQ("eHh4eA", Base64Encode("xxxx"));
|
|
||||||
ASSERT_EQ("eHh4eHg", Base64Encode("xxxxx"));
|
|
||||||
ASSERT_EQ("eHh4eHh4", Base64Encode("xxxxxx"));
|
|
||||||
ASSERT_EQ("_-4", Base64Encode("\xff\xee"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Base64, Base64Decode)
|
|
||||||
{
|
|
||||||
ASSERT_EQ("x", Base64Decode("eA"));
|
|
||||||
ASSERT_EQ("xx", Base64Decode("eHg"));
|
|
||||||
ASSERT_EQ("xxx", Base64Decode("eHh4"));
|
|
||||||
ASSERT_EQ("xxxx", Base64Decode("eHh4eA"));
|
|
||||||
ASSERT_EQ("xxxxx", Base64Decode("eHh4eHg"));
|
|
||||||
ASSERT_EQ("xxxxxx", Base64Decode("eHh4eHh4"));
|
|
||||||
ASSERT_EQ("\xff\xee", Base64Decode("_-4"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Base64, Base64EncodeLong)
|
|
||||||
{
|
|
||||||
char original[] = {
|
|
||||||
1, 0, 1, 207, 17, 181, 36, 18, 19, 37, 65, 15, 31, 197, 149, 161, 63, 33, 22,
|
|
||||||
60, 141, 27, 202, 35, 184, 47, 254, 227, 135, 135, 11, 58, 139, 208, 65, 127,
|
|
||||||
52, 167, 241, 31, 99, 182, 25, 159, 96, 70, 71, 160, 251, 168, 75, 132, 185,
|
|
||||||
112, 230, 193, 133, 252, 42, 126, 66, 91, 121, 60, 135, 79, 24, 185, 210, 28,
|
|
||||||
199, 133, 255, 240, 113, 101, 67, 199, 23, 225, 181, 160, 121, 140, 67, 123,
|
|
||||||
161, 229, 184, 137, 30, 205, 135, 119, 70, 94, 252, 71, 120, 150
|
|
||||||
};
|
|
||||||
char encoded[] = "AQABzxG1JBITJUEPH8WVoT8hFjyNG8ojuC_-44eHCzqL0EF_NKfxH2O2GZ9gRkeg-6hLhLlw5sGF_Cp-Qlt5PIdPGLnSHMeF__BxZUPHF-G1oHmMQ3uh5biJHs2Hd0Ze_Ed4lg";
|
|
||||||
ASSERT_EQ(encoded, Base64Encode(string(original, NELEMS(original))));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Base64, Base64DecodeLong)
|
|
||||||
{
|
|
||||||
char original[] = {
|
|
||||||
1, 0, 1, 207, 17, 181, 36, 18, 19, 37, 65, 15, 31, 197, 149, 161, 63, 33, 22,
|
|
||||||
60, 141, 27, 202, 35, 184, 47, 254, 227, 135, 135, 11, 58, 139, 208, 65, 127,
|
|
||||||
52, 167, 241, 31, 99, 182, 25, 159, 96, 70, 71, 160, 251, 168, 75, 132, 185,
|
|
||||||
112, 230, 193, 133, 252, 42, 126, 66, 91, 121, 60, 135, 79, 24, 185, 210, 28,
|
|
||||||
199, 133, 255, 240, 113, 101, 67, 199, 23, 225, 181, 160, 121, 140, 67, 123,
|
|
||||||
161, 229, 184, 137, 30, 205, 135, 119, 70, 94, 252, 71, 120, 150
|
|
||||||
};
|
|
||||||
char encoded[] = "AQABzxG1JBITJUEPH8WVoT8hFjyNG8ojuC_-44eHCzqL0EF_NKfxH2O2GZ9gRkeg-6hLhLlw5sGF_Cp-Qlt5PIdPGLnSHMeF__BxZUPHF-G1oHmMQ3uh5biJHs2Hd0Ze_Ed4lg";
|
|
||||||
ASSERT_EQ(string(original, NELEMS(original)), Base64Decode(string(encoded)));
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include "image.h"
|
|
||||||
#include "classifier.h"
|
|
||||||
#include "bit_string_reader.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "test_utils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(BitStringReader, OneByte)
|
|
||||||
{
|
|
||||||
char data[] = { -28 };
|
|
||||||
BitStringReader reader(string(data, 1));
|
|
||||||
|
|
||||||
ASSERT_EQ(0, reader.Read(2));
|
|
||||||
ASSERT_EQ(1, reader.Read(2));
|
|
||||||
ASSERT_EQ(2, reader.Read(2));
|
|
||||||
ASSERT_EQ(3, reader.Read(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(BitStringReader, TwoBytesIncomplete)
|
|
||||||
{
|
|
||||||
char data[] = { -28, 1 };
|
|
||||||
BitStringReader reader(string(data, 2));
|
|
||||||
|
|
||||||
ASSERT_EQ(0, reader.Read(2));
|
|
||||||
ASSERT_EQ(1, reader.Read(2));
|
|
||||||
ASSERT_EQ(2, reader.Read(2));
|
|
||||||
ASSERT_EQ(3, reader.Read(2));
|
|
||||||
ASSERT_EQ(1, reader.Read(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(BitStringReader, TwoBytesSplit)
|
|
||||||
{
|
|
||||||
char data[] = { -120, 6 };
|
|
||||||
BitStringReader reader(string(data, 2));
|
|
||||||
|
|
||||||
ASSERT_EQ(0, reader.Read(3));
|
|
||||||
ASSERT_EQ(1, reader.Read(3));
|
|
||||||
ASSERT_EQ(2, reader.Read(3));
|
|
||||||
ASSERT_EQ(3, reader.Read(3));
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include "image.h"
|
|
||||||
#include "classifier.h"
|
|
||||||
#include "bit_string_writer.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "test_utils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(BitStringWriter, OneByte)
|
|
||||||
{
|
|
||||||
BitStringWriter writer;
|
|
||||||
writer.Write(0, 2);
|
|
||||||
writer.Write(1, 2);
|
|
||||||
writer.Write(2, 2);
|
|
||||||
writer.Write(3, 2);
|
|
||||||
writer.Flush();
|
|
||||||
|
|
||||||
char expected[] = { -28 };
|
|
||||||
CheckString(writer.value(), expected, sizeof(expected)/sizeof(expected[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(BitStringWriter, TwoBytesIncomplete)
|
|
||||||
{
|
|
||||||
BitStringWriter writer;
|
|
||||||
writer.Write(0, 2);
|
|
||||||
writer.Write(1, 2);
|
|
||||||
writer.Write(2, 2);
|
|
||||||
writer.Write(3, 2);
|
|
||||||
writer.Write(1, 2);
|
|
||||||
writer.Flush();
|
|
||||||
|
|
||||||
char expected[] = { -28, 1 };
|
|
||||||
CheckString(writer.value(), expected, sizeof(expected)/sizeof(expected[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(BitStringWriter, TwoBytesSplit)
|
|
||||||
{
|
|
||||||
BitStringWriter writer;
|
|
||||||
writer.Write(0, 3);
|
|
||||||
writer.Write(1, 3);
|
|
||||||
writer.Write(2, 3);
|
|
||||||
writer.Write(3, 3);
|
|
||||||
writer.Flush();
|
|
||||||
|
|
||||||
char expected[] = { -120, 6 };
|
|
||||||
CheckString(writer.value(), expected, sizeof(expected)/sizeof(expected[0]));
|
|
||||||
}
|
|
125
3rdparty/chromaprint/tests/test_chroma.cpp
vendored
125
3rdparty/chromaprint/tests/test_chroma.cpp
vendored
@ -1,125 +0,0 @@
|
|||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include "fft_frame.h"
|
|
||||||
#include "chroma.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
class FeatureVectorBuffer : public FeatureVectorConsumer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Consume(std::vector<double> &features)
|
|
||||||
{
|
|
||||||
m_features = features;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<double> m_features;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST(Chroma, NormalA) {
|
|
||||||
FeatureVectorBuffer buffer;
|
|
||||||
Chroma chroma(10, 510, 256, 1000, &buffer);
|
|
||||||
FFTFrame frame(128);
|
|
||||||
std::fill(frame.data(), frame.data() + frame.size(), 0.0);
|
|
||||||
frame.data()[113] = 1.0;
|
|
||||||
chroma.Consume(frame);
|
|
||||||
ASSERT_EQ(12, buffer.m_features.size());
|
|
||||||
double expected_features[12] = {
|
|
||||||
1.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
|
||||||
};
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
EXPECT_NEAR(expected_features[i], buffer.m_features[i], 0.0001) << "Different value at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Chroma, NormalGSharp) {
|
|
||||||
FeatureVectorBuffer buffer;
|
|
||||||
Chroma chroma(10, 510, 256, 1000, &buffer);
|
|
||||||
FFTFrame frame(128);
|
|
||||||
std::fill(frame.data(), frame.data() + frame.size(), 0.0);
|
|
||||||
frame.data()[112] = 1.0;
|
|
||||||
chroma.Consume(frame);
|
|
||||||
ASSERT_EQ(12, buffer.m_features.size());
|
|
||||||
double expected_features[12] = {
|
|
||||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
|
|
||||||
};
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
EXPECT_NEAR(expected_features[i], buffer.m_features[i], 0.0001) << "Different value at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Chroma, NormalB) {
|
|
||||||
FeatureVectorBuffer buffer;
|
|
||||||
Chroma chroma(10, 510, 256, 1000, &buffer);
|
|
||||||
FFTFrame frame(128);
|
|
||||||
std::fill(frame.data(), frame.data() + frame.size(), 0.0);
|
|
||||||
frame.data()[64] = 1.0; // 250 Hz
|
|
||||||
chroma.Consume(frame);
|
|
||||||
ASSERT_EQ(12, buffer.m_features.size());
|
|
||||||
double expected_features[12] = {
|
|
||||||
0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
|
||||||
};
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
EXPECT_NEAR(expected_features[i], buffer.m_features[i], 0.0001) << "Different value at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Chroma, InterpolatedB) {
|
|
||||||
FeatureVectorBuffer buffer;
|
|
||||||
Chroma chroma(10, 510, 256, 1000, &buffer);
|
|
||||||
chroma.set_interpolate(true);
|
|
||||||
FFTFrame frame(128);
|
|
||||||
std::fill(frame.data(), frame.data() + frame.size(), 0.0);
|
|
||||||
frame.data()[64] = 1.0;
|
|
||||||
chroma.Consume(frame);
|
|
||||||
ASSERT_EQ(12, buffer.m_features.size());
|
|
||||||
double expected_features[12] = {
|
|
||||||
0.0, 0.286905, 0.713095, 0.0, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
|
||||||
};
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
EXPECT_NEAR(expected_features[i], buffer.m_features[i], 0.0001) << "Different value at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Chroma, InterpolatedA) {
|
|
||||||
FeatureVectorBuffer buffer;
|
|
||||||
Chroma chroma(10, 510, 256, 1000, &buffer);
|
|
||||||
chroma.set_interpolate(true);
|
|
||||||
FFTFrame frame(128);
|
|
||||||
std::fill(frame.data(), frame.data() + frame.size(), 0.0);
|
|
||||||
frame.data()[113] = 1.0;
|
|
||||||
chroma.Consume(frame);
|
|
||||||
ASSERT_EQ(12, buffer.m_features.size());
|
|
||||||
double expected_features[12] = {
|
|
||||||
0.555242, 0.0, 0.0, 0.0, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.444758,
|
|
||||||
};
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
EXPECT_NEAR(expected_features[i], buffer.m_features[i], 0.0001) << "Different value at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Chroma, InterpolatedGSharp) {
|
|
||||||
FeatureVectorBuffer buffer;
|
|
||||||
Chroma chroma(10, 510, 256, 1000, &buffer);
|
|
||||||
chroma.set_interpolate(true);
|
|
||||||
FFTFrame frame(128);
|
|
||||||
std::fill(frame.data(), frame.data() + frame.size(), 0.0);
|
|
||||||
frame.data()[112] = 1.0;
|
|
||||||
chroma.Consume(frame);
|
|
||||||
ASSERT_EQ(12, buffer.m_features.size());
|
|
||||||
double expected_features[12] = {
|
|
||||||
0.401354, 0.0, 0.0, 0.0, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.598646,
|
|
||||||
};
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
EXPECT_NEAR(expected_features[i], buffer.m_features[i], 0.0001) << "Different value at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include "image.h"
|
|
||||||
#include "image_builder.h"
|
|
||||||
#include "chroma_filter.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(ChromaFilter, Blur2) {
|
|
||||||
double coefficients[] = { 0.5, 0.5 };
|
|
||||||
Image image(12);
|
|
||||||
ImageBuilder builder(&image);
|
|
||||||
ChromaFilter filter(coefficients, 2, &builder);
|
|
||||||
double d1[] = { 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
double d2[] = { 1.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
double d3[] = { 2.0, 7.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
std::vector<double> v1(d1, d1 + 12);
|
|
||||||
std::vector<double> v2(d2, d2 + 12);
|
|
||||||
std::vector<double> v3(d3, d3 + 12);
|
|
||||||
filter.Consume(v1);
|
|
||||||
filter.Consume(v2);
|
|
||||||
filter.Consume(v3);
|
|
||||||
ASSERT_EQ(2, image.NumRows());
|
|
||||||
EXPECT_EQ(0.5, image[0][0]);
|
|
||||||
EXPECT_EQ(1.5, image[1][0]);
|
|
||||||
EXPECT_EQ(5.5, image[0][1]);
|
|
||||||
EXPECT_EQ(6.5, image[1][1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(ChromaFilter, Blur3) {
|
|
||||||
double coefficients[] = { 0.5, 0.7, 0.5 };
|
|
||||||
Image image(12);
|
|
||||||
ImageBuilder builder(&image);
|
|
||||||
ChromaFilter filter(coefficients, 3, &builder);
|
|
||||||
double d1[] = { 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
double d2[] = { 1.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
double d3[] = { 2.0, 7.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
double d4[] = { 3.0, 8.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
std::vector<double> v1(d1, d1 + 12);
|
|
||||||
std::vector<double> v2(d2, d2 + 12);
|
|
||||||
std::vector<double> v3(d3, d3 + 12);
|
|
||||||
std::vector<double> v4(d4, d4 + 12);
|
|
||||||
filter.Consume(v1);
|
|
||||||
filter.Consume(v2);
|
|
||||||
filter.Consume(v3);
|
|
||||||
filter.Consume(v4);
|
|
||||||
ASSERT_EQ(2, image.NumRows());
|
|
||||||
EXPECT_FLOAT_EQ(1.7, image[0][0]);
|
|
||||||
EXPECT_FLOAT_EQ(3.399999999999999, image[1][0]);
|
|
||||||
EXPECT_FLOAT_EQ(10.199999999999999, image[0][1]);
|
|
||||||
EXPECT_FLOAT_EQ(11.899999999999999, image[1][1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(ChromaFilter, Diff) {
|
|
||||||
double coefficients[] = { 1.0, -1.0 };
|
|
||||||
Image image(12);
|
|
||||||
ImageBuilder builder(&image);
|
|
||||||
ChromaFilter filter(coefficients, 2, &builder);
|
|
||||||
double d1[] = { 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
double d2[] = { 1.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
double d3[] = { 2.0, 7.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
std::vector<double> v1(d1, d1 + 12);
|
|
||||||
std::vector<double> v2(d2, d2 + 12);
|
|
||||||
std::vector<double> v3(d3, d3 + 12);
|
|
||||||
filter.Consume(v1);
|
|
||||||
filter.Consume(v2);
|
|
||||||
filter.Consume(v3);
|
|
||||||
ASSERT_EQ(2, image.NumRows());
|
|
||||||
EXPECT_EQ(-1.0, image[0][0]);
|
|
||||||
EXPECT_EQ(-1.0, image[1][0]);
|
|
||||||
EXPECT_EQ(-1.0, image[0][1]);
|
|
||||||
EXPECT_EQ(-1.0, image[1][1]);
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include "image.h"
|
|
||||||
#include "image_builder.h"
|
|
||||||
#include "chroma_resampler.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(ChromaResampler, Test1) {
|
|
||||||
Image image(12);
|
|
||||||
ImageBuilder builder(&image);
|
|
||||||
ChromaResampler resampler(2, &builder);
|
|
||||||
double d1[] = { 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
double d2[] = { 1.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
double d3[] = { 2.0, 7.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
std::vector<double> v1(d1, d1 + 12);
|
|
||||||
std::vector<double> v2(d2, d2 + 12);
|
|
||||||
std::vector<double> v3(d3, d3 + 12);
|
|
||||||
resampler.Consume(v1);
|
|
||||||
resampler.Consume(v2);
|
|
||||||
resampler.Consume(v3);
|
|
||||||
ASSERT_EQ(1, image.NumRows());
|
|
||||||
EXPECT_EQ(0.5, image[0][0]);
|
|
||||||
EXPECT_EQ(5.5, image[0][1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(ChromaResampler, Test2) {
|
|
||||||
Image image(12);
|
|
||||||
ImageBuilder builder(&image);
|
|
||||||
ChromaResampler resampler(2, &builder);
|
|
||||||
double d1[] = { 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
double d2[] = { 1.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
double d3[] = { 2.0, 7.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
double d4[] = { 3.0, 8.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
std::vector<double> v1(d1, d1 + 12);
|
|
||||||
std::vector<double> v2(d2, d2 + 12);
|
|
||||||
std::vector<double> v3(d3, d3 + 12);
|
|
||||||
std::vector<double> v4(d4, d4 + 12);
|
|
||||||
resampler.Consume(v1);
|
|
||||||
resampler.Consume(v2);
|
|
||||||
resampler.Consume(v3);
|
|
||||||
resampler.Consume(v4);
|
|
||||||
ASSERT_EQ(2, image.NumRows());
|
|
||||||
EXPECT_EQ(0.5, image[0][0]);
|
|
||||||
EXPECT_EQ(5.5, image[0][1]);
|
|
||||||
EXPECT_EQ(2.5, image[1][0]);
|
|
||||||
EXPECT_EQ(7.5, image[1][1]);
|
|
||||||
}
|
|
67
3rdparty/chromaprint/tests/test_chromaprint.cpp
vendored
67
3rdparty/chromaprint/tests/test_chromaprint.cpp
vendored
@ -1,67 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include "audio_processor.h"
|
|
||||||
#include "test_utils.h"
|
|
||||||
#include "audio_processor.h"
|
|
||||||
#include "chroma.h"
|
|
||||||
#include "chroma_normalizer.h"
|
|
||||||
#include "chroma_resampler.h"
|
|
||||||
#include "fft.h"
|
|
||||||
#include "audio_processor.h"
|
|
||||||
#include "image.h"
|
|
||||||
#include "image_builder.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
static const int SAMPLE_RATE = 11025;
|
|
||||||
static const int FRAME_SIZE = 4096;
|
|
||||||
static const int OVERLAP = FRAME_SIZE - FRAME_SIZE / 3;// 2720;
|
|
||||||
static const int MIN_FREQ = 28;
|
|
||||||
static const int MAX_FREQ = 3520;
|
|
||||||
static const int MAX_FILTER_WIDTH = 20;
|
|
||||||
|
|
||||||
TEST(Chromaprint, BasicImage)
|
|
||||||
{
|
|
||||||
vector<short> data = LoadAudioFile("data/test_stereo_44100.raw");
|
|
||||||
|
|
||||||
Chromaprint::Image image(12);
|
|
||||||
Chromaprint::ImageBuilder image_builder(&image);
|
|
||||||
Chromaprint::ChromaNormalizer chroma_normalizer(&image_builder);
|
|
||||||
Chromaprint::Chroma chroma(MIN_FREQ, MAX_FREQ, FRAME_SIZE, SAMPLE_RATE, &chroma_normalizer);
|
|
||||||
Chromaprint::FFT fft(FRAME_SIZE, OVERLAP, &chroma);
|
|
||||||
Chromaprint::AudioProcessor processor(SAMPLE_RATE, &fft);
|
|
||||||
|
|
||||||
processor.Reset(44100, 2);
|
|
||||||
processor.Consume(&data[0], data.size());
|
|
||||||
processor.Flush();
|
|
||||||
|
|
||||||
double chromagram[][12] = {
|
|
||||||
{ 0.155444, 0.268618, 0.474445, 0.159887, 0.1761, 0.423511, 0.178933, 0.34433, 0.360958, 0.30421, 0.200217, 0.17072 },
|
|
||||||
{ 0.159809, 0.238675, 0.286526, 0.166119, 0.225144, 0.449236, 0.162444, 0.371875, 0.259626, 0.483961, 0.24491, 0.17034 },
|
|
||||||
{ 0.156518, 0.271503, 0.256073, 0.152689, 0.174664, 0.52585, 0.141517, 0.253695, 0.293199, 0.332114, 0.442906, 0.170459 },
|
|
||||||
{ 0.154183, 0.38592, 0.497451, 0.203884, 0.362608, 0.355691, 0.125349, 0.146766, 0.315143, 0.318133, 0.172547, 0.112769 },
|
|
||||||
{ 0.201289, 0.42033, 0.509467, 0.259247, 0.322772, 0.325837, 0.140072, 0.177756, 0.320356, 0.228176, 0.148994, 0.132588 },
|
|
||||||
{ 0.187921, 0.302804, 0.46976, 0.302809, 0.183035, 0.228691, 0.206216, 0.35174, 0.308208, 0.233234, 0.316017, 0.243563 },
|
|
||||||
{ 0.213539, 0.240346, 0.308664, 0.250704, 0.204879, 0.365022, 0.241966, 0.312579, 0.361886, 0.277293, 0.338944, 0.290351 },
|
|
||||||
{ 0.227784, 0.252841, 0.295752, 0.265796, 0.227973, 0.451155, 0.219418, 0.272508, 0.376082, 0.312717, 0.285395, 0.165745 },
|
|
||||||
{ 0.168662, 0.180795, 0.264397, 0.225101, 0.562332, 0.33243, 0.236684, 0.199847, 0.409727, 0.247569, 0.21153, 0.147286 },
|
|
||||||
{ 0.0491864, 0.0503369, 0.130942, 0.0505802, 0.0694409, 0.0303877, 0.0389852, 0.674067, 0.712933, 0.05762, 0.0245158, 0.0389336 },
|
|
||||||
{ 0.0814379, 0.0312366, 0.240546, 0.134609, 0.063374, 0.0466124, 0.0752175, 0.657041, 0.680085, 0.0720311, 0.0249404, 0.0673359 },
|
|
||||||
{ 0.139331, 0.0173442, 0.49035, 0.287237, 0.0453947, 0.0873279, 0.15423, 0.447475, 0.621502, 0.127166, 0.0355933, 0.141163 },
|
|
||||||
{ 0.115417, 0.0132515, 0.356601, 0.245902, 0.0283943, 0.0588233, 0.117077, 0.499376, 0.715366, 0.100398, 0.0281382, 0.0943482 },
|
|
||||||
{ 0.047297, 0.0065354, 0.181074, 0.121455, 0.0135504, 0.030693, 0.0613105, 0.631705, 0.73548, 0.0550565, 0.0128093, 0.0460393 },
|
|
||||||
};
|
|
||||||
|
|
||||||
ASSERT_EQ(14, image.NumRows()) << "Numbers of rows doesn't match";
|
|
||||||
for (int y = 0; y < 14; y++) {
|
|
||||||
for (int x = 0; x < 12; x++) {
|
|
||||||
EXPECT_NEAR(chromagram[y][x], image[y][x], 1e-5)
|
|
||||||
<< "Image not equal at (" << x << ", " << y << ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,95 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include "combined_buffer.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(CombinedBuffer, Size) {
|
|
||||||
short buffer1[] = { 1, 2, 3, 4, 5 };
|
|
||||||
short buffer2[] = { 6, 7, 8 };
|
|
||||||
CombinedBuffer<short> buffer(buffer1, 5, buffer2, 3);
|
|
||||||
EXPECT_EQ(8, buffer.Size());
|
|
||||||
buffer.Shift(1);
|
|
||||||
EXPECT_EQ(7, buffer.Size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CombinedBuffer, AccessElements) {
|
|
||||||
short buffer1[] = { 1, 2, 3, 4, 5 };
|
|
||||||
short buffer2[] = { 6, 7, 8 };
|
|
||||||
CombinedBuffer<short> buffer(buffer1, 5, buffer2, 3);
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
EXPECT_EQ(1 + i, buffer[i]);
|
|
||||||
}
|
|
||||||
buffer.Shift(1);
|
|
||||||
for (int i = 0; i < 7; i++) {
|
|
||||||
EXPECT_EQ(2 + i, buffer[i]);
|
|
||||||
}
|
|
||||||
buffer.Shift(5);
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
EXPECT_EQ(7 + i, buffer[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CombinedBuffer, AccessElementsViaIterator) {
|
|
||||||
short buffer1[] = { 1, 2, 3, 4, 5 };
|
|
||||||
short buffer2[] = { 6, 7, 8 };
|
|
||||||
CombinedBuffer<short> buffer(buffer1, 5, buffer2, 3);
|
|
||||||
CombinedBuffer<short>::Iterator iter = buffer.Begin();
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
EXPECT_EQ(1 + i, *iter);
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
EXPECT_TRUE(buffer.End() == iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CombinedBuffer, AccessElementsViaIteratorAfterShift) {
|
|
||||||
short buffer1[] = { 1, 2, 3, 4, 5 };
|
|
||||||
short buffer2[] = { 6, 7, 8 };
|
|
||||||
CombinedBuffer<short> buffer(buffer1, 5, buffer2, 3);
|
|
||||||
buffer.Shift(6);
|
|
||||||
CombinedBuffer<short>::Iterator iter = buffer.Begin();
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
EXPECT_EQ(7 + i, *iter);
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
EXPECT_TRUE(buffer.End() == iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CombinedBuffer, CopyUsingStlAlgorithms) {
|
|
||||||
short buffer1[] = { 1, 2, 3, 4, 5 };
|
|
||||||
short buffer2[] = { 6, 7, 8 };
|
|
||||||
short tmp[10];
|
|
||||||
CombinedBuffer<short> buffer(buffer1, 5, buffer2, 3);
|
|
||||||
fill(tmp, tmp + 10, 0);
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
EXPECT_EQ(0, tmp[i]);
|
|
||||||
}
|
|
||||||
copy(buffer.Begin(), buffer.End(), tmp);
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
EXPECT_EQ(1 + i, tmp[i]);
|
|
||||||
}
|
|
||||||
for (int i = 8; i < 10; i++) {
|
|
||||||
EXPECT_EQ(0, tmp[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(CombinedBuffer, CopyUsingStlAlgorithmsAfterShift) {
|
|
||||||
short buffer1[] = { 1, 2, 3, 4, 5 };
|
|
||||||
short buffer2[] = { 6, 7, 8 };
|
|
||||||
short tmp[10];
|
|
||||||
CombinedBuffer<short> buffer(buffer1, 5, buffer2, 3);
|
|
||||||
buffer.Shift(6);
|
|
||||||
fill(tmp, tmp + 10, 0);
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
EXPECT_EQ(0, tmp[i]);
|
|
||||||
}
|
|
||||||
copy(buffer.Begin(), buffer.End(), tmp);
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
EXPECT_EQ(7 + i, tmp[i]);
|
|
||||||
}
|
|
||||||
for (int i = 2; i < 10; i++) {
|
|
||||||
EXPECT_EQ(0, tmp[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
25
3rdparty/chromaprint/tests/test_filter.cpp
vendored
25
3rdparty/chromaprint/tests/test_filter.cpp
vendored
@ -1,25 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include "image.h"
|
|
||||||
#include "filter.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(Filter, Filter0)
|
|
||||||
{
|
|
||||||
Image image(2, 2);
|
|
||||||
image[0][0] = 0.0;
|
|
||||||
image[0][1] = 1.0;
|
|
||||||
image[1][0] = 2.0;
|
|
||||||
image[1][1] = 3.0;
|
|
||||||
|
|
||||||
Filter flt1(0, 0, 1, 1);
|
|
||||||
IntegralImage integral_image(&image);
|
|
||||||
ASSERT_FLOAT_EQ(0.0, flt1.Apply(&integral_image, 0));
|
|
||||||
ASSERT_FLOAT_EQ(1.0986123, flt1.Apply(&integral_image, 1));
|
|
||||||
}
|
|
||||||
|
|
118
3rdparty/chromaprint/tests/test_filter_utils.cpp
vendored
118
3rdparty/chromaprint/tests/test_filter_utils.cpp
vendored
@ -1,118 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include "filter_utils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(FilterUtils, CompareSubtract) {
|
|
||||||
double res = Subtract(2.0, 1.0);
|
|
||||||
EXPECT_FLOAT_EQ(1.0, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FilterUtils, CompareSubtractLog) {
|
|
||||||
double res = SubtractLog(2.0, 1.0);
|
|
||||||
EXPECT_FLOAT_EQ(0.4054651, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FilterUtils, Filter0) {
|
|
||||||
double data[] = {
|
|
||||||
1.0, 2.0, 3.0,
|
|
||||||
4.0, 5.0, 6.0,
|
|
||||||
7.0, 8.0, 9.0,
|
|
||||||
};
|
|
||||||
Image image(3, data, data + 9);
|
|
||||||
IntegralImage integral_image(&image);
|
|
||||||
double res;
|
|
||||||
res = Filter0(&integral_image, 0, 0, 1, 1, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(1.0, res);
|
|
||||||
res = Filter0(&integral_image, 0, 0, 2, 2, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(12.0, res);
|
|
||||||
res = Filter0(&integral_image, 0, 0, 3, 3, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(45.0, res);
|
|
||||||
res = Filter0(&integral_image, 1, 1, 2, 2, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(28.0, res);
|
|
||||||
res = Filter0(&integral_image, 2, 2, 1, 1, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(9.0, res);
|
|
||||||
res = Filter0(&integral_image, 0, 0, 3, 1, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(12.0, res);
|
|
||||||
res = Filter0(&integral_image, 0, 0, 1, 3, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(6.0, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FilterUtils, Filter1) {
|
|
||||||
double data[] = {
|
|
||||||
1.0, 2.0, 3.0,
|
|
||||||
3.0, 4.0, 5.0,
|
|
||||||
6.0, 7.0, 8.0,
|
|
||||||
};
|
|
||||||
Image image(3, data, data + 9);
|
|
||||||
IntegralImage integral_image(&image);
|
|
||||||
double res;
|
|
||||||
res = Filter1(&integral_image, 0, 0, 1, 1, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(1.0, res); // 2 - 1
|
|
||||||
res = Filter1(&integral_image, 0, 0, 2, 2, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(2.0, res); // 2+4 - 1+3
|
|
||||||
res = Filter1(&integral_image, 0, 0, 3, 2, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(3.0, res); // 2+4+7 - 1+3+6
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FilterUtils, Filter2) {
|
|
||||||
double data[] = {
|
|
||||||
1.0, 2.0, 3.0,
|
|
||||||
3.0, 4.0, 5.0,
|
|
||||||
6.0, 7.0, 8.0,
|
|
||||||
};
|
|
||||||
Image image(3, data, data + 9);
|
|
||||||
IntegralImage integral_image(&image);
|
|
||||||
double res;
|
|
||||||
res = Filter2(&integral_image, 0, 0, 2, 1, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(2.0, res); // 3 - 1
|
|
||||||
res = Filter2(&integral_image, 0, 0, 2, 2, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(4.0, res); // 3+4 - 1+2
|
|
||||||
res = Filter2(&integral_image, 0, 0, 2, 3, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(6.0, res); // 3+4+5 - 1+2+3
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FilterUtils, Filter3) {
|
|
||||||
double data[] = {
|
|
||||||
1.0, 2.1, 3.4,
|
|
||||||
3.1, 4.1, 5.1,
|
|
||||||
6.0, 7.1, 8.0,
|
|
||||||
};
|
|
||||||
Image image(3, data, data + 9);
|
|
||||||
IntegralImage integral_image(&image);
|
|
||||||
double res;
|
|
||||||
res = Filter3(&integral_image, 0, 0, 2, 2, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(0.1, res); // 2.1+3.1 - 1+4.1
|
|
||||||
res = Filter3(&integral_image, 1, 1, 2, 2, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(0.1, res); // 4+8 - 5+7
|
|
||||||
res = Filter3(&integral_image, 0, 1, 2, 2, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(0.3, res); // 2.1+5.1 - 3.4+4.1
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FilterUtils, Filter4) {
|
|
||||||
double data[] = {
|
|
||||||
1.0, 2.0, 3.0,
|
|
||||||
3.0, 4.0, 5.0,
|
|
||||||
6.0, 7.0, 8.0,
|
|
||||||
};
|
|
||||||
Image image(3, data, data + 9);
|
|
||||||
IntegralImage integral_image(&image);
|
|
||||||
double res;
|
|
||||||
res = Filter4(&integral_image, 0, 0, 3, 3, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(-13.0, res); // 2+4+7 - (1+3+6) - (3+5+8)
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FilterUtils, Filter5) {
|
|
||||||
double data[] = {
|
|
||||||
1.0, 2.0, 3.0,
|
|
||||||
3.0, 4.0, 5.0,
|
|
||||||
6.0, 7.0, 8.0,
|
|
||||||
};
|
|
||||||
Image image(3, data, data + 9);
|
|
||||||
IntegralImage integral_image(&image);
|
|
||||||
double res;
|
|
||||||
res = Filter5(&integral_image, 0, 0, 3, 3, Subtract);
|
|
||||||
EXPECT_FLOAT_EQ(-15.0, res); // 3+4+5 - (1+2+3) - (6+7+8)
|
|
||||||
}
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include "image.h"
|
|
||||||
#include "classifier.h"
|
|
||||||
#include "fingerprint_calculator.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(FingerprintCalculator, CalculateSubfingerprint)
|
|
||||||
{
|
|
||||||
Image image(2, 2);
|
|
||||||
image[0][0] = 0.0;
|
|
||||||
image[0][1] = 1.0;
|
|
||||||
image[1][0] = 2.0;
|
|
||||||
image[1][1] = 3.0;
|
|
||||||
|
|
||||||
Classifier classifiers[] = {
|
|
||||||
Classifier(Filter(0, 0, 1, 1), Quantizer(0.01, 1.01, 1.5)),
|
|
||||||
};
|
|
||||||
FingerprintCalculator calculator(classifiers, 1);
|
|
||||||
|
|
||||||
IntegralImage integral_image(&image);
|
|
||||||
EXPECT_EQ(GrayCode(0), calculator.CalculateSubfingerprint(&integral_image, 0));
|
|
||||||
EXPECT_EQ(GrayCode(2), calculator.CalculateSubfingerprint(&integral_image, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FingerprintCalculator, Calculate)
|
|
||||||
{
|
|
||||||
Image image(2, 3);
|
|
||||||
image[0][0] = 0.0;
|
|
||||||
image[0][1] = 1.0;
|
|
||||||
image[1][0] = 2.0;
|
|
||||||
image[1][1] = 3.0;
|
|
||||||
image[2][0] = 4.0;
|
|
||||||
image[2][1] = 5.0;
|
|
||||||
|
|
||||||
Classifier classifiers[] = {
|
|
||||||
Classifier(Filter(0, 0, 1, 1), Quantizer(0.01, 1.01, 1.5)),
|
|
||||||
};
|
|
||||||
FingerprintCalculator calculator(classifiers, 1);
|
|
||||||
|
|
||||||
vector<int32_t> fp = calculator.Calculate(&image);
|
|
||||||
ASSERT_EQ(3, fp.size());
|
|
||||||
EXPECT_EQ(GrayCode(0), fp[0]);
|
|
||||||
EXPECT_EQ(GrayCode(2), fp[1]);
|
|
||||||
EXPECT_EQ(GrayCode(3), fp[2]);
|
|
||||||
}
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include "image.h"
|
|
||||||
#include "classifier.h"
|
|
||||||
#include "fingerprint_compressor.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "test_utils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(FingerprintCompressor, OneItemOneBit)
|
|
||||||
{
|
|
||||||
FingerprintCompressor compressor;
|
|
||||||
|
|
||||||
int32_t fingerprint[] = { 1 };
|
|
||||||
string value = compressor.Compress(vector<int32_t>(fingerprint, fingerprint + 1));
|
|
||||||
|
|
||||||
char expected[] = { 0, 0, 0, 1, 1 };
|
|
||||||
CheckString(value, expected, sizeof(expected)/sizeof(expected[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FingerprintCompressor, OneItemThreeBits)
|
|
||||||
{
|
|
||||||
FingerprintCompressor compressor;
|
|
||||||
|
|
||||||
int32_t fingerprint[] = { 7 };
|
|
||||||
string value = compressor.Compress(vector<int32_t>(fingerprint, fingerprint + 1));
|
|
||||||
|
|
||||||
char expected[] = { 0, 0, 0, 1, 73, 0 };
|
|
||||||
CheckString(value, expected, sizeof(expected)/sizeof(expected[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FingerprintCompressor, OneItemOneBitExcept)
|
|
||||||
{
|
|
||||||
FingerprintCompressor compressor;
|
|
||||||
|
|
||||||
int32_t fingerprint[] = { 1<<6 };
|
|
||||||
string value = compressor.Compress(vector<int32_t>(fingerprint, fingerprint + 1));
|
|
||||||
|
|
||||||
char expected[] = { 0, 0, 0, 1, 7, 0 };
|
|
||||||
CheckString(value, expected, sizeof(expected)/sizeof(expected[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FingerprintCompressor, OneItemOneBitExcept2)
|
|
||||||
{
|
|
||||||
FingerprintCompressor compressor;
|
|
||||||
|
|
||||||
int32_t fingerprint[] = { 1<<8 };
|
|
||||||
string value = compressor.Compress(vector<int32_t>(fingerprint, fingerprint + 1));
|
|
||||||
|
|
||||||
char expected[] = { 0, 0, 0, 1, 7, 2 };
|
|
||||||
CheckString(value, expected, sizeof(expected)/sizeof(expected[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FingerprintCompressor, TwoItems)
|
|
||||||
{
|
|
||||||
FingerprintCompressor compressor;
|
|
||||||
|
|
||||||
int32_t fingerprint[] = { 1, 0 };
|
|
||||||
string value = compressor.Compress(vector<int32_t>(fingerprint, fingerprint + 2));
|
|
||||||
|
|
||||||
char expected[] = { 0, 0, 0, 2, 65, 0 };
|
|
||||||
CheckString(value, expected, sizeof(expected)/sizeof(expected[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FingerprintCompressor, TwoItemsNoChange)
|
|
||||||
{
|
|
||||||
FingerprintCompressor compressor;
|
|
||||||
|
|
||||||
int32_t fingerprint[] = { 1, 1 };
|
|
||||||
string value = compressor.Compress(vector<int32_t>(fingerprint, fingerprint + 2));
|
|
||||||
|
|
||||||
char expected[] = { 0, 0, 0, 2, 1, 0 };
|
|
||||||
CheckString(value, expected, sizeof(expected)/sizeof(expected[0]));
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include "fingerprint_decompressor.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "test_utils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(FingerprintDecompressor, OneItemOneBit)
|
|
||||||
{
|
|
||||||
int32_t expected[] = { 1 };
|
|
||||||
char data[] = { 0, 0, 0, 1, 1 };
|
|
||||||
|
|
||||||
int algorithm = 1;
|
|
||||||
vector<int32_t> value = DecompressFingerprint(string(data, NELEMS(data)), &algorithm);
|
|
||||||
CheckFingerprints(value, expected, NELEMS(expected));
|
|
||||||
ASSERT_EQ(0, algorithm);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST(FingerprintDecompressor, OneItemThreeBits)
|
|
||||||
{
|
|
||||||
int32_t expected[] = { 7 };
|
|
||||||
char data[] = { 0, 0, 0, 1, 73, 0 };
|
|
||||||
|
|
||||||
int algorithm = 1;
|
|
||||||
vector<int32_t> value = DecompressFingerprint(string(data, NELEMS(data)), &algorithm);
|
|
||||||
CheckFingerprints(value, expected, NELEMS(expected));
|
|
||||||
ASSERT_EQ(0, algorithm);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FingerprintDecompressor, OneItemOneBitExcept)
|
|
||||||
{
|
|
||||||
int32_t expected[] = { 1<<6 };
|
|
||||||
char data[] = { 0, 0, 0, 1, 7, 0 };
|
|
||||||
|
|
||||||
int algorithm = 1;
|
|
||||||
vector<int32_t> value = DecompressFingerprint(string(data, NELEMS(data)), &algorithm);
|
|
||||||
CheckFingerprints(value, expected, NELEMS(expected));
|
|
||||||
ASSERT_EQ(0, algorithm);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FingerprintDecompressor, OneItemOneBitExcept2)
|
|
||||||
{
|
|
||||||
int32_t expected[] = { 1<<8 };
|
|
||||||
char data[] = { 0, 0, 0, 1, 7, 2 };
|
|
||||||
|
|
||||||
int algorithm = 1;
|
|
||||||
vector<int32_t> value = DecompressFingerprint(string(data, NELEMS(data)), &algorithm);
|
|
||||||
CheckFingerprints(value, expected, NELEMS(expected));
|
|
||||||
ASSERT_EQ(0, algorithm);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FingerprintDecompressor, TwoItems)
|
|
||||||
{
|
|
||||||
int32_t expected[] = { 1, 0 };
|
|
||||||
char data[] = { 0, 0, 0, 2, 65, 0 };
|
|
||||||
|
|
||||||
int algorithm = 1;
|
|
||||||
vector<int32_t> value = DecompressFingerprint(string(data, NELEMS(data)), &algorithm);
|
|
||||||
CheckFingerprints(value, expected, NELEMS(expected));
|
|
||||||
ASSERT_EQ(0, algorithm);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FingerprintDecompressor, TwoItemsNoChange)
|
|
||||||
{
|
|
||||||
int32_t expected[] = { 1, 1 };
|
|
||||||
char data[] = { 0, 0, 0, 2, 1, 0 };
|
|
||||||
|
|
||||||
int algorithm = 1;
|
|
||||||
vector<int32_t> value = DecompressFingerprint(string(data, NELEMS(data)), &algorithm);
|
|
||||||
CheckFingerprints(value, expected, NELEMS(expected));
|
|
||||||
ASSERT_EQ(0, algorithm);
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include "integral_image.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(IntegralImage, Basic2D) {
|
|
||||||
double data[] = {
|
|
||||||
1.0, 2.0,
|
|
||||||
3.0, 4.0,
|
|
||||||
};
|
|
||||||
Image image(2, data, data + 4);
|
|
||||||
IntegralImage integral_image(&image);
|
|
||||||
EXPECT_FLOAT_EQ(1.0, integral_image[0][0]);
|
|
||||||
EXPECT_FLOAT_EQ(3.0, integral_image[0][1]);
|
|
||||||
EXPECT_FLOAT_EQ(4.0, integral_image[1][0]);
|
|
||||||
EXPECT_FLOAT_EQ(10.0, integral_image[1][1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(IntegralImage, Vertical1D) {
|
|
||||||
double data[] = {
|
|
||||||
1.0, 2.0, 3.0
|
|
||||||
};
|
|
||||||
Image image(1, data, data + 3);
|
|
||||||
IntegralImage integral_image(&image);
|
|
||||||
EXPECT_FLOAT_EQ(1.0, integral_image[0][0]);
|
|
||||||
EXPECT_FLOAT_EQ(3.0, integral_image[1][0]);
|
|
||||||
EXPECT_FLOAT_EQ(6.0, integral_image[2][0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(IntegralImage, Horizontal1D) {
|
|
||||||
double data[] = {
|
|
||||||
1.0, 2.0, 3.0
|
|
||||||
};
|
|
||||||
Image image(3, data, data + 3);
|
|
||||||
IntegralImage integral_image(&image);
|
|
||||||
EXPECT_FLOAT_EQ(1.0, integral_image[0][0]);
|
|
||||||
EXPECT_FLOAT_EQ(3.0, integral_image[0][1]);
|
|
||||||
EXPECT_FLOAT_EQ(6.0, integral_image[0][2]);
|
|
||||||
}
|
|
80
3rdparty/chromaprint/tests/test_lloyds.cpp
vendored
80
3rdparty/chromaprint/tests/test_lloyds.cpp
vendored
@ -1,80 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <limits>
|
|
||||||
#include "lloyds.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
ostream &operator<<(ostream &stream, const vector<T> &vec)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < vec.size(); i++) {
|
|
||||||
if (i != 0)
|
|
||||||
stream << ", ";
|
|
||||||
stream << vec[i];
|
|
||||||
}
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*TEST(Lloyds, Long) {
|
|
||||||
double signal[] = {
|
|
||||||
-2.23622, -2.2133, -2.08922, -2.02973, -2.01912, -2.00194, -1.94793, -1.92903, -1.90671, -1.90311, -1.86394, -1.82542, -1.82281, -1.77955, -1.77286, -1.77119, -1.76317, -1.74447, -1.74447, -1.71927, -1.71244, -1.70758, -1.69632, -1.69448, -1.68845, -1.68842, -1.65839, -1.64934, -1.63575, -1.61216, -1.56943, -1.56546, -1.5601, -1.5584, -1.53875, -1.52408, -1.51576, -1.47345, -1.44838, -1.44712, -1.43751, -1.43722, -1.43159, -1.41818, -1.41585, -1.36654, -1.36556, -1.36486, -1.3596, -1.35941, -1.35301, -1.35301, -1.35145, -1.34479, -1.34443, -1.3441, -1.3381, -1.3334, -1.31715, -1.31105, -1.31071, -1.30166, -1.29944, -1.29715, -1.29669, -1.29634, -1.28696, -1.28504, -1.27143, -1.26548, -1.26533, -1.26421, -1.26054, -1.25978, -1.25631, -1.24751, -1.23887, -1.23797, -1.23588, -1.22391, -1.21961, -1.21559, -1.21499, -1.19502, -1.19009, -1.18784, -1.18746, -1.18264, -1.17917, -1.17597, -1.17482, -1.1664, -1.15644, -1.15584, -1.15317, -1.14694, -1.14341, -1.14246, -1.14234, -1.14027, -1.13955, -1.13745, -1.13674, -1.12764, -1.12735, -1.12729, -1.12645, -1.12578, -1.12533, -1.12131, -1.11019, -1.10879, -1.10357, -1.09973, -1.09187, -1.09187, -1.06664, -1.06356, -1.0554, -1.0492, -1.04506, -1.04027, -1.03942, -1.03896, -1.034, -1.03285, -1.02334, -1.02084, -1.01993, -1.01447, -1.01447, -1.01447, -1.00864, -1.00689, -1.00471, -1.00125, -0.999809, -0.998627, -0.998156, -0.994751, -0.994212, -0.993412, -0.992572, -0.992572, -0.992548, -0.992472, -0.989607, -0.987201, -0.982932, -0.982652, -0.980823, -0.976318, -0.974594, -0.973334, -0.97326, -0.971969, -0.970954, -0.964969, -0.963816, -0.960578, -0.959536, -0.95708, -0.953791, -0.953782, -0.952128, -0.951757, -0.95172, -0.951264, -0.950896, -0.949007, -0.947225, -0.945958, -0.945852, -0.945044, -0.94482, -0.940381, -0.940254, -0.940084, -0.939844, -0.937978, -0.935127, -0.93345, -0.931299, -0.931147, -0.929513, -0.927091, -0.926682, -0.926458, -0.925325, -0.918487, -0.917891, -0.917015, -0.916352, -0.915526, -0.915489, -0.913747, -0.91204, -0.911457, -0.911281, -0.910753, -0.909806, -0.909361, -0.908686, -0.907, -0.906509, -0.903637, -0.902177, -0.896958, -0.896304, -0.895733, -0.889965, -0.886484, -0.884943, -0.882143, -0.879831, -0.879507, -0.876134, -0.875782, -0.873226, -0.873167, -0.872282, -0.870152, -0.869655, -0.869655, -0.866992, -0.862656, -0.862331, -0.861969, -0.861246, -0.856819, -0.854323, -0.853294, -0.846832, -0.843682, -0.842113, -0.840478, -0.835353, -0.83055, -0.828979, -0.828979, -0.828088, -0.826904, -0.826844, -0.826474, -0.820101, -0.819027, -0.819027, -0.818121, -0.812784, -0.812206, -0.810112, -0.806803, -0.805296, -0.80126, -0.800501, -0.798129, -0.797067, -0.786663, -0.785991, -0.784662, -0.78212, -0.776524, -0.774306, -0.772335, -0.771675, -0.771675, -0.77125, -0.770083, -0.769165, -0.767499, -0.766419, -0.763909, -0.762582, -0.76243, -0.761753, -0.761182, -0.759494, -0.755514, -0.745122, -0.742554, -0.739007, -0.73575, -0.735359, -0.73376, -0.732161, -0.728712, -0.726951, -0.726218, -0.725935, -0.724686, -0.722143, -0.722044, -0.721563, -0.721248, -0.720543, -0.719718, -0.716511, -0.714431, -0.714329, -0.712779, -0.712512, -0.712512, -0.711802, -0.71157, -0.709608, -0.706909, -0.706774, -0.704839, -0.703444, -0.702687, -0.70263, -0.702272, -0.700726, -0.700691, -0.700566, -0.698961, -0.697583, -0.697153, -0.696813, -0.696062, -0.695309, -0.694557, -0.691675, -0.691434, -0.687548, -0.686447, -0.684052, -0.68283, -0.682705, -0.682523, -0.682514, -0.679172, -0.675747, -0.675161, -0.673046, -0.670132, -0.663973, -0.659537, -0.655187, -0.65481, -0.653818, -0.65335, -0.653181, -0.649845, -0.649723, -0.648533, -0.647648, -0.645932, -0.645885, -0.645736, -0.643418, -0.642324, -0.642275, -0.641053, -0.641053, -0.636907, -0.635015, -0.634658, -0.632863, -0.629322, -0.629234, -0.628869, -0.627114, -0.626578, -0.626576, -0.62511, -0.625091, -0.621436, -0.620774, -0.616916, -0.616051, -0.612722, -0.611527, -0.610163, -0.609325, -0.606185, -0.606169, -0.606019, -0.603731, -0.602434, -0.596665, -0.596236, -0.595822, -0.594053, -0.588736, -0.588164, -0.586796, -0.586709, -0.585038, -0.583978, -0.583929, -0.582533, -0.576205, -0.57511
|
|
||||||
};
|
|
||||||
vector<double> r = lloyds(signal, signal + sizeof(signal) / sizeof(signal[0]), 10);
|
|
||||||
EXPECT_EQ(9, r.size());
|
|
||||||
EXPECT_FLOAT_EQ(-2.15126, r[0]);
|
|
||||||
EXPECT_FLOAT_EQ(-1.95019, r[1]);
|
|
||||||
EXPECT_FLOAT_EQ(-1.72034, r[2]);
|
|
||||||
EXPECT_FLOAT_EQ(-1.42570, r[3]);
|
|
||||||
EXPECT_FLOAT_EQ(-1.23976, r[4]);
|
|
||||||
EXPECT_FLOAT_EQ(-1.06092, r[5]);
|
|
||||||
EXPECT_FLOAT_EQ(-0.93395, r[6]);
|
|
||||||
EXPECT_FLOAT_EQ(-0.81530, r[7]);
|
|
||||||
EXPECT_FLOAT_EQ(-0.68837, r[8]);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
TEST(LLoyds, Lloyds1) {
|
|
||||||
double data[] = {
|
|
||||||
1.0, 1.1, 1.2,
|
|
||||||
3.0, 3.1, 3.2,
|
|
||||||
};
|
|
||||||
vector<double> sig(data, data + 6);
|
|
||||||
vector<double> table = lloyds(sig, 2);
|
|
||||||
EXPECT_EQ(1, table.size());
|
|
||||||
EXPECT_FLOAT_EQ(2.1, table[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(LLoyds, Lloyds2) {
|
|
||||||
double data[] = {
|
|
||||||
1.0, 1.1, 1.2,
|
|
||||||
};
|
|
||||||
vector<double> sig(data, data + 3);
|
|
||||||
vector<double> table = lloyds(sig, 2);
|
|
||||||
EXPECT_EQ(1, table.size());
|
|
||||||
EXPECT_FLOAT_EQ(1.075, table[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(LLoyds, Lloyds3) {
|
|
||||||
double data[] = {
|
|
||||||
1.0, 1.1, 1.2,
|
|
||||||
};
|
|
||||||
vector<double> sig(data, data + 3);
|
|
||||||
vector<double> table = lloyds(sig, 3);
|
|
||||||
EXPECT_EQ(2, table.size());
|
|
||||||
EXPECT_FLOAT_EQ(1.05, table[0]);
|
|
||||||
EXPECT_FLOAT_EQ(1.15, table[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(LLoyds, Lloyds4) {
|
|
||||||
double data[] = {
|
|
||||||
435,219,891,906,184,572,301,892,875,121,245,146,640,137,938,25,668,288,848,790,141,890,528,145,289,861,339,769,293,757
|
|
||||||
};
|
|
||||||
vector<double> sig(data, data + 30);
|
|
||||||
vector<double> table = lloyds(sig, 4);
|
|
||||||
EXPECT_EQ(3, table.size());
|
|
||||||
EXPECT_FLOAT_EQ(214.77678, table[0]);
|
|
||||||
EXPECT_FLOAT_EQ(451.5625, table[1]);
|
|
||||||
EXPECT_FLOAT_EQ(729.04547, table[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
17
3rdparty/chromaprint/tests/test_quantizer.cpp
vendored
17
3rdparty/chromaprint/tests/test_quantizer.cpp
vendored
@ -1,17 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include "quantizer.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(Quantizer, Quantize) {
|
|
||||||
Quantizer q(0.0, 0.1, 0.3);
|
|
||||||
EXPECT_EQ(0, q.Quantize(-0.1));
|
|
||||||
EXPECT_EQ(1, q.Quantize(0.0));
|
|
||||||
EXPECT_EQ(1, q.Quantize(0.03));
|
|
||||||
EXPECT_EQ(2, q.Quantize(0.1));
|
|
||||||
EXPECT_EQ(2, q.Quantize(0.13));
|
|
||||||
EXPECT_EQ(3, q.Quantize(0.3));
|
|
||||||
EXPECT_EQ(3, q.Quantize(0.33));
|
|
||||||
EXPECT_EQ(3, q.Quantize(1000.0));
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include "test_utils.h"
|
|
||||||
#include "silence_remover.h"
|
|
||||||
#include "audio_buffer.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(SilenceRemover, PassThrough)
|
|
||||||
{
|
|
||||||
short samples[] = { 1, 2, 3, 4, 5, 6 };
|
|
||||||
vector<short> data(samples, samples + 6);
|
|
||||||
|
|
||||||
boost::scoped_ptr<AudioBuffer> buffer(new AudioBuffer());
|
|
||||||
boost::scoped_ptr<SilenceRemover> processor(new SilenceRemover(buffer.get()));
|
|
||||||
processor->Reset(44100, 1);
|
|
||||||
processor->Consume(&data[0], data.size());
|
|
||||||
processor->Flush();
|
|
||||||
|
|
||||||
ASSERT_EQ(data.size(), buffer->data().size());
|
|
||||||
for (size_t i = 0; i < data.size(); i++) {
|
|
||||||
ASSERT_EQ(data[i], buffer->data()[i]) << "Signals differ at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SilenceRemover, RemoveLeadingSilence)
|
|
||||||
{
|
|
||||||
short samples1[] = { 0, 0, 1, 2, 0, 4, 5, 0 };
|
|
||||||
vector<short> data1(samples1, samples1 + 8);
|
|
||||||
|
|
||||||
short samples2[] = { 1, 2, 0, 4, 5, 0 };
|
|
||||||
vector<short> data2(samples2, samples2 + 6);
|
|
||||||
|
|
||||||
boost::scoped_ptr<AudioBuffer> buffer(new AudioBuffer());
|
|
||||||
boost::scoped_ptr<SilenceRemover> processor(new SilenceRemover(buffer.get()));
|
|
||||||
processor->Reset(44100, 1);
|
|
||||||
processor->Consume(&data1[0], data1.size());
|
|
||||||
processor->Flush();
|
|
||||||
|
|
||||||
ASSERT_EQ(data2.size(), buffer->data().size());
|
|
||||||
for (size_t i = 0; i < data2.size(); i++) {
|
|
||||||
ASSERT_EQ(data2[i], buffer->data()[i]) << "Signals differ at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
91
3rdparty/chromaprint/tests/test_utils.cpp
vendored
91
3rdparty/chromaprint/tests/test_utils.cpp
vendored
@ -1,91 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <limits>
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
|
|
||||||
TEST(Utils, PrepareHammingWindow) {
|
|
||||||
double window_ex[10] = { 0.08, 0.187619556165, 0.460121838273, 0.77, 0.972258605562, 0.972258605562, 0.77, 0.460121838273, 0.187619556165, 0.08};
|
|
||||||
double window[10];
|
|
||||||
PrepareHammingWindow(window, window + 10);
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
EXPECT_FLOAT_EQ(window_ex[i], window[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Utils, ApplyWindow1) {
|
|
||||||
double window_ex[10] = { 0.08, 0.187619556165, 0.460121838273, 0.77, 0.972258605562, 0.972258605562, 0.77, 0.460121838273, 0.187619556165, 0.08};
|
|
||||||
double window[10];
|
|
||||||
short input[10];
|
|
||||||
double output[10];
|
|
||||||
PrepareHammingWindow(window, window + 10);
|
|
||||||
fill(input, input + 10, numeric_limits<short>::max());
|
|
||||||
double scale = 1.0 / numeric_limits<short>::max();
|
|
||||||
ApplyWindow(input, window, output, 10, scale);
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
EXPECT_FLOAT_EQ(window_ex[i], output[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Utils, ApplyWindow2) {
|
|
||||||
double window[10];
|
|
||||||
short input[10];
|
|
||||||
double output[10];
|
|
||||||
PrepareHammingWindow(window, window + 10);
|
|
||||||
fill(input, input + 10, 0);
|
|
||||||
double scale = 1.0 / numeric_limits<short>::max();
|
|
||||||
ApplyWindow(input, window, output, 10, scale);
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
EXPECT_FLOAT_EQ(0.0, output[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Utils, Sum) {
|
|
||||||
double data[] = { 0.1, 0.2, 0.4, 1.0 };
|
|
||||||
EXPECT_FLOAT_EQ(1.7, Sum(data, data + 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Utils, EuclideanNorm) {
|
|
||||||
double data[] = { 0.1, 0.2, 0.4, 1.0 };
|
|
||||||
EXPECT_FLOAT_EQ(1.1, EuclideanNorm(data, data + 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Utils, NormalizeVector) {
|
|
||||||
double data[] = { 0.1, 0.2, 0.4, 1.0 };
|
|
||||||
double normalized_data[] = { 0.090909, 0.181818, 0.363636, 0.909091 };
|
|
||||||
NormalizeVector(data, data + 4, EuclideanNorm<double *>, 0.01);
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
EXPECT_NEAR(normalized_data[i], data[i], 1e-5) << "Wrong data at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Utils, NormalizeVectorNearZero) {
|
|
||||||
double data[] = { 0.0, 0.001, 0.002, 0.003 };
|
|
||||||
NormalizeVector(data, data + 4, EuclideanNorm<double *>, 0.01);
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
EXPECT_FLOAT_EQ(0.0, data[i]) << "Wrong data at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Utils, NormalizeVectorZero) {
|
|
||||||
double data[] = { 0.0, 0.0, 0.0, 0.0 };
|
|
||||||
NormalizeVector(data, data + 4, EuclideanNorm<double *>, 0.01);
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
EXPECT_FLOAT_EQ(0.0, data[i]) << "Wrong data at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Utils, UnsignedToSigned) {
|
|
||||||
EXPECT_EQ(numeric_limits<int32_t>::max(), UnsignedToSigned(0x7FFFFFFFU));
|
|
||||||
EXPECT_EQ(-1, UnsignedToSigned(0xFFFFFFFFU));
|
|
||||||
EXPECT_EQ(-2, UnsignedToSigned(0xFFFFFFFEU));
|
|
||||||
EXPECT_EQ(numeric_limits<int32_t>::min(), UnsignedToSigned(0x80000000U));
|
|
||||||
EXPECT_EQ(numeric_limits<int32_t>::min() + 1, UnsignedToSigned(0x80000001U));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Utils, IsNaN) {
|
|
||||||
EXPECT_FALSE(IsNaN(0.0));
|
|
||||||
EXPECT_TRUE(IsNaN(sqrt(-1.0)));
|
|
||||||
}
|
|
42
3rdparty/chromaprint/tests/test_utils.h
vendored
42
3rdparty/chromaprint/tests/test_utils.h
vendored
@ -1,42 +0,0 @@
|
|||||||
#ifndef CHROMAPRINT_TESTS_UTILS_H_
|
|
||||||
#define CHROMAPRINT_TESTS_UTILS_H_
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include <string>
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NELEMS(x) (sizeof(x)/sizeof(x[0]))
|
|
||||||
|
|
||||||
inline void CheckString(std::string actual, char *expected, int expected_size)
|
|
||||||
{
|
|
||||||
ASSERT_EQ(expected_size, actual.size());
|
|
||||||
for (int i = 0; i < expected_size; i++) {
|
|
||||||
EXPECT_EQ(expected[i], actual[i]) << "Different at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void CheckFingerprints(std::vector<int32_t> actual, int32_t *expected, int expected_size)
|
|
||||||
{
|
|
||||||
ASSERT_EQ(expected_size, actual.size());
|
|
||||||
for (int i = 0; i < expected_size; i++) {
|
|
||||||
EXPECT_EQ(expected[i], actual[i]) << "Different at index " << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::vector<short> LoadAudioFile(const std::string &file_name)
|
|
||||||
{
|
|
||||||
std::string path = TESTS_DIR + file_name;
|
|
||||||
std::ifstream file(path.c_str(), std::ifstream::in);
|
|
||||||
file.seekg(0, std::ios::end);
|
|
||||||
int length = file.tellg();
|
|
||||||
file.seekg(0, std::ios::beg);
|
|
||||||
std::vector<short> data(length / 2);
|
|
||||||
file.read((char *)&data[0], length);
|
|
||||||
file.close();
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
63
3rdparty/chromaprint/tools/CMakeLists.txt
vendored
63
3rdparty/chromaprint/tools/CMakeLists.txt
vendored
@ -1,63 +0,0 @@
|
|||||||
include_directories(
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../src
|
|
||||||
${FFMPEG_LIBAVCODEC_INCLUDE_DIRS}
|
|
||||||
${FFMPEG_LIBAVFORMAT_INCLUDE_DIRS}
|
|
||||||
${FFMPEG_LIBAVUTIL_INCLUDE_DIRS}
|
|
||||||
${Boost_INCLUDE_DIRS}
|
|
||||||
${TAGLIB_INCLUDES}
|
|
||||||
)
|
|
||||||
|
|
||||||
if(BUILD_EXTRA_TOOLS)
|
|
||||||
|
|
||||||
add_executable(resample resample.cpp)
|
|
||||||
target_link_libraries(resample chromaprint_p
|
|
||||||
${FFMPEG_LIBAVFORMAT_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVCODEC_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVUTIL_LIBRARIES})
|
|
||||||
|
|
||||||
add_executable(decode decode.cpp)
|
|
||||||
target_link_libraries(decode chromaprint_p
|
|
||||||
${FFMPEG_LIBAVFORMAT_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVCODEC_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVUTIL_LIBRARIES})
|
|
||||||
|
|
||||||
add_executable(chromagram chromagram.cpp)
|
|
||||||
target_link_libraries(chromagram chromaprint_p
|
|
||||||
${FFMPEG_LIBAVFORMAT_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVCODEC_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVUTIL_LIBRARIES}
|
|
||||||
-lpng)
|
|
||||||
|
|
||||||
add_executable(spectrogram spectrogram.cpp)
|
|
||||||
target_link_libraries(spectrogram chromaprint_p
|
|
||||||
${FFMPEG_LIBAVFORMAT_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVCODEC_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVUTIL_LIBRARIES}
|
|
||||||
-lpng)
|
|
||||||
|
|
||||||
add_executable(learn_filters learn_filters.cpp)
|
|
||||||
target_link_libraries(learn_filters chromaprint_p
|
|
||||||
${FFMPEG_LIBAVFORMAT_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVCODEC_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVUTIL_LIBRARIES}
|
|
||||||
${Boost_SYSTEM_LIBRARY}
|
|
||||||
${Boost_FILESYSTEM_LIBRARY})
|
|
||||||
|
|
||||||
add_executable(fpeval fpeval.cpp)
|
|
||||||
target_link_libraries(fpeval chromaprint_p
|
|
||||||
${FFMPEG_LIBAVFORMAT_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVCODEC_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVUTIL_LIBRARIES}
|
|
||||||
${Boost_SYSTEM_LIBRARY}
|
|
||||||
${Boost_FILESYSTEM_LIBRARY})
|
|
||||||
|
|
||||||
endif(BUILD_EXTRA_TOOLS)
|
|
||||||
|
|
||||||
if(NOT MSVC)
|
|
||||||
add_executable(fpcollect fpcollect.cpp)
|
|
||||||
target_link_libraries(fpcollect chromaprint_p
|
|
||||||
${FFMPEG_LIBAVFORMAT_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVCODEC_LIBRARIES}
|
|
||||||
${FFMPEG_LIBAVUTIL_LIBRARIES}
|
|
||||||
${TAGLIB_LIBRARIES})
|
|
||||||
endif()
|
|
65
3rdparty/chromaprint/tools/chromagram.cpp
vendored
65
3rdparty/chromaprint/tools/chromagram.cpp
vendored
@ -1,65 +0,0 @@
|
|||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "ext/ffmpeg_decoder.h"
|
|
||||||
#include "ext/audio_dumper.h"
|
|
||||||
#include "audio_processor.h"
|
|
||||||
#include "chroma.h"
|
|
||||||
#include "spectral_centroid.h"
|
|
||||||
#include "chroma_normalizer.h"
|
|
||||||
#include "chroma_resampler.h"
|
|
||||||
#include "chroma_filter.h"
|
|
||||||
#include "fft.h"
|
|
||||||
#include "audio_processor.h"
|
|
||||||
#include "image.h"
|
|
||||||
#include "image_builder.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "ext/image_utils.h"
|
|
||||||
|
|
||||||
static const int SAMPLE_RATE = 11025;
|
|
||||||
static const int FRAME_SIZE = 4096;
|
|
||||||
static const int OVERLAP = FRAME_SIZE - FRAME_SIZE / 3;// 2720;
|
|
||||||
static const int MIN_FREQ = 28;
|
|
||||||
static const int MAX_FREQ = 3520;
|
|
||||||
static const int MAX_FILTER_WIDTH = 20;
|
|
||||||
|
|
||||||
static const int kChromaFilterSize = 5;
|
|
||||||
static const double kChromaFilterCoefficients[] = { 0.25, 0.75, 1.0, 0.75, 0.25 };
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc < 3) {
|
|
||||||
cerr << "Usage: " << argv[0] << " AUDIOFILE IMAGEFILE\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
string file_name(argv[1]);
|
|
||||||
cout << "Loading file " << file_name << "\n";
|
|
||||||
|
|
||||||
Decoder decoder(file_name);
|
|
||||||
if (!decoder.Open()) {
|
|
||||||
cerr << "ERROR: " << decoder.LastError() << "\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
Chromaprint::Image image(12);
|
|
||||||
Chromaprint::ImageBuilder image_builder(&image);
|
|
||||||
Chromaprint::ChromaNormalizer chroma_normalizer(&image_builder);
|
|
||||||
Chromaprint::ChromaFilter chroma_filter(kChromaFilterCoefficients, kChromaFilterSize, &chroma_normalizer);
|
|
||||||
//Chromaprint::Chroma chroma(MIN_FREQ, MAX_FREQ, FRAME_SIZE, SAMPLE_RATE, &chroma_normalizer);
|
|
||||||
Chromaprint::Chroma chroma(MIN_FREQ, MAX_FREQ, FRAME_SIZE, SAMPLE_RATE, &chroma_filter);
|
|
||||||
Chromaprint::FFT fft(FRAME_SIZE, OVERLAP, &chroma);
|
|
||||||
Chromaprint::AudioProcessor processor(SAMPLE_RATE, &fft);
|
|
||||||
|
|
||||||
processor.Reset(decoder.SampleRate(), decoder.Channels());
|
|
||||||
decoder.Decode(&processor);
|
|
||||||
processor.Flush();
|
|
||||||
|
|
||||||
//Chromaprint::ExportTextImage(&image, argv[2]);
|
|
||||||
Chromaprint::ExportImage(&image, argv[2]);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
28
3rdparty/chromaprint/tools/decode.cpp
vendored
28
3rdparty/chromaprint/tools/decode.cpp
vendored
@ -1,28 +0,0 @@
|
|||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "ext/ffmpeg_decoder.h"
|
|
||||||
#include "ext/audio_dumper.h"
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc < 3) {
|
|
||||||
cerr << "Usage: " << argv[0] << " FILENAME\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
string file_name(argv[1]);
|
|
||||||
Decoder decoder(file_name);
|
|
||||||
if (!decoder.Open()) {
|
|
||||||
cerr << "ERROR: " << decoder.LastError() << "\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioDumper dumper(argv[2]);
|
|
||||||
decoder.Decode(&dumper);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
76
3rdparty/chromaprint/tools/fillpuid.py
vendored
76
3rdparty/chromaprint/tools/fillpuid.py
vendored
@ -1,76 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import time
|
|
||||||
import sys
|
|
||||||
from optparse import OptionParser
|
|
||||||
import subprocess
|
|
||||||
import os.path
|
|
||||||
from xml.etree import ElementTree
|
|
||||||
|
|
||||||
|
|
||||||
usage = "usage: %prog [options] logfile"
|
|
||||||
parser = OptionParser(usage=usage)
|
|
||||||
parser.add_option("-a", "--musicdns-apikey", dest="musicdns_api_key", metavar="KEY",
|
|
||||||
help="MusicDNS API key")
|
|
||||||
parser.add_option("-g", "--genpuid", dest="genpuid_path", metavar="PATH",
|
|
||||||
help="path to the GenPUID binary", default="genpuid")
|
|
||||||
|
|
||||||
(options, args) = parser.parse_args()
|
|
||||||
if len(args) != 1:
|
|
||||||
parser.error("no log file specified")
|
|
||||||
|
|
||||||
|
|
||||||
def read_log_file(input):
|
|
||||||
group = {}
|
|
||||||
for line in input:
|
|
||||||
line = line.strip()
|
|
||||||
if not line:
|
|
||||||
if group:
|
|
||||||
yield group
|
|
||||||
group = {}
|
|
||||||
continue
|
|
||||||
name, value = line.split('=', 1)
|
|
||||||
group[name] = value
|
|
||||||
if group:
|
|
||||||
yield group
|
|
||||||
|
|
||||||
|
|
||||||
def make_groups(input, size=10):
|
|
||||||
group = []
|
|
||||||
for entry in input:
|
|
||||||
group.append(entry)
|
|
||||||
if len(group) >= size:
|
|
||||||
yield group
|
|
||||||
group = []
|
|
||||||
if group:
|
|
||||||
yield group
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def write_log_file(entry):
|
|
||||||
for row in entry.iteritems():
|
|
||||||
print '%s=%s' % row
|
|
||||||
print
|
|
||||||
|
|
||||||
|
|
||||||
def call_genpuid(entries):
|
|
||||||
paths = [e['FILENAME'] for e in entries]
|
|
||||||
process = subprocess.Popen([options.genpuid_path, options.musicdns_api_key, '-xml'] + paths, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
||||||
out, err = process.communicate()
|
|
||||||
tree = ElementTree.fromstring('<?xml version="1.0" encoding="iso-8859-1"?>' + out)
|
|
||||||
puids = {}
|
|
||||||
for track in tree.findall("track"):
|
|
||||||
if 'puid' in track.attrib and 'file' in track.attrib:
|
|
||||||
puids[os.path.normpath(track.attrib['file']).encode('iso-8859-1')] = track.attrib['puid']
|
|
||||||
for entry in entries:
|
|
||||||
path = os.path.normpath(entry['FILENAME'])
|
|
||||||
if path in puids:
|
|
||||||
entry['PUID'] = puids[path]
|
|
||||||
|
|
||||||
|
|
||||||
for entries in make_groups(read_log_file(open(args[0]) if args[0] != '-' else sys.stdin), 20):
|
|
||||||
call_genpuid([e for e in entries if 'MBID' not in e])
|
|
||||||
for entry in entries:
|
|
||||||
print >>sys.stderr, entry['FILENAME']
|
|
||||||
write_log_file(entry)
|
|
||||||
|
|
323
3rdparty/chromaprint/tools/fpcollect.cpp
vendored
323
3rdparty/chromaprint/tools/fpcollect.cpp
vendored
@ -1,323 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
//#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/algorithm/string.hpp>
|
|
||||||
#include <fileref.h>
|
|
||||||
#include <tag.h>
|
|
||||||
#include "chromaprint.h"
|
|
||||||
#include "fingerprinter.h"
|
|
||||||
#include "fingerprinter_configuration.h"
|
|
||||||
#include "fingerprint_compressor.h"
|
|
||||||
#include "base64.h"
|
|
||||||
#include "ext/ffmpeg_decoder.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static const int kChromaprintAlgorithm = CHROMAPRINT_ALGORITHM_DEFAULT;
|
|
||||||
|
|
||||||
typedef vector<string> string_vector;
|
|
||||||
|
|
||||||
void FindFiles(const string &dirname, string_vector *result, time_t changed_since)
|
|
||||||
{
|
|
||||||
DIR *dirp = opendir(dirname.c_str());
|
|
||||||
if (!dirp) {
|
|
||||||
if (errno == ENOTDIR) {
|
|
||||||
result->push_back(dirname);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (dirp) {
|
|
||||||
struct dirent *dp;
|
|
||||||
if ((dp = readdir(dirp)) != NULL) {
|
|
||||||
struct stat sp;
|
|
||||||
string filename = dirname + '/' + string(dp->d_name);
|
|
||||||
stat(filename.c_str(), &sp);
|
|
||||||
if (S_ISREG(sp.st_mode)) {
|
|
||||||
//cerr << "file " << filename << " mtime=" << sp.st_mtime << " ch=" << changed_since << "\n";
|
|
||||||
if (!changed_since || sp.st_mtime >= changed_since) {
|
|
||||||
result->push_back(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (S_ISDIR(sp.st_mode) && dp->d_name[0] != '.') {
|
|
||||||
FindFiles(filename, result, changed_since);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dirp);
|
|
||||||
}
|
|
||||||
|
|
||||||
string_vector FindFiles(const string_vector &files, time_t changed_since)
|
|
||||||
{
|
|
||||||
string_vector result;
|
|
||||||
for (size_t i = 0; i < files.size(); i++) {
|
|
||||||
FindFiles(files[i], &result, changed_since);
|
|
||||||
}
|
|
||||||
sort(result.begin(), result.end());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DISPATCH_TAGLIB_FILE(type, file) \
|
|
||||||
{ \
|
|
||||||
type *tmp = dynamic_cast<type *>(file); \
|
|
||||||
if (tmp) { \
|
|
||||||
return ExtractMBIDFromFile(tmp); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <xiphcomment.h>
|
|
||||||
#include <apetag.h>
|
|
||||||
#include <vorbisfile.h>
|
|
||||||
#include <oggflacfile.h>
|
|
||||||
#include <speexfile.h>
|
|
||||||
#include <flacfile.h>
|
|
||||||
#include <mpcfile.h>
|
|
||||||
#include <wavpackfile.h>
|
|
||||||
#ifdef TAGLIB_WITH_ASF
|
|
||||||
#include <asffile.h>
|
|
||||||
#endif
|
|
||||||
#ifdef TAGLIB_WITH_MP4
|
|
||||||
#include <mp4file.h>
|
|
||||||
#endif
|
|
||||||
#include <mpegfile.h>
|
|
||||||
#include <id3v2tag.h>
|
|
||||||
#include <uniquefileidentifierframe.h>
|
|
||||||
|
|
||||||
string ExtractMBIDFromXiphComment(TagLib::Ogg::XiphComment *tag)
|
|
||||||
{
|
|
||||||
string key = "MUSICBRAINZ_TRACKID";
|
|
||||||
if (tag && tag->fieldListMap().contains(key)) {
|
|
||||||
return tag->fieldListMap()[key].front().to8Bit(true);
|
|
||||||
}
|
|
||||||
return string();
|
|
||||||
}
|
|
||||||
|
|
||||||
string ExtractMBIDFromAPETag(TagLib::APE::Tag *tag)
|
|
||||||
{
|
|
||||||
string key = "MUSICBRAINZ_TRACKID";
|
|
||||||
if (tag && tag->itemListMap().contains(key)) {
|
|
||||||
return tag->itemListMap()[key].toString().to8Bit(true);
|
|
||||||
}
|
|
||||||
return string();
|
|
||||||
}
|
|
||||||
|
|
||||||
string ExtractMBIDFromFile(TagLib::Ogg::Vorbis::File *file)
|
|
||||||
{
|
|
||||||
return ExtractMBIDFromXiphComment(file->tag());
|
|
||||||
}
|
|
||||||
|
|
||||||
string ExtractMBIDFromFile(TagLib::Ogg::FLAC::File *file)
|
|
||||||
{
|
|
||||||
return ExtractMBIDFromXiphComment(file->tag());
|
|
||||||
}
|
|
||||||
|
|
||||||
string ExtractMBIDFromFile(TagLib::Ogg::Speex::File *file)
|
|
||||||
{
|
|
||||||
return ExtractMBIDFromXiphComment(file->tag());
|
|
||||||
}
|
|
||||||
|
|
||||||
string ExtractMBIDFromFile(TagLib::FLAC::File *file)
|
|
||||||
{
|
|
||||||
return ExtractMBIDFromXiphComment(file->xiphComment());
|
|
||||||
}
|
|
||||||
|
|
||||||
string ExtractMBIDFromFile(TagLib::MPC::File *file)
|
|
||||||
{
|
|
||||||
return ExtractMBIDFromAPETag(file->APETag());
|
|
||||||
}
|
|
||||||
|
|
||||||
string ExtractMBIDFromFile(TagLib::WavPack::File *file)
|
|
||||||
{
|
|
||||||
return ExtractMBIDFromAPETag(file->APETag());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*string ExtractMBIDFromFile(TagLib::APE::File *file)
|
|
||||||
{
|
|
||||||
return ExtractMBIDFromAPETag(file->APETag());
|
|
||||||
}*/
|
|
||||||
|
|
||||||
#ifdef TAGLIB_WITH_ASF
|
|
||||||
string ExtractMBIDFromFile(TagLib::ASF::File *file)
|
|
||||||
{
|
|
||||||
string key = "MusicBrainz/Track Id";
|
|
||||||
TagLib::ASF::Tag *tag = file->tag();
|
|
||||||
if (tag && tag->attributeListMap().contains(key)) {
|
|
||||||
return tag->attributeListMap()[key].front().toString().to8Bit(true);
|
|
||||||
}
|
|
||||||
return string();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TAGLIB_WITH_MP4
|
|
||||||
string ExtractMBIDFromFile(TagLib::MP4::File *file)
|
|
||||||
{
|
|
||||||
string key = "----:com.apple.iTunes:MusicBrainz Track Id";
|
|
||||||
TagLib::MP4::Tag *tag = file->tag();
|
|
||||||
if (tag && tag->itemListMap().contains(key)) {
|
|
||||||
return tag->itemListMap()[key].toStringList().toString().to8Bit(true);
|
|
||||||
}
|
|
||||||
return string();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
string ExtractMBIDFromFile(TagLib::MPEG::File *file)
|
|
||||||
{
|
|
||||||
TagLib::ID3v2::Tag *tag = file->ID3v2Tag();
|
|
||||||
if (!tag) {
|
|
||||||
return string();
|
|
||||||
}
|
|
||||||
TagLib::ID3v2::FrameList ufid = tag->frameListMap()["UFID"];
|
|
||||||
if (!ufid.isEmpty()) {
|
|
||||||
for (TagLib::ID3v2::FrameList::Iterator i = ufid.begin(); i != ufid.end(); i++) {
|
|
||||||
TagLib::ID3v2::UniqueFileIdentifierFrame *frame = dynamic_cast<TagLib::ID3v2::UniqueFileIdentifierFrame *>(*i);
|
|
||||||
if (frame && frame->owner() == "http://musicbrainz.org") {
|
|
||||||
TagLib::ByteVector id = frame->identifier();
|
|
||||||
return string(id.data(), id.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return string();
|
|
||||||
}
|
|
||||||
|
|
||||||
string ExtractMusicBrainzTrackID(TagLib::File *file)
|
|
||||||
{
|
|
||||||
DISPATCH_TAGLIB_FILE(TagLib::FLAC::File, file);
|
|
||||||
DISPATCH_TAGLIB_FILE(TagLib::Ogg::Vorbis::File, file);
|
|
||||||
DISPATCH_TAGLIB_FILE(TagLib::Ogg::FLAC::File, file);
|
|
||||||
DISPATCH_TAGLIB_FILE(TagLib::Ogg::Speex::File, file);
|
|
||||||
DISPATCH_TAGLIB_FILE(TagLib::MPC::File, file);
|
|
||||||
DISPATCH_TAGLIB_FILE(TagLib::WavPack::File, file);
|
|
||||||
#ifdef TAGLIB_WITH_ASF
|
|
||||||
DISPATCH_TAGLIB_FILE(TagLib::ASF::File, file);
|
|
||||||
#endif
|
|
||||||
#ifdef TAGLIB_WITH_MP4
|
|
||||||
DISPATCH_TAGLIB_FILE(TagLib::MP4::File, file);
|
|
||||||
#endif
|
|
||||||
DISPATCH_TAGLIB_FILE(TagLib::MPEG::File, file);
|
|
||||||
return string();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ReadTags(const string &filename, bool ignore_missing_mbid)
|
|
||||||
{
|
|
||||||
TagLib::FileRef file(filename.c_str(), true);
|
|
||||||
if (file.isNull())
|
|
||||||
return false;
|
|
||||||
TagLib::Tag *tags = file.tag();
|
|
||||||
TagLib::AudioProperties *props = file.audioProperties();
|
|
||||||
if (!tags || !props)
|
|
||||||
return false;
|
|
||||||
//cout << "ARTIST=" << tags->artist().to8Bit(true) << "\n";
|
|
||||||
//cout << "TITLE=" << tags->title().to8Bit(true) << "\n";
|
|
||||||
//cout << "ALBUM=" << tags->album().to8Bit(true) << "\n";
|
|
||||||
int length = props->length();
|
|
||||||
if (!length)
|
|
||||||
return false;
|
|
||||||
string mbid = ExtractMusicBrainzTrackID(file.file());
|
|
||||||
if (mbid.size() != 36 && !ignore_missing_mbid)
|
|
||||||
return false;
|
|
||||||
if (mbid.size() == 36)
|
|
||||||
cout << "MBID=" << mbid << "\n";
|
|
||||||
cout << "LENGTH=" << length << "\n";
|
|
||||||
cout << "BITRATE=" << props->bitrate() << "\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
string ExtractExtension(const string &filename)
|
|
||||||
{
|
|
||||||
size_t pos = filename.find_last_of('.');
|
|
||||||
if (pos == string::npos) {
|
|
||||||
return string();
|
|
||||||
}
|
|
||||||
return boost::to_upper_copy(filename.substr(pos + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
string EncodeFingerprint(const vector<uint32_t> &fp)
|
|
||||||
{
|
|
||||||
string res;
|
|
||||||
res.resize(fp.size());
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProcessFile(Chromaprint::Fingerprinter *fingerprinter, const string &filename, bool ignore_missing_mbid, int audio_length)
|
|
||||||
{
|
|
||||||
if (!ReadTags(filename, ignore_missing_mbid))
|
|
||||||
return false;
|
|
||||||
Decoder decoder(filename);
|
|
||||||
if (!decoder.Open())
|
|
||||||
return false;
|
|
||||||
if (!fingerprinter->Start(decoder.SampleRate(), decoder.Channels()))
|
|
||||||
return false;
|
|
||||||
cerr << filename << "\n";
|
|
||||||
cout << "FILENAME=" << filename << "\n";
|
|
||||||
cout << "FORMAT=" << ExtractExtension(filename) << "\n";
|
|
||||||
decoder.Decode(fingerprinter, audio_length);
|
|
||||||
vector<int32_t> fp = fingerprinter->Finish();
|
|
||||||
/*cout << "FINGERPRINT1=";
|
|
||||||
for (int i = 0; i < fp.size(); i++) {
|
|
||||||
cout << fp[i] << ", ";
|
|
||||||
}
|
|
||||||
cout << "\n";*/
|
|
||||||
cout << "FINGERPRINT=" << Chromaprint::Base64Encode(Chromaprint::CompressFingerprint(fp, kChromaprintAlgorithm)) << "\n\n";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc < 2) {
|
|
||||||
cerr << "Usage: " << argv[0] << " [OPTIONS] FILE...\n";
|
|
||||||
cerr << "Options:\n";
|
|
||||||
cerr << " -nombid Do not require a MBID embedded in the file\n";
|
|
||||||
cerr << " -since DATE Process only files modified since the given date\n";
|
|
||||||
cerr << " -length SECONDS Length of the audio data used for fingerprinting (default 120)\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_vector files;
|
|
||||||
char *changed_since_str = NULL;
|
|
||||||
int audio_length = 120;
|
|
||||||
bool ignore_missing_mbid = false;
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
if (strcmp(argv[i], "-nombid") == 0) {
|
|
||||||
ignore_missing_mbid = true;
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[i], "-since") == 0 && i + 1 < argc) {
|
|
||||||
changed_since_str = argv[++i];
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[i], "-length") == 0 && i + 1 < argc) {
|
|
||||||
audio_length = atoi(argv[++i]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
files.push_back(argv[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t changed_since = 0;
|
|
||||||
if (changed_since_str) {
|
|
||||||
struct tm tm;
|
|
||||||
memset(&tm, 0, sizeof(tm));
|
|
||||||
if (strptime(changed_since_str, "%Y-%m-%d %H:%M", &tm) == NULL) {
|
|
||||||
if (strptime(changed_since_str, "%Y-%m-%d", &tm) == NULL) {
|
|
||||||
cerr << "ERROR: Invalid date, the expected format is 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM'\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tm.tm_isdst = -1;
|
|
||||||
changed_since = mktime(&tm);
|
|
||||||
//cerr << "Calculating fingerprints for files in " << files << " that were changed since " << changed_since_str << "\n";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//cerr << "Calculating fingerprints for all files in " << files << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
Chromaprint::Fingerprinter fingerprinter(Chromaprint::CreateFingerprinterConfiguration(kChromaprintAlgorithm));
|
|
||||||
files = FindFiles(files, changed_since);
|
|
||||||
for (string_vector::iterator it = files.begin(); it != files.end(); it++) {
|
|
||||||
ProcessFile(&fingerprinter, *it, ignore_missing_mbid, audio_length);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
142
3rdparty/chromaprint/tools/fpeval.cpp
vendored
142
3rdparty/chromaprint/tools/fpeval.cpp
vendored
@ -1,142 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/algorithm/string.hpp>
|
|
||||||
#include <boost/dynamic_bitset.hpp>
|
|
||||||
#include <boost/multi_array.hpp>
|
|
||||||
#include "ext/ffmpeg_decoder.h"
|
|
||||||
#include "ext/image_utils.h"
|
|
||||||
#include "audio_processor.h"
|
|
||||||
#include "fingerprinter.h"
|
|
||||||
#include "image.h"
|
|
||||||
#include "integral_image.h"
|
|
||||||
#include "image_builder.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "filter.h"
|
|
||||||
#include "lloyds.h"
|
|
||||||
#include "classifier.h"
|
|
||||||
#include "match.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
namespace fs = boost::filesystem;
|
|
||||||
|
|
||||||
typedef vector<string> string_vector;
|
|
||||||
typedef vector<double> double_vector;
|
|
||||||
|
|
||||||
string_vector FindAudioFiles(const char *dirname)
|
|
||||||
{
|
|
||||||
string_vector result;
|
|
||||||
fs::path path(dirname);
|
|
||||||
fs::directory_iterator end_iter;
|
|
||||||
for (fs::directory_iterator dir_iter(path); dir_iter != end_iter; ++dir_iter) {
|
|
||||||
if (fs::is_regular_file(dir_iter->status())) {
|
|
||||||
string filename = dir_iter->path().string();
|
|
||||||
if (boost::ends_with(filename, ".mp3") || boost::ends_with(filename, ".wav")) {
|
|
||||||
result.push_back(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort(result.begin(), result.end());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<string_vector> GenerateFilePairs(const vector<string> &files)
|
|
||||||
{
|
|
||||||
string last_name;
|
|
||||||
vector<string_vector> result;
|
|
||||||
for (int i = 0; i < files.size(); i++) {
|
|
||||||
string name = fs::basename(files[i]);
|
|
||||||
name = name.substr(0, name.find_first_of('-'));
|
|
||||||
if (last_name != name) {
|
|
||||||
result.push_back(string_vector());
|
|
||||||
last_name = name;
|
|
||||||
}
|
|
||||||
result.back().push_back(files[i]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<int> MultiMapValues(const multimap<int, int> &data, const int &key)
|
|
||||||
{
|
|
||||||
pair<multimap<int, int>::const_iterator, multimap<int, int>::const_iterator> range = data.equal_range(key);
|
|
||||||
vector<int> result;
|
|
||||||
for (multimap<int, int>::const_iterator i = range.first; i != range.second; ++i) {
|
|
||||||
result.push_back((*i).second);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const int SAMPLE_RATE = 11025;
|
|
||||||
static const int FRAME_SIZE = 4096;
|
|
||||||
static const int OVERLAP = FRAME_SIZE - FRAME_SIZE / 3;// 2720;
|
|
||||||
static const int MIN_FREQ = 28;
|
|
||||||
static const int MAX_FREQ = 3520;
|
|
||||||
static const int MAX_FILTER_WIDTH = 16;
|
|
||||||
/*static const int OVERLAP = FRAME_SIZE - FRAME_SIZE / 2;// 2720;
|
|
||||||
static const int MIN_FREQ = 300;
|
|
||||||
static const int MAX_FREQ = 5300;
|
|
||||||
static const int MAX_FILTER_WIDTH = 20;*/
|
|
||||||
|
|
||||||
void PrintRate(const std::string &name, const std::vector<int> &values, int scale)
|
|
||||||
{
|
|
||||||
cout << name << " = [";
|
|
||||||
for (int j = 0; j < 32; j++) {
|
|
||||||
double rate = double(values[j]) / scale;
|
|
||||||
if (j != 0) std::cout << ", ";
|
|
||||||
std::cout << rate;
|
|
||||||
}
|
|
||||||
cout << "]\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FP_TYPE_CHROMA 1
|
|
||||||
#define FP_TYPE_CENTROID 2
|
|
||||||
#define FP_TYPE FP_TYPE_CHROMA
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
Chromaprint::Fingerprinter fingerprinter;
|
|
||||||
|
|
||||||
vector<string> files = FindAudioFiles(argv[1]);
|
|
||||||
vector< string > names[2];
|
|
||||||
vector< vector<int32_t> > fingerprints[2];
|
|
||||||
for (int i = 0; i < files.size(); i++) {
|
|
||||||
cout << " - " << files[i] << "\n";
|
|
||||||
Decoder decoder(files[i]);
|
|
||||||
if (!decoder.Open()) {
|
|
||||||
cerr << "ERROR: " << decoder.LastError() << "\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
fingerprinter.Start(decoder.SampleRate(), decoder.Channels());
|
|
||||||
decoder.Decode(&fingerprinter, 60);
|
|
||||||
vector<int32_t> fp = fingerprinter.Finish();
|
|
||||||
int orig = files[i].find("orig") != string::npos ? 1 : 0;
|
|
||||||
fingerprints[orig].push_back(fp);
|
|
||||||
names[orig].push_back(files[i]);
|
|
||||||
}
|
|
||||||
int num_files = files.size() / 2;
|
|
||||||
|
|
||||||
typedef boost::multi_array<float, 2> DoubleArray2D;
|
|
||||||
|
|
||||||
float total = 0.0f, diagonal = 0.0f;
|
|
||||||
DoubleArray2D confmatrix(boost::extents[num_files][num_files]);
|
|
||||||
for (int i = 0; i < num_files; i++) {
|
|
||||||
for (int j = 0; j < num_files; j++) {
|
|
||||||
float score = match_fingerprints(fingerprints[0][i], fingerprints[1][j]);
|
|
||||||
cout << " - " << names[0][i] << " / " << names[1][j] << " = " << score <<"\n";
|
|
||||||
confmatrix[i][j] = score;
|
|
||||||
if (i == j) {
|
|
||||||
diagonal += score;
|
|
||||||
}
|
|
||||||
total += score;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cout << "true positive: " << diagonal / num_files << "\n";
|
|
||||||
cout << "false positive: " << (total - diagonal) / (num_files * num_files - num_files) << "\n";
|
|
||||||
cout << "score: " << diagonal / total << "\n";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
121
3rdparty/chromaprint/tools/fpsubmit.py
vendored
121
3rdparty/chromaprint/tools/fpsubmit.py
vendored
@ -1,121 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import time
|
|
||||||
import sys
|
|
||||||
import urllib2
|
|
||||||
import urllib
|
|
||||||
import gzip
|
|
||||||
import socket
|
|
||||||
from cStringIO import StringIO
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
|
|
||||||
usage = "usage: %prog [options] logfile"
|
|
||||||
parser = OptionParser(usage=usage)
|
|
||||||
parser.add_option("-a", "--api-key", dest="api_key", metavar="KEY",
|
|
||||||
help="your Acoustid API key (http://acoustid.org/api-key)")
|
|
||||||
parser.add_option("-b", "--batch-size", dest="batch_size", type="int",
|
|
||||||
default=50, metavar="SIZE",
|
|
||||||
help="how many fingerprints to submit in one request [default: %default]")
|
|
||||||
parser.add_option("--app-url", dest="app_url", type="string",
|
|
||||||
default='http://api.acoustid.org/submit',
|
|
||||||
help="how many fingerprints to submit in one request [default: %default]")
|
|
||||||
parser.add_option("--app-api-key", dest="app_api_key", type="string", default='5hOby2eZ',
|
|
||||||
help="application API key (needed only if you submit to a non-default URL)")
|
|
||||||
parser.add_option("-s", "--start", dest="start", type="int",
|
|
||||||
default=1, metavar="SIZE",
|
|
||||||
help="start with the Nth entry from the log file [default: %default]")
|
|
||||||
|
|
||||||
(options, args) = parser.parse_args()
|
|
||||||
if not options.api_key:
|
|
||||||
parser.error("no API key specified")
|
|
||||||
if len(args) != 1:
|
|
||||||
parser.error("no log file specified")
|
|
||||||
|
|
||||||
|
|
||||||
USER_API_KEY = options.api_key
|
|
||||||
CLIENT_API_KEY = options.app_api_key
|
|
||||||
API_URL = options.app_url
|
|
||||||
BATCH_SIZE = options.batch_size
|
|
||||||
|
|
||||||
|
|
||||||
def read_log_file(input):
|
|
||||||
group = {}
|
|
||||||
for line in input:
|
|
||||||
line = line.strip()
|
|
||||||
if not line:
|
|
||||||
if group:
|
|
||||||
yield group
|
|
||||||
group = {}
|
|
||||||
continue
|
|
||||||
name, value = line.split('=', 1)
|
|
||||||
group[name] = value
|
|
||||||
if group:
|
|
||||||
yield group
|
|
||||||
|
|
||||||
|
|
||||||
def encode_params(data):
|
|
||||||
encoded_body = StringIO()
|
|
||||||
encoded_file = gzip.GzipFile(mode='w', fileobj=encoded_body)
|
|
||||||
encoded_file.write(urllib.urlencode(data))
|
|
||||||
encoded_file.close()
|
|
||||||
return encoded_body.getvalue()
|
|
||||||
|
|
||||||
|
|
||||||
def submit_data(i, entries):
|
|
||||||
if not entries:
|
|
||||||
return True
|
|
||||||
params = { 'user': USER_API_KEY, 'client': CLIENT_API_KEY }
|
|
||||||
print 'Submitting... (entries from %d to %d)' % (i, i + len(entries) - 1)
|
|
||||||
i = 0
|
|
||||||
for entry in [e for e in entries if e['LENGTH'] >= 40 and len(e['FINGERPRINT'])>100]:
|
|
||||||
if 'MBID' not in entry and 'PUID' not in entry or int(entry.get('LENGTH', '0')) <= 0:
|
|
||||||
continue
|
|
||||||
if 'MBID' in entry:
|
|
||||||
print ' MBID ', entry['MBID'], entry['FINGERPRINT'][:20] + '...'
|
|
||||||
for mbid in entry['MBID'].split(','):
|
|
||||||
params['mbid.%d' % i] = mbid
|
|
||||||
if 'PUID' in entry:
|
|
||||||
print ' PUID ', entry['PUID'], entry['FINGERPRINT'][:20] + '...'
|
|
||||||
params['puid.%d' % i] = entry['PUID']
|
|
||||||
params['fingerprint.%d' % i] = entry['FINGERPRINT']
|
|
||||||
params['length.%d' % i] = entry['LENGTH']
|
|
||||||
if 'BITRATE' in entry:
|
|
||||||
params['bitrate.%d' % i] = entry['BITRATE']
|
|
||||||
if 'FORMAT' in entry:
|
|
||||||
params['format.%d' % i] = entry['FORMAT']
|
|
||||||
i += 1
|
|
||||||
data = encode_params(params)
|
|
||||||
request = urllib2.Request(API_URL, data, headers={'Content-Encoding': 'gzip'})
|
|
||||||
try:
|
|
||||||
urllib2.urlopen(request)
|
|
||||||
except urllib2.HTTPError, e:
|
|
||||||
print e
|
|
||||||
for line in e.readlines():
|
|
||||||
print line.rstrip()
|
|
||||||
return False
|
|
||||||
except urllib2.URLError, e:
|
|
||||||
print e
|
|
||||||
return False
|
|
||||||
except socket.error, e:
|
|
||||||
print e
|
|
||||||
return False
|
|
||||||
print 'OK'
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
batch = []
|
|
||||||
i = options.start
|
|
||||||
j = 0
|
|
||||||
for entry in read_log_file(open(args[0]) if args[0] != '-' else sys.stdin):
|
|
||||||
j += 1
|
|
||||||
if j < options.start:
|
|
||||||
continue
|
|
||||||
batch.append(entry)
|
|
||||||
if len(batch) >= BATCH_SIZE:
|
|
||||||
submit_data(i, batch)
|
|
||||||
i = j
|
|
||||||
batch = []
|
|
||||||
time.sleep(0.1)
|
|
||||||
submit_data(i, batch)
|
|
||||||
|
|
396
3rdparty/chromaprint/tools/learn_filters.cpp
vendored
396
3rdparty/chromaprint/tools/learn_filters.cpp
vendored
@ -1,396 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/algorithm/string.hpp>
|
|
||||||
#include <boost/dynamic_bitset.hpp>
|
|
||||||
#include "ext/ffmpeg_decoder.h"
|
|
||||||
#include "ext/image_utils.h"
|
|
||||||
#include "audio_processor.h"
|
|
||||||
#include "chroma.h"
|
|
||||||
#include "spectral_centroid.h"
|
|
||||||
#include "chroma_normalizer.h"
|
|
||||||
#include "chroma_resampler.h"
|
|
||||||
#include "chroma_filter.h"
|
|
||||||
#include "fft.h"
|
|
||||||
#include "audio_processor.h"
|
|
||||||
#include "image.h"
|
|
||||||
#include "integral_image.h"
|
|
||||||
#include "image_builder.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "filter.h"
|
|
||||||
#include "lloyds.h"
|
|
||||||
#include "classifier.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace Chromaprint;
|
|
||||||
namespace fs = boost::filesystem;
|
|
||||||
|
|
||||||
typedef vector<string> string_vector;
|
|
||||||
typedef vector<double> double_vector;
|
|
||||||
|
|
||||||
string_vector FindAudioFiles(const char *dirname)
|
|
||||||
{
|
|
||||||
string_vector result;
|
|
||||||
fs::path path(dirname);
|
|
||||||
fs::directory_iterator end_iter;
|
|
||||||
for (fs::directory_iterator dir_iter(path); dir_iter != end_iter; ++dir_iter) {
|
|
||||||
if (fs::is_regular_file(dir_iter->status())) {
|
|
||||||
string filename = dir_iter->path().string();
|
|
||||||
if (boost::ends_with(filename, ".mp3") || boost::ends_with(filename, ".wma") || boost::ends_with(filename, ".wav")) {
|
|
||||||
result.push_back(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort(result.begin(), result.end());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<string_vector> GenerateFilePairs(const vector<string> &files)
|
|
||||||
{
|
|
||||||
string last_name;
|
|
||||||
vector<string_vector> result;
|
|
||||||
for (int i = 0; i < files.size(); i++) {
|
|
||||||
string name = fs::basename(files[i]);
|
|
||||||
name = name.substr(0, name.find_first_of('-'));
|
|
||||||
if (last_name != name) {
|
|
||||||
result.push_back(string_vector());
|
|
||||||
last_name = name;
|
|
||||||
}
|
|
||||||
result.back().push_back(files[i]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<int> MultiMapValues(const multimap<int, int> &data, const int &key)
|
|
||||||
{
|
|
||||||
pair<multimap<int, int>::const_iterator, multimap<int, int>::const_iterator> range = data.equal_range(key);
|
|
||||||
vector<int> result;
|
|
||||||
for (multimap<int, int>::const_iterator i = range.first; i != range.second; ++i) {
|
|
||||||
result.push_back((*i).second);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const int SAMPLE_RATE = 11025;
|
|
||||||
static const int FRAME_SIZE = 4096;
|
|
||||||
static const int OVERLAP = FRAME_SIZE - FRAME_SIZE / 3;// 2720;
|
|
||||||
static const int MIN_FREQ = 28;
|
|
||||||
static const int MAX_FREQ = 3520;
|
|
||||||
static const int MAX_FILTER_WIDTH = 16;
|
|
||||||
/*static const int OVERLAP = FRAME_SIZE - FRAME_SIZE / 2;// 2720;
|
|
||||||
static const int MIN_FREQ = 300;
|
|
||||||
static const int MAX_FREQ = 5300;
|
|
||||||
static const int MAX_FILTER_WIDTH = 20;*/
|
|
||||||
|
|
||||||
static const int TRAINING_SET_SIZE = 60000;
|
|
||||||
|
|
||||||
void PrintRate(const std::string &name, const std::vector<int> &values, int scale)
|
|
||||||
{
|
|
||||||
cout << name << " = [";
|
|
||||||
for (int j = 0; j < 32; j++) {
|
|
||||||
double rate = double(values[j]) / scale;
|
|
||||||
if (j != 0) std::cout << ", ";
|
|
||||||
std::cout << rate;
|
|
||||||
}
|
|
||||||
cout << "]\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FP_TYPE_CHROMA 1
|
|
||||||
#define FP_TYPE_CENTROID 2
|
|
||||||
#define FP_TYPE FP_TYPE_CHROMA
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
Chromaprint::ImageBuilder image_builder;
|
|
||||||
#if FP_TYPE == FP_TYPE_CHROMA
|
|
||||||
Chromaprint::ChromaNormalizer chroma_normalizer(&image_builder);
|
|
||||||
static const double kChromaFilterCoeffs[] = { 0.25, 0.75, 1.0, 0.75, 0.25 };
|
|
||||||
Chromaprint::ChromaFilter chroma_filter(kChromaFilterCoeffs, 5, &chroma_normalizer);
|
|
||||||
Chromaprint::Chroma chroma(MIN_FREQ, MAX_FREQ, FRAME_SIZE, SAMPLE_RATE, &chroma_filter);
|
|
||||||
//chroma.set_interpolate(true);
|
|
||||||
Chromaprint::FFT fft(FRAME_SIZE, OVERLAP, &chroma);
|
|
||||||
#elif FP_TYPE == FP_TYPE_CHROMA
|
|
||||||
Chromaprint::SpectralCentroid centroid(16, MIN_FREQ, MAX_FREQ, FRAME_SIZE, SAMPLE_RATE, &image_builder);
|
|
||||||
Chromaprint::FFT fft(FRAME_SIZE, OVERLAP, ¢roid);
|
|
||||||
#endif
|
|
||||||
Chromaprint::AudioProcessor processor(SAMPLE_RATE, &fft);
|
|
||||||
|
|
||||||
cout << "Loading audio files\n";
|
|
||||||
vector<string_vector> files = GenerateFilePairs(FindAudioFiles(argv[1]));
|
|
||||||
vector<int> groups;
|
|
||||||
multimap<int, int> reverse_groups;
|
|
||||||
vector<Chromaprint::Image *> images;
|
|
||||||
vector<Chromaprint::IntegralImage *> integral_images;
|
|
||||||
for (int i = 0; i < files.size(); i++) {
|
|
||||||
//cout << i << ".\n";
|
|
||||||
for (int j = 0; j < files[i].size(); j++) {
|
|
||||||
cout << " - " << files[i][j] << "\n";
|
|
||||||
Decoder decoder(files[i][j]);
|
|
||||||
if (!decoder.Open()) {
|
|
||||||
cerr << "ERROR: " << decoder.LastError() << "\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#if FP_TYPE == FP_TYPE_CHROMA
|
|
||||||
Image *image = new Image(12);
|
|
||||||
#elif FP_TYPE == FP_TYPE_CENTROID
|
|
||||||
Image *image = new Image(16);
|
|
||||||
#endif
|
|
||||||
processor.Reset(decoder.SampleRate(), decoder.Channels());
|
|
||||||
fft.Reset();
|
|
||||||
#if FP_TYPE == FP_TYPE_CHROMA
|
|
||||||
chroma.Reset();
|
|
||||||
chroma_filter.Reset();
|
|
||||||
chroma_normalizer.Reset();
|
|
||||||
#elif FP_TYPE == FP_TYPE_CENTROID
|
|
||||||
centroid.Reset();
|
|
||||||
#endif
|
|
||||||
image_builder.Reset(image);
|
|
||||||
decoder.Decode(&processor);
|
|
||||||
processor.Flush();
|
|
||||||
//ExportTextImage(image, files[i][j] + ".img.txt");
|
|
||||||
//Chromaprint::ExportImage(image_builder.image(), files[i][j] + ".img.png");
|
|
||||||
reverse_groups.insert(make_pair(i, images.size()));
|
|
||||||
groups.push_back(i);
|
|
||||||
images.push_back(image);
|
|
||||||
IntegralImage *int_image = new IntegralImage(image) ;
|
|
||||||
// ExportTextImage(int_image, files[i][j] + ".int_img.txt");
|
|
||||||
integral_images.push_back(int_image);
|
|
||||||
//ExportTextImage(int_image, files[i][j] + ".img.txt");
|
|
||||||
// return 1;
|
|
||||||
}
|
|
||||||
cout << images.size() << "\r";
|
|
||||||
cout.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
cout << "Training data set:\n";
|
|
||||||
cout << " - File groups: " << files.size() << "\n";
|
|
||||||
cout << " - Files: " << images.size() << "\n";
|
|
||||||
files.clear();
|
|
||||||
|
|
||||||
bool labels[TRAINING_SET_SIZE];
|
|
||||||
int data1[TRAINING_SET_SIZE];
|
|
||||||
int data2[TRAINING_SET_SIZE];
|
|
||||||
int data1_pos[TRAINING_SET_SIZE];
|
|
||||||
int data2_pos[TRAINING_SET_SIZE];
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
srand(3);
|
|
||||||
// Find matching pairs
|
|
||||||
for (; i < TRAINING_SET_SIZE / 2; i++) {
|
|
||||||
int x1 = rand() % images.size();
|
|
||||||
vector<int> group = MultiMapValues(reverse_groups, groups[x1]);
|
|
||||||
int x2;
|
|
||||||
do {
|
|
||||||
x2 = group[rand() % group.size()];
|
|
||||||
} while (x1 == x2);
|
|
||||||
size_t min_length = min(images[x1]->NumRows(), images[x2]->NumRows());
|
|
||||||
int pos = rand() % (min_length - 30);
|
|
||||||
//cout << "+ " << x1 << " " << x2 << " - " << pos << "\n";
|
|
||||||
data1[i] = x1;
|
|
||||||
data2[i] = x2;
|
|
||||||
data1_pos[i] = pos;
|
|
||||||
data2_pos[i] = pos;
|
|
||||||
labels[i] = true;
|
|
||||||
}
|
|
||||||
// Find non-matching pairs
|
|
||||||
for (; i < TRAINING_SET_SIZE; i++) {
|
|
||||||
int x2, x1 = rand() % images.size();
|
|
||||||
int pos2, pos1 = rand() % (images[x1]->NumRows() - 30);
|
|
||||||
vector<int> group = MultiMapValues(reverse_groups, groups[x1]);
|
|
||||||
set<int> group_set(group.begin(), group.end());
|
|
||||||
do {
|
|
||||||
x2 = rand() % images.size();
|
|
||||||
pos2 = rand() % (images[x2]->NumRows() - 30);
|
|
||||||
} while (group_set.count(x2) && abs(pos1 - pos2) < 50);
|
|
||||||
//cout << "- " << x1 << " " << x2 << " - " << pos1 << " " << pos2 << "\n";
|
|
||||||
data1[i] = x1;
|
|
||||||
data2[i] = x2;
|
|
||||||
data1_pos[i] = pos1;
|
|
||||||
data2_pos[i] = pos2;
|
|
||||||
labels[i] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const float maxWidth = 16.0;
|
|
||||||
const float widthScale = 1.0;
|
|
||||||
const float widthIncrement = 1.0;
|
|
||||||
|
|
||||||
const int numFilters = 6;
|
|
||||||
const int maxHeight = images[0]->NumColumns();
|
|
||||||
const int filterWidthInc[] = { 1, 1, 2, 2, 1, 3 };
|
|
||||||
const int filterHeightInc[] = { 1, 2, 1, 2, 3, 1 };
|
|
||||||
const int kNumCandidateQuantizers = 24;
|
|
||||||
|
|
||||||
double weights[TRAINING_SET_SIZE];
|
|
||||||
for (int i = 0; i < TRAINING_SET_SIZE; i++) {
|
|
||||||
weights[i] = 1.0 / TRAINING_SET_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
cout << "Computing filter responses\n";
|
|
||||||
std::vector<Filter> filters;
|
|
||||||
double *values_buffer = new double[100 * TRAINING_SET_SIZE * 2];
|
|
||||||
|
|
||||||
Filter flt;
|
|
||||||
FILE *f = fopen("filters.tmp", "wb");
|
|
||||||
for (int filter = 0; filter < numFilters; filter++) {
|
|
||||||
flt.set_type(filter);
|
|
||||||
for (int y = 0; y < maxHeight; y++) {
|
|
||||||
flt.set_y(y);
|
|
||||||
for (int h = filterHeightInc[filter]; h < maxHeight - y; h += filterHeightInc[filter]) {
|
|
||||||
flt.set_height(h);
|
|
||||||
int pw = 0;
|
|
||||||
for (int wf = filterWidthInc[filter]; wf <= maxWidth; wf += filterWidthInc[filter]) {
|
|
||||||
int w = wf;
|
|
||||||
if (pw == w)
|
|
||||||
continue;
|
|
||||||
flt.set_width(w);
|
|
||||||
fill(values_buffer, values_buffer + TRAINING_SET_SIZE * 2, 0.0);
|
|
||||||
for (int i = 0; i < TRAINING_SET_SIZE; i++) {
|
|
||||||
double value1 = flt.Apply(integral_images[data1[i]], data1_pos[i]);
|
|
||||||
double value2 = flt.Apply(integral_images[data2[i]], data2_pos[i]);
|
|
||||||
//cout << flt << " " << value1 << " [" << data1[i] << ":" << data1_pos[i] << "] " << value2 << " [" << data2[i] << ":" << data2_pos[i] << "]\n";
|
|
||||||
values_buffer[2*i+0] = value1;
|
|
||||||
values_buffer[2*i+1] = value2;
|
|
||||||
}
|
|
||||||
fwrite(values_buffer, sizeof(double), TRAINING_SET_SIZE * 2, f);
|
|
||||||
filters.push_back(flt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cout << "Filters: " << filters.size() << "\n";
|
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
f = fopen("filters.tmp", "rb");
|
|
||||||
|
|
||||||
cout << "Computing quantizers\n";
|
|
||||||
double *all_candidate_quantizers = new double[filters.size() * kNumCandidateQuantizers];
|
|
||||||
double *quantizer_ptr = all_candidate_quantizers;
|
|
||||||
fseek(f, 0, SEEK_SET);
|
|
||||||
double *values_ptr = values_buffer + 100 * TRAINING_SET_SIZE * 2;
|
|
||||||
for (int filter_i = 0; filter_i < filters.size(); filter_i++) {
|
|
||||||
int num_values = TRAINING_SET_SIZE * 2;
|
|
||||||
if (values_ptr >= values_buffer + 100 * TRAINING_SET_SIZE * 2) {
|
|
||||||
fread(values_buffer, sizeof(double), 100 * num_values, f);
|
|
||||||
values_ptr = values_buffer;
|
|
||||||
}
|
|
||||||
double_vector candidate_quantizers = lloyds(values_ptr, values_ptr + num_values, kNumCandidateQuantizers);
|
|
||||||
copy(candidate_quantizers.begin(), candidate_quantizers.end(), quantizer_ptr);
|
|
||||||
quantizer_ptr += kNumCandidateQuantizers;
|
|
||||||
values_ptr += num_values;
|
|
||||||
cout << filter_i << "\r";
|
|
||||||
cout.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
cout << "Running AdaBoost\n";
|
|
||||||
vector<Classifier> best_classifiers;
|
|
||||||
vector<double> best_classifiers_alpha;
|
|
||||||
|
|
||||||
int iteration = 0;
|
|
||||||
next_iteration:
|
|
||||||
|
|
||||||
double min_error = 1.0;
|
|
||||||
Classifier best_classifier;
|
|
||||||
boost::dynamic_bitset<> best_results(TRAINING_SET_SIZE);
|
|
||||||
fseek(f, 0, SEEK_SET);
|
|
||||||
quantizer_ptr = all_candidate_quantizers;
|
|
||||||
values_ptr = values_buffer + 100 * TRAINING_SET_SIZE * 2;
|
|
||||||
for (int filter_i = 0; filter_i < filters.size(); filter_i++) {
|
|
||||||
std::size_t num_values = TRAINING_SET_SIZE * 2;
|
|
||||||
if (values_ptr >= values_buffer + 100 * TRAINING_SET_SIZE * 2) {
|
|
||||||
fread(values_buffer, sizeof(double), 100 * num_values, f);
|
|
||||||
values_ptr = values_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quantizer quantizer(0.0, 0.0, 0.0);
|
|
||||||
for (int ti0 = 0; ti0 < kNumCandidateQuantizers - 3; ti0++) {
|
|
||||||
quantizer.set_t0(quantizer_ptr[ti0]);
|
|
||||||
for (int ti1 = ti0 + 1; ti1 < kNumCandidateQuantizers - 2; ti1++) {
|
|
||||||
quantizer.set_t1(quantizer_ptr[ti1]);
|
|
||||||
for (int ti2 = ti1 + 1; ti2 < kNumCandidateQuantizers - 1; ti2++) {
|
|
||||||
quantizer.set_t2(quantizer_ptr[ti2]);
|
|
||||||
double error = 0.0;
|
|
||||||
for (int i = 0; i < TRAINING_SET_SIZE; i++) {
|
|
||||||
int q1 = quantizer.Quantize(values_ptr[i*2 + 0]);
|
|
||||||
int q2 = quantizer.Quantize(values_ptr[i*2 + 1]);
|
|
||||||
bool match = (q1 == q2) == labels[i];
|
|
||||||
if (!match) {
|
|
||||||
error += weights[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (error < min_error) {
|
|
||||||
best_classifier = Classifier(filters[filter_i], quantizer);
|
|
||||||
min_error = error;
|
|
||||||
for (int i = 0; i < TRAINING_SET_SIZE; i++) {
|
|
||||||
int q1 = quantizer.Quantize(values_ptr[i*2 + 0]);
|
|
||||||
int q2 = quantizer.Quantize(values_ptr[i*2 + 1]);
|
|
||||||
bool match = (q1 == q2) == labels[i];
|
|
||||||
best_results[i] = match;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
quantizer_ptr += kNumCandidateQuantizers;
|
|
||||||
values_ptr += num_values;
|
|
||||||
cout << filter_i << " [" << min_error << "] \r";
|
|
||||||
cout.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
double weight_sum = 0.0;
|
|
||||||
double alpha = 0.5 * log((1.0 - min_error) / min_error);
|
|
||||||
for (int i = 0; i < TRAINING_SET_SIZE; i++) {
|
|
||||||
weights[i] *= exp(-alpha * (best_results[i] ? 1.0 : -1.0));
|
|
||||||
weight_sum += weights[i];
|
|
||||||
}
|
|
||||||
for (int i = 0; i < TRAINING_SET_SIZE; i++) {
|
|
||||||
weights[i] /= weight_sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
best_classifiers.push_back(best_classifier);
|
|
||||||
best_classifiers_alpha.push_back(alpha);
|
|
||||||
|
|
||||||
int wrong = 0;
|
|
||||||
int counts[2];
|
|
||||||
counts[0] = 0;
|
|
||||||
counts[1] = 0;
|
|
||||||
std::vector<int> bit_tp(32, 0);
|
|
||||||
std::vector<int> bit_fp(32, 0);
|
|
||||||
for (int i = 0; i < TRAINING_SET_SIZE; i++) {
|
|
||||||
double value = 0.0;
|
|
||||||
int bit_error = 0;
|
|
||||||
for (int j = 0; j < best_classifiers.size(); j++) {
|
|
||||||
int q1 = best_classifiers[j].Classify(integral_images[data1[i]], data1_pos[i]);
|
|
||||||
int q2 = best_classifiers[j].Classify(integral_images[data2[i]], data2_pos[i]);
|
|
||||||
int e = abs(q1 - q2);
|
|
||||||
bit_error += e == 3 ? 1 : e;
|
|
||||||
value += best_classifiers_alpha[j] * (q1 == q2 ? 1.0 : -1.0);
|
|
||||||
}
|
|
||||||
bool match = value > 0.0;
|
|
||||||
counts[labels[i]]++;
|
|
||||||
if (labels[i] != match) {
|
|
||||||
wrong += 1.0;
|
|
||||||
}
|
|
||||||
for (int j = 0; j < 32; j++) {
|
|
||||||
bool bit_match = bit_error <= j;
|
|
||||||
if (labels[i] && bit_match) {
|
|
||||||
bit_tp[j]++;
|
|
||||||
}
|
|
||||||
if (!labels[i] && bit_match) {
|
|
||||||
bit_fp[j]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++iteration;
|
|
||||||
cout << iteration << ". best classifier is " << best_classifier << " with error " << min_error << " (alpha " << alpha << "), final error is " << double(wrong) / TRAINING_SET_SIZE << "\n";
|
|
||||||
PrintRate("TP", bit_tp, counts[1]);
|
|
||||||
PrintRate("FP", bit_fp, counts[0]);
|
|
||||||
|
|
||||||
if (iteration < 16)
|
|
||||||
goto next_iteration;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
42
3rdparty/chromaprint/tools/match.h
vendored
42
3rdparty/chromaprint/tools/match.h
vendored
@ -1,42 +0,0 @@
|
|||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/* fingerprint matcher settings */
|
|
||||||
#define ACOUSTID_MAX_BIT_ERROR 2
|
|
||||||
#define ACOUSTID_MAX_ALIGN_OFFSET 120
|
|
||||||
|
|
||||||
#define BITCOUNT(x) __builtin_popcount(x)
|
|
||||||
|
|
||||||
inline float
|
|
||||||
match_fingerprints(const std::vector<int32_t> &a, const std::vector<int32_t> &b)
|
|
||||||
{
|
|
||||||
int i, j, topcount;
|
|
||||||
int maxsize = std::max(a.size(), b.size());
|
|
||||||
int numcounts = maxsize * 2 + 1;
|
|
||||||
int *counts = (int*)malloc(sizeof(int) * numcounts);
|
|
||||||
|
|
||||||
memset(counts, 0, sizeof(int) * numcounts);
|
|
||||||
for (i = 0; i < a.size(); i++) {
|
|
||||||
int jbegin = std::max(0, i - ACOUSTID_MAX_ALIGN_OFFSET);
|
|
||||||
int jend = std::min(b.size(), size_t(i + ACOUSTID_MAX_ALIGN_OFFSET));
|
|
||||||
for (j = jbegin; j < jend; j++) {
|
|
||||||
int biterror = BITCOUNT(a[i] ^ b[j]);
|
|
||||||
if (biterror <= ACOUSTID_MAX_BIT_ERROR) {
|
|
||||||
int offset = i - j + maxsize;
|
|
||||||
counts[offset]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
topcount = 0;
|
|
||||||
for (i = 0; i < numcounts; i++) {
|
|
||||||
if (counts[i] > topcount) {
|
|
||||||
topcount = counts[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(counts);
|
|
||||||
|
|
||||||
return (float)topcount / std::min(a.size(), b.size());
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
for FILE in `ls *-orig.wav`; do
|
|
||||||
TMPNEWFILE=`echo $FILE | perl -pe 's/-orig\..*$/-128mp3.mp3/'`
|
|
||||||
NEWFILE=`echo $FILE | perl -pe 's/-orig\..*$/-128mp3.wav/'`
|
|
||||||
if [ ! -f $NEWFILE ]; then
|
|
||||||
rm -f $NEWFILE
|
|
||||||
ffmpeg -i $FILE -ab 128000 $TMPNEWFILE
|
|
||||||
ffmpeg -i $TMPNEWFILE $NEWFILE
|
|
||||||
rm -f $TMPNEWFILE
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
13
3rdparty/chromaprint/tools/misc/prepare-32mp3.sh
vendored
13
3rdparty/chromaprint/tools/misc/prepare-32mp3.sh
vendored
@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
for FILE in `ls *-orig.wav`; do
|
|
||||||
TMPNEWFILE=`echo $FILE | perl -pe 's/-orig\..*$/-32mp3.mp3/'`
|
|
||||||
NEWFILE=`echo $FILE | perl -pe 's/-orig\..*$/-32mp3.wav/'`
|
|
||||||
if [ ! -f $NEWFILE ]; then
|
|
||||||
rm -f $NEWFILE
|
|
||||||
ffmpeg -i $FILE -ab 32000 $TMPNEWFILE
|
|
||||||
ffmpeg -i $TMPNEWFILE $NEWFILE
|
|
||||||
rm -f $TMPNEWFILE
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
13
3rdparty/chromaprint/tools/misc/prepare-64mp3.sh
vendored
13
3rdparty/chromaprint/tools/misc/prepare-64mp3.sh
vendored
@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
for FILE in `ls *-orig.wav`; do
|
|
||||||
TMPNEWFILE=`echo $FILE | perl -pe 's/-orig\..*$/-64mp3.mp3/'`
|
|
||||||
NEWFILE=`echo $FILE | perl -pe 's/-orig\..*$/-64mp3.wav/'`
|
|
||||||
if [ ! -f $NEWFILE ]; then
|
|
||||||
rm -f $NEWFILE
|
|
||||||
ffmpeg -i $FILE -ab 64000 $TMPNEWFILE
|
|
||||||
ffmpeg -i $TMPNEWFILE $NEWFILE
|
|
||||||
rm -f $TMPNEWFILE
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
13
3rdparty/chromaprint/tools/misc/prepare-64wma.sh
vendored
13
3rdparty/chromaprint/tools/misc/prepare-64wma.sh
vendored
@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
for FILE in `ls *-orig.wav`; do
|
|
||||||
TMPNEWFILE=`echo $FILE | perl -pe 's/-orig\..*$/-64wma.wma/'`
|
|
||||||
NEWFILE=`echo $FILE | perl -pe 's/-orig\..*$/-64wma.wav/'`
|
|
||||||
if [ ! -f $NEWFILE ]; then
|
|
||||||
rm -f $NEWFILE
|
|
||||||
ffmpeg -i $FILE -ab 64000 -acodec wmav2 $TMPNEWFILE
|
|
||||||
ffmpeg -i $TMPNEWFILE $NEWFILE
|
|
||||||
rm -f $TMPNEWFILE
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
17
3rdparty/chromaprint/tools/misc/prepare-gain.sh
vendored
17
3rdparty/chromaprint/tools/misc/prepare-gain.sh
vendored
@ -1,17 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
for FILE in `ls *-orig.wav`; do
|
|
||||||
TMP1FILE=`echo $FILE | perl -pe 's/-orig\..*$/-tmp.wav/'`
|
|
||||||
TMP2FILE=`echo $FILE | perl -pe 's/-orig\..*$/-tmp2.wav/'`
|
|
||||||
TMPNEWFILE=`echo $FILE | perl -pe 's/-orig\..*$/-gain.wma/'`
|
|
||||||
NEWFILE=`echo $FILE | perl -pe 's/-orig\..*$/-gain.wav/'`
|
|
||||||
if [ ! -f $NEWFILE ]; then
|
|
||||||
rm -f $NEWFILE $TMP1FILE $TMP2FILE
|
|
||||||
ffmpeg -i $FILE $TMP1FILE
|
|
||||||
sox $TMP1FILE $TMP2FILE gain -n -10
|
|
||||||
ffmpeg -i $TMP2FILE -ab 128000 -acodec wmav2 $TMPNEWFILE
|
|
||||||
ffmpeg -i $TMPNEWFILE $NEWFILE
|
|
||||||
rm -f $TMP1FILE $TMP2FILE $TMPNEWFILE
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
for FILE in `ls *-orig.wav`; do
|
|
||||||
TMP1FILE=`echo $FILE | perl -pe 's/-orig\..*$/-tmp.wav/'`
|
|
||||||
TMPNEWFILE=`echo $FILE | perl -pe 's/-orig\..*$/-resample.wma/'`
|
|
||||||
NEWFILE=`echo $FILE | perl -pe 's/-orig\..*$/-resample.wav/'`
|
|
||||||
if [ ! -f $NEWFILE ]; then
|
|
||||||
rm -f $NEWFILE $TMP1FILE $TMPNEWFILE
|
|
||||||
sox $FILE $TMP1FILE rate -l 8k
|
|
||||||
ffmpeg -i $TMP1FILE -ab 128000 -acodec wmav2 $TMPNEWFILE
|
|
||||||
ffmpeg -i $TMPNEWFILE $NEWFILE
|
|
||||||
rm -f $TMP1FILE $TMPNEWFILE
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
for FILE in `ls *.{mp3,wma,ogg}`; do
|
|
||||||
NEWFILE=`echo $FILE | perl -pe 's/\..*$/.wav/'`
|
|
||||||
rm -f $NEWFILE
|
|
||||||
ffmpeg -i $FILE $NEWFILE
|
|
||||||
rm -f $FILE
|
|
||||||
done
|
|
||||||
|
|
9
3rdparty/chromaprint/tools/misc/prepare.sh
vendored
9
3rdparty/chromaprint/tools/misc/prepare.sh
vendored
@ -1,9 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
cp orig/*.wav .
|
|
||||||
./prepare-32mp3.sh
|
|
||||||
./prepare-64mp3.sh
|
|
||||||
./prepare-128mp3.sh
|
|
||||||
./prepare-64wma.sh
|
|
||||||
./prepare-gain.sh
|
|
||||||
./prepare-wav.sh
|
|
35
3rdparty/chromaprint/tools/resample.cpp
vendored
35
3rdparty/chromaprint/tools/resample.cpp
vendored
@ -1,35 +0,0 @@
|
|||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "ext/ffmpeg_decoder.h"
|
|
||||||
#include "ext/audio_dumper.h"
|
|
||||||
#include "audio_processor.h"
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc < 2) {
|
|
||||||
cerr << "Usage: " << argv[0] << " FILENAME\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
string file_name(argv[1]);
|
|
||||||
cout << "Loading file " << file_name << "\n";
|
|
||||||
|
|
||||||
Decoder decoder(file_name);
|
|
||||||
if (!decoder.Open()) {
|
|
||||||
cerr << "ERROR: " << decoder.LastError() << "\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioDumper dumper("resampled.raw");
|
|
||||||
Chromaprint::AudioProcessor processor(11025, &dumper);
|
|
||||||
processor.Reset(decoder.SampleRate(), decoder.Channels());
|
|
||||||
|
|
||||||
decoder.Decode(&processor);
|
|
||||||
processor.Flush();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
63
3rdparty/chromaprint/tools/spectrogram.cpp
vendored
63
3rdparty/chromaprint/tools/spectrogram.cpp
vendored
@ -1,63 +0,0 @@
|
|||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "ext/ffmpeg_decoder.h"
|
|
||||||
#include "ext/audio_dumper.h"
|
|
||||||
#include "audio_processor.h"
|
|
||||||
#include "chroma.h"
|
|
||||||
#include "spectrum.h"
|
|
||||||
#include "chroma_normalizer.h"
|
|
||||||
#include "chroma_resampler.h"
|
|
||||||
#include "chroma_filter.h"
|
|
||||||
#include "fft.h"
|
|
||||||
#include "audio_processor.h"
|
|
||||||
#include "image.h"
|
|
||||||
#include "image_builder.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "ext/image_utils.h"
|
|
||||||
|
|
||||||
static const int SAMPLE_RATE = 11025;
|
|
||||||
static const int FRAME_SIZE = 4096;
|
|
||||||
static const int OVERLAP = FRAME_SIZE - FRAME_SIZE / 3;// 2720;
|
|
||||||
static const int MIN_FREQ = 28;
|
|
||||||
static const int MAX_FREQ = 3520;
|
|
||||||
static const int MAX_FILTER_WIDTH = 20;
|
|
||||||
|
|
||||||
static const int kChromaFilterSize = 5;
|
|
||||||
static const double kChromaFilterCoefficients[] = { 0.25, 0.75, 1.0, 0.75, 0.25 };
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc < 3) {
|
|
||||||
cerr << "Usage: " << argv[0] << " AUDIOFILE IMAGEFILE\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
string file_name(argv[1]);
|
|
||||||
cout << "Loading file " << file_name << "\n";
|
|
||||||
|
|
||||||
Decoder decoder(file_name);
|
|
||||||
if (!decoder.Open()) {
|
|
||||||
cerr << "ERROR: " << decoder.LastError() << "\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int numBands = 72;
|
|
||||||
Chromaprint::Image image(numBands);
|
|
||||||
Chromaprint::ImageBuilder image_builder(&image);
|
|
||||||
Chromaprint::Spectrum chroma(numBands, MIN_FREQ, MAX_FREQ, FRAME_SIZE, SAMPLE_RATE, &image_builder);
|
|
||||||
Chromaprint::FFT fft(FRAME_SIZE, OVERLAP, &chroma);
|
|
||||||
Chromaprint::AudioProcessor processor(SAMPLE_RATE, &fft);
|
|
||||||
|
|
||||||
processor.Reset(decoder.SampleRate(), decoder.Channels());
|
|
||||||
decoder.Decode(&processor);
|
|
||||||
processor.Flush();
|
|
||||||
|
|
||||||
//Chromaprint::ExportTextImage(&image, argv[2]);
|
|
||||||
Chromaprint::ExportImage(&image, argv[2], 0.5);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user