Merge branch 'dev'
This commit is contained in:
@@ -1 +1 @@
|
||||
-I ./include -std=c++11
|
||||
-I ./include -I ./external/Catch/include/ -std=c++11
|
||||
|
||||
+81
-13
@@ -3,28 +3,96 @@ set(CMAKE_CXX_STANDARD 11)
|
||||
# Set the project name
|
||||
project (concatenator)
|
||||
|
||||
set(Boost_USE_STATIC_LIBS OFF)
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||
find_package(Boost 1.60.0 COMPONENTS program_options log log_setup thread date_time filesystem system)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
||||
|
||||
###############################################################################
|
||||
### Boost Settings
|
||||
find_package(Boost 1.60.0 COMPONENTS program_options log log_setup thread date_time filesystem system REQUIRED)
|
||||
find_package(LibSndFile REQUIRED)
|
||||
|
||||
if (NOT FO_BOOST_STATIC_LINK)
|
||||
add_definitions(-DBOOST_ALL_NO_LIB -DBOOST_ALL_DYN_LINK -DBOOST_LOG_DYN_LINK)
|
||||
endif()
|
||||
|
||||
set(Boost_USE_STATIC_LIBS OFF)
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||
###############################################################################
|
||||
|
||||
# Set build flags
|
||||
set(CMAKE_CXX_FLAGS "-g -Wall ")
|
||||
set(CMAKE_CXX_FLAGS "-g -Wall")
|
||||
# Set cmake to output executable to the bin directory
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
include_directories(include)
|
||||
|
||||
# Find all the source fies in the src directory
|
||||
file(GLOB SOURCES "src/*.cpp")
|
||||
|
||||
# Build the executable from the source files found
|
||||
if(Boost_FOUND)
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
add_executable(concatenator ${SOURCES})
|
||||
target_link_libraries(concatenator ${Boost_LIBRARIES})
|
||||
|
||||
set(CONCATENATOR_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src)
|
||||
set(CONCATENATOR_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
|
||||
set(CONCATENATOR_TEST_DIR ${PROJECT_SOURCE_DIR}/test)
|
||||
|
||||
set(CONCATENATOR_SOURCE_FILES
|
||||
${CONCATENATOR_SOURCE_DIR}/Concatenator.cpp
|
||||
${CONCATENATOR_SOURCE_DIR}/AudioDatabase.cpp
|
||||
${CONCATENATOR_SOURCE_DIR}/AudioFile.cpp
|
||||
${CONCATENATOR_SOURCE_DIR}/Logger.cpp
|
||||
${CONCATENATOR_SOURCE_DIR}/ArgumentParser.cpp
|
||||
)
|
||||
set(CONCATENATOR_HEADER_FILES
|
||||
${CONCATENATOR_INCLUDE_DIR}/ArgumentParser.h
|
||||
${CONCATENATOR_INCLUDE_DIR}/AudioDatabase.h
|
||||
${CONCATENATOR_INCLUDE_DIR}/AudioFile.h
|
||||
${CONCATENATOR_INCLUDE_DIR}/Logger.h
|
||||
)
|
||||
set(CONCATENATOR_TEST_SOURCES
|
||||
${CONCATENATOR_TEST_DIR}/Concatenator_Test.cpp
|
||||
${CONCATENATOR_TEST_DIR}/Basic_Tests.cpp
|
||||
)
|
||||
|
||||
include_directories(${CONCATENATOR_INCLUDE_DIR})
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
include_directories(${LIBSNDFILE_INCLUDE_DIR})
|
||||
add_subdirectory(external)
|
||||
|
||||
add_executable(concatenator ${CONCATENATOR_SOURCE_FILES} ${CONCATENATOR_HEADER_FILES})
|
||||
|
||||
# Link to external libraries
|
||||
target_link_libraries(concatenator ${Boost_LIBRARIES})
|
||||
target_link_libraries(concatenator ${LIBSNDFILE_LIBRARIES})
|
||||
|
||||
# Test build options (this code adapted from: https://github.com/ComicSansMS/GhulbusBase/blob/master/CMakeLists.txt)
|
||||
option(BUILD_TESTS "Determines whether to build tests." ON)
|
||||
if(BUILD_TESTS)
|
||||
enable_testing()
|
||||
|
||||
if(NOT TARGET Catch)
|
||||
include(ExternalProject)
|
||||
if(WIN32)
|
||||
set(FETCH_EXTERNAL_CATCH
|
||||
URL https://github.com/philsquared/Catch/archive/v1.2.1-develop.12.zip
|
||||
URL_HASH MD5=cda228922a1c9248364c99a3ff9cd9fa)
|
||||
else()
|
||||
set(FETCH_EXTERNAL_CATCH
|
||||
URL https://github.com/philsquared/Catch/archive/v1.2.1-develop.12.tar.gz
|
||||
URL_HASH MD5=a8dfb7be899a6e7fb30bd55d53426122)
|
||||
endif()
|
||||
ExternalProject_Add(Catch-External
|
||||
PREFIX ${CMAKE_BINARY_DIR}/external/Catch
|
||||
${FETCH_EXTERNAL_CATCH}
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/external/Catch/src/Catch-External/single_include/catch.hpp
|
||||
${CMAKE_BINARY_DIR}/external/Catch/include/catch.hpp
|
||||
)
|
||||
add_library(Catch INTERFACE)
|
||||
add_dependencies(Catch Catch-External)
|
||||
|
||||
target_include_directories(Catch INTERFACE ${CMAKE_BINARY_DIR}/external/Catch/include)
|
||||
endif()
|
||||
|
||||
|
||||
add_executable(Concatenator_Test ${CONCATENATOR_TEST_SOURCES})
|
||||
target_link_libraries(Concatenator_Test Catch)
|
||||
add_test(NAME TestBase COMMAND Concatenator_Test)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# - Try to find libsndfile
|
||||
# Once done, this will define
|
||||
#
|
||||
# LIBSNDFILE_FOUND - system has libsndfile
|
||||
# LIBSNDFILE_INCLUDE_DIRS - the libsndfile include directories
|
||||
# LIBSNDFILE_LIBRARIES - link these to use libsndfile
|
||||
|
||||
# Use pkg-config to get hints about paths
|
||||
find_package(PkgConfig QUIET)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(LIBSNDFILE_PKGCONF sndfile)
|
||||
endif(PKG_CONFIG_FOUND)
|
||||
|
||||
# Include dir
|
||||
find_path(LIBSNDFILE_INCLUDE_DIR
|
||||
NAMES sndfile.h
|
||||
PATHS ${LIBSNDFILE_PKGCONF_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# Library
|
||||
find_library(LIBSNDFILE_LIBRARY
|
||||
NAMES sndfile libsndfile-1
|
||||
PATHS ${LIBSNDFILE_PKGCONF_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
find_package(PackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LibSndFile DEFAULT_MSG LIBSNDFILE_LIBRARY LIBSNDFILE_INCLUDE_DIR)
|
||||
|
||||
if(LIBSNDFILE_FOUND)
|
||||
set(LIBSNDFILE_LIBRARIES ${LIBSNDFILE_LIBRARY})
|
||||
set(LIBSNDFILE_INCLUDE_DIRS ${LIBSNDFILE_INCLUDE_DIR})
|
||||
endif(LIBSNDFILE_FOUND)
|
||||
|
||||
mark_as_advanced(LIBSNDFILE_LIBRARY LIBSNDFILE_LIBRARIES LIBSNDFILE_INCLUDE_DIR LIBSNDFILE_INCLUDE_DIRS)
|
||||
Vendored
@@ -1,7 +1,13 @@
|
||||
#include <iostream>
|
||||
#include "boost/program_options.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
namespace po = boost::program_options;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
class ArgumentParser {
|
||||
public:
|
||||
@@ -10,12 +16,25 @@ class ArgumentParser {
|
||||
ArgumentParser(const ArgumentParser&);
|
||||
ArgumentParser& operator=(const ArgumentParser&);
|
||||
int parseargs(int argc, char** argv);
|
||||
po::variables_map::size_type count(char const *ref);
|
||||
|
||||
const po::variable_value& operator [](char const *b) const;
|
||||
//std::string& operator [](char const *b);
|
||||
|
||||
private:
|
||||
// Stores values for arguments parsed from the command line
|
||||
po::variables_map vm;
|
||||
//Create a positional options object for parsing input, output etc
|
||||
//positional arguments from command line.
|
||||
po::positional_options_description positionalOptions;
|
||||
//
|
||||
po::variables_map vm;
|
||||
po::options_description desc;
|
||||
};
|
||||
|
||||
class ConcatenatorArgParse : public ArgumentParser {
|
||||
public:
|
||||
vector<string> get_analyses() { return (*this)["analyses"].as<vector<string>>(); }
|
||||
string get_source_db() { return (*this)["source"].as<string>(); }
|
||||
string get_target_db() { return (*this)["target"].as<string>(); }
|
||||
fs::path get_tar_audio_dir() { return ((*this)["tar_audio"].empty() ? fs::path("") : fs::path((*this)["tar_audio"].as<string>())); }
|
||||
fs::path get_src_audio_dir() { return ((*this)["src_audio"].empty() ? fs::path("") : fs::path((*this)["src_audio"].as<string>())); }
|
||||
};
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "logger.h"
|
||||
|
||||
using std::string;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::list;
|
||||
using std::vector;
|
||||
|
||||
/*!
|
||||
* A class that encapsulates a collection of AudioFile objects in order to
|
||||
* perform analysis and synthesis operations on batches of audio files.
|
||||
*/
|
||||
|
||||
class AudioDatabase {
|
||||
public:
|
||||
AudioDatabase(
|
||||
const std::string database_dir,
|
||||
vector<string>& analyses,
|
||||
Logger* log
|
||||
);
|
||||
void load_database(boost::filesystem::path source_dir, bool reanalyse=false);
|
||||
|
||||
private:
|
||||
boost::filesystem::path database_dir;
|
||||
boost::filesystem::path audio_dir;
|
||||
// Define a set that stores the locations of audiofiles in the database.
|
||||
std::set<boost::filesystem::path> audio_file_set;
|
||||
std::map<string, boost::filesystem::path> database_dirs;
|
||||
Logger* log;
|
||||
|
||||
void validate_analysis_list();
|
||||
bool validate_filetype(const boost::filesystem::path& filepath);
|
||||
void create_subdirs();
|
||||
void organise_audio(boost::filesystem::path source_dir, bool symlink=true);
|
||||
void register_audio();
|
||||
};
|
||||
|
||||
/*! A function that determines whether a string value is found in the container.
|
||||
*/
|
||||
template<typename container>
|
||||
bool in_array(string &value, const container &array)
|
||||
{
|
||||
boost::algorithm::to_upper(value);
|
||||
return std::find(array.begin(), array.end(), value) != array.end();
|
||||
}
|
||||
|
||||
/*! Check that analysis strings provided are supported by the database object
|
||||
|
||||
\param iterator - An iterator pointing to where to begin checking strings are valid.
|
||||
\param end - An iterator pointing to the point at which to stop analysing strings.
|
||||
*/
|
||||
template<typename Iter>
|
||||
std::list<string> check_analyses_valid(Iter iterator, Iter end)
|
||||
{
|
||||
static std::list<string> valid_analyses = {
|
||||
"RMS",
|
||||
"ZEROX",
|
||||
"FFT",
|
||||
"SPCCNTR",
|
||||
"SPCSPRD",
|
||||
"SPCFLUX",
|
||||
"SPCCF",
|
||||
"SPCFLATNESS",
|
||||
"F0",
|
||||
"PEAK",
|
||||
"CENTROID",
|
||||
"VARIANCE",
|
||||
"KURTOSIS",
|
||||
"SKEWNESS",
|
||||
"HARM_RATIO"
|
||||
};
|
||||
std::list<string> invalid;
|
||||
|
||||
while(iterator != end)
|
||||
{
|
||||
if(!in_array(*iterator, valid_analyses)) {
|
||||
invalid.push_back(*iterator);
|
||||
}
|
||||
++iterator;
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <string>
|
||||
#include <sndfile.hh>
|
||||
|
||||
class AudioFile {
|
||||
public:
|
||||
AudioFile(const char * &name, const int &mode=SFM_RDWR, const int &format=0, const int &channels=0, const int &samplerate=0);
|
||||
int open(const int &mode=SFM_READ, const int &format=0, const int &channels=0, const int &samplerate=0);
|
||||
protected:
|
||||
SndfileHandle file;
|
||||
SF_INFO* file_info;
|
||||
private:
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class AnalysedAudioFile : public AudioFile {
|
||||
public:
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
+6
-3
@@ -1,3 +1,5 @@
|
||||
#ifndef LOGGER_H
|
||||
#define LOGGER_H
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/log/sinks.hpp>
|
||||
#include <boost/log/sources/severity_logger.hpp>
|
||||
@@ -8,7 +10,7 @@
|
||||
class Logger {
|
||||
public:
|
||||
Logger();
|
||||
~Logger() {};
|
||||
~Logger();
|
||||
void trace(std::string str);
|
||||
void debug(std::string str);
|
||||
void info(std::string str);
|
||||
@@ -21,8 +23,8 @@ class Logger {
|
||||
static void log_formatter(boost::log::record_view const& rec, boost::log::formatting_ostream& strm);
|
||||
|
||||
// Define types for logging backends
|
||||
typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_ostream_backend> console_backend;
|
||||
typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_file_backend> file_backend;
|
||||
typedef boost::log::sinks::synchronous_sink<boost::log::sinks::text_ostream_backend> console_backend;
|
||||
typedef boost::log::sinks::synchronous_sink<boost::log::sinks::text_file_backend> file_backend;
|
||||
|
||||
// Define a sink for console output and for log file output
|
||||
boost::shared_ptr<console_backend> console_sink;
|
||||
@@ -31,3 +33,4 @@ class Logger {
|
||||
//Define a logger
|
||||
boost::log::sources::severity_logger< boost::log::trivial::severity_level > lg;
|
||||
};
|
||||
#endif
|
||||
|
||||
+29
-5
@@ -1,29 +1,53 @@
|
||||
#include "ArgumentParser.h"
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
ArgumentParser::ArgumentParser() : desc("Allowed options") {
|
||||
// Add positional arguments to specify source, target and output database locations.
|
||||
positionalOptions.add("source_db", 1);
|
||||
positionalOptions.add("target_db", 1);
|
||||
positionalOptions.add("output_db", 1);
|
||||
positionalOptions.add("source", 1);
|
||||
positionalOptions.add("target", 1);
|
||||
positionalOptions.add("output", 1);
|
||||
|
||||
// Add optional arguments to allow control over application settings from the command line.
|
||||
desc.add_options()
|
||||
("help,h", "produce help message")
|
||||
("compression", po::value<int>(), "set compression level")
|
||||
("source", po::value<string>()->required(), "Source location")
|
||||
("target", po::value<string>()->required(), "Target location")
|
||||
("output", po::value<string>()->required(), "Output location")
|
||||
("analyses,a", po::value<vector<string>>()->multitoken(), "Analysis "
|
||||
"strings specifying analyses to use for database comparison.")
|
||||
("src_audio", po::value<string>(), "Specifies the "
|
||||
"directory to create the source database and store analyses in. If "
|
||||
"not specified then the " "source directory will be used directly.")
|
||||
("tar_audio", po::value<string>(), "Specifies the "
|
||||
"directory to create the target database and store analyses in. If "
|
||||
"not specified then the target directory will be used directly.")
|
||||
;
|
||||
}
|
||||
|
||||
int ArgumentParser::parseargs(int argc, char** argv) {
|
||||
po::store(po::command_line_parser(argc, argv).options(desc).positional(positionalOptions).run(), vm);
|
||||
po::notify(vm);
|
||||
|
||||
// If help option is specified then output help message
|
||||
if (vm.count("help")) {
|
||||
cout << desc << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
po::notify(vm);
|
||||
|
||||
if (vm["analyses"].empty()) {
|
||||
throw runtime_error("No analysis strings provided as arguments.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const po::variable_value& ArgumentParser::operator [](char const *b) const {
|
||||
return vm[b];
|
||||
}
|
||||
|
||||
po::variables_map::size_type ArgumentParser::count(char const *ref) {
|
||||
return vm.count(ref);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include "AudioDatabase.h"
|
||||
#include <stdexcept>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
using namespace std;
|
||||
|
||||
AudioDatabase::AudioDatabase(
|
||||
const string database_dir,
|
||||
vector<string>& analyses,
|
||||
Logger* log
|
||||
)
|
||||
{
|
||||
this->log = log;
|
||||
|
||||
log->info("Database directory: " + database_dir);
|
||||
|
||||
// Remove duplicate strings from vector of analyses.
|
||||
std::vector<string>::iterator it;
|
||||
it = std::unique (analyses.begin(), analyses.end());
|
||||
analyses.resize(std::distance(analyses.begin(),it));
|
||||
|
||||
// Check that all analysis strings supplied refer to valid analyses.
|
||||
list<string> invalid = check_analyses_valid(analyses.begin(), analyses.end());
|
||||
if(!invalid.empty()) {
|
||||
string err = "The following analysis string(s) supplied to the AudioDatabase constructor are not valid: ";
|
||||
string invalid_strings = boost::algorithm::join(invalid, " ");
|
||||
throw std::runtime_error(err + invalid_strings);
|
||||
}
|
||||
|
||||
database_dirs.insert({"root", fs::path(database_dir)});
|
||||
this->audio_dir = fs::path(audio_dir);
|
||||
}
|
||||
|
||||
void AudioDatabase::validate_analysis_list()
|
||||
{
|
||||
}
|
||||
|
||||
void AudioDatabase::load_database(fs::path source_dir, bool reanalyse)
|
||||
{
|
||||
// Make sure the database root directory exists.
|
||||
try
|
||||
{
|
||||
if(create_directory(database_dirs["root"]))
|
||||
{
|
||||
log->debug("Database directory created: " + database_dir.string());
|
||||
}
|
||||
else if(exists(database_dirs["root"]))
|
||||
{
|
||||
log->debug("Database directory already exists: " + database_dir.string());
|
||||
}
|
||||
}
|
||||
catch(boost::filesystem::filesystem_error &e)
|
||||
{
|
||||
throw std::runtime_error("Database directory could not be created: " + database_dir.string());
|
||||
}
|
||||
|
||||
|
||||
// Create a folder hierachy used to store audio and analysis data used by the database.
|
||||
create_subdirs();
|
||||
|
||||
if(source_dir.empty()) {
|
||||
source_dir = database_dirs["audio"];
|
||||
log->debug("Source directory not provided. Setting to:" + source_dir.string());
|
||||
}
|
||||
|
||||
if(!exists(source_dir)) {
|
||||
throw std::runtime_error("Source audio directory does not exist: " + source_dir.string());
|
||||
}
|
||||
|
||||
// Only organise audio if new audio is to be added from a new location.
|
||||
if(source_dir != database_dirs["audio"]) {
|
||||
// Copy/create links to audio files that are to be used as part of the database.
|
||||
organise_audio(source_dir);
|
||||
}
|
||||
|
||||
// Find all audio in the database and store references for use later...
|
||||
register_audio();
|
||||
|
||||
}
|
||||
|
||||
void AudioDatabase::create_subdirs()
|
||||
{
|
||||
array<fs::path, 2> directory_names = {{
|
||||
fs::path("audio"),
|
||||
fs::path("data")
|
||||
}};
|
||||
|
||||
for(const auto& name : directory_names) {
|
||||
fs::path subdir = database_dirs["root"]/name;
|
||||
try
|
||||
{
|
||||
if(create_directory(subdir)) {
|
||||
log->info("Subdirectory created: " + subdir.string());
|
||||
}
|
||||
else if(exists(database_dirs["root"]))
|
||||
{
|
||||
log->info("Subdirectory already exists: " + subdir.string());
|
||||
}
|
||||
}
|
||||
catch(boost::filesystem::filesystem_error &e)
|
||||
{
|
||||
throw std::runtime_error("Subdirectory could not be created: " + database_dirs["root"].string());
|
||||
}
|
||||
database_dirs.insert({name.string(), subdir});
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioDatabase::validate_filetype(const fs::path& filepath)
|
||||
{
|
||||
// Define patterns to validate files found based on their file extensions.
|
||||
static array<string, 4> valid_filetypes = {{
|
||||
".wav",
|
||||
".aif",
|
||||
".aiff",
|
||||
".flac"
|
||||
}};
|
||||
|
||||
for(const auto& filetype : valid_filetypes)
|
||||
{
|
||||
// compare file extension with valid extension strings to find match.
|
||||
bool valid = (filetype.compare(filepath.extension().string()) == 0);
|
||||
if(valid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AudioDatabase::organise_audio(fs::path source_dir, bool symlink)
|
||||
{
|
||||
|
||||
log->info("Organising audio directory at: " + database_dirs["audio"].string());
|
||||
// Define the destination for copying/linking all valid audio files found.
|
||||
for(fs::recursive_directory_iterator iter(source_dir), end; iter != end; ++iter)
|
||||
{
|
||||
// Don't search the audio directory of the database if this is a subdirectory of the source directory provided.
|
||||
if (iter->path() == database_dirs["audio"])
|
||||
{
|
||||
iter.disable_recursion_pending();
|
||||
}
|
||||
|
||||
if(!validate_filetype(iter->path())) {
|
||||
log->debug("File: " + iter->path().string() + " isn't a supported audiofile. Skipping...");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
fs::path destination_file = database_dirs["audio"]/iter->path().filename();
|
||||
|
||||
if(symlink) {
|
||||
// Try to symlink the file to the audio directory of the database.
|
||||
try {
|
||||
fs::create_symlink(iter->path(), destination_file);
|
||||
log->debug("Linked: " + iter->path().string() + " to: " + destination_file.string());
|
||||
}
|
||||
catch(boost::filesystem::filesystem_error &e){
|
||||
// If symbolic linking fails then the file probably already exists at the location.
|
||||
log->debug("Failed to link: " + iter->path().string() + " to " + destination_file.string() + " File may already exists.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If it is in the database as a symlink, but a full copy is required
|
||||
if(fs::exists(destination_file) && !fs::is_symlink(destination_file)) {
|
||||
log->debug("File already exists: " + iter->path().string());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copy file, overwriting any previously created symbolic links.
|
||||
try {
|
||||
fs::remove(destination_file);
|
||||
fs::copy_file(iter->path(), destination_file, fs::copy_option::overwrite_if_exists);
|
||||
log->debug("Copied: " + iter->path().string() + " to: " + destination_file.string());
|
||||
}
|
||||
catch(boost::filesystem::filesystem_error &e){
|
||||
// If symbolic linking fails then the file probably already exists at the location.
|
||||
log->debug("Failed to copy source file to: " + destination_file.string() + " File may already exists.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioDatabase::register_audio()
|
||||
{
|
||||
// Clear any previous entries from set.
|
||||
audio_file_set.clear();
|
||||
for(auto& entry : boost::make_iterator_range(fs::directory_iterator(database_dirs["audio"]), {}))
|
||||
{
|
||||
if(validate_filetype(entry.path())) {
|
||||
log->info("Registered audio file: " + entry.path().string());
|
||||
audio_file_set.insert(entry.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-10
@@ -1,12 +1,23 @@
|
||||
#include <sndfile.hh>
|
||||
#include "AudioFile.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
class AudioFile {
|
||||
public:
|
||||
private:
|
||||
SndfileHandle file;
|
||||
};
|
||||
AudioFile::AudioFile(const char * &name, const int &mode, const int &format, const int &channels, const int &samplerate)
|
||||
{
|
||||
this->name = name;
|
||||
open(mode, format, channels, samplerate);
|
||||
}
|
||||
|
||||
int AudioFile::open(const int &mode, const int &format, const int &channels, const int &samplerate)
|
||||
{
|
||||
switch(mode){
|
||||
case SFM_READ: file = SndfileHandle(name);
|
||||
case SFM_WRITE: file = SndfileHandle(name, SFM_WRITE, format, channels, samplerate);
|
||||
case SFM_RDWR: file = SndfileHandle(name, SFM_RDWR, format, channels, samplerate);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
class AnalysedAudioFile : public AudioFile {
|
||||
public:
|
||||
private:
|
||||
};
|
||||
|
||||
+61
-8
@@ -1,15 +1,68 @@
|
||||
#include <iostream>
|
||||
#include "Logger.h"
|
||||
#include "logger.h"
|
||||
#include "ArgumentParser.h"
|
||||
#include "AudioDatabase.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Logger log = Logger();
|
||||
|
||||
ArgumentParser argparse = ArgumentParser();
|
||||
argparse.parseargs(argc, argv);
|
||||
log.error("My pretty little error!");
|
||||
return 0;
|
||||
namespace
|
||||
{
|
||||
const size_t ERROR_IN_COMMAND_LINE = 1;
|
||||
const size_t SUCCESS = 0;
|
||||
const size_t ERROR_UNHANDLED_EXCEPTION = 2;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// Initialize a logger object to be used for message handeling throughout
|
||||
// the program
|
||||
Logger log = Logger();
|
||||
/*
|
||||
try
|
||||
{
|
||||
*/
|
||||
|
||||
// Initialize object to parse arguments supplied by user from command
|
||||
// line
|
||||
ConcatenatorArgParse argparse = ConcatenatorArgParse();
|
||||
// Parse arguments and exit program if specified (through use of --help
|
||||
// or -h flag)
|
||||
if(argparse.parseargs(argc, argv)) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
vector<string> analyses = argparse.get_analyses();
|
||||
|
||||
// Initialize the source audio database object with arguments provided from the command line.
|
||||
AudioDatabase source_db = AudioDatabase(
|
||||
argparse.get_source_db(),
|
||||
analyses,
|
||||
&log
|
||||
);
|
||||
source_db.load_database(argparse.get_src_audio_dir());
|
||||
|
||||
/*
|
||||
// Initialize the target audio database object with arguments provided from the command line.
|
||||
AudioDatabase target_db = AudioDatabase(
|
||||
argparse.get_target_db(),
|
||||
analyses,
|
||||
&log
|
||||
);
|
||||
target_db.load_database(argparse.get_tar_audio_dir());
|
||||
*/
|
||||
|
||||
/*
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
string error("Unhandled Exception reached the top of main:\n");
|
||||
error.append(e.what());
|
||||
|
||||
log.error(error);
|
||||
throw;
|
||||
}
|
||||
*/
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,10 @@ Logger::Logger() {
|
||||
|
||||
};
|
||||
|
||||
Logger::~Logger() {
|
||||
Logger::file_sink->flush();
|
||||
Logger::console_sink->flush();
|
||||
}
|
||||
void Logger::trace(std::string str) {
|
||||
BOOST_LOG_SEV(lg, logging::trivial::trace) << str;
|
||||
}
|
||||
@@ -87,8 +91,12 @@ void Logger::warning(std::string str) {
|
||||
|
||||
void Logger::error(std::string str) {
|
||||
BOOST_LOG_SEV(lg, logging::trivial::error) << str;
|
||||
Logger::file_sink->flush();
|
||||
Logger::console_sink->flush();
|
||||
}
|
||||
|
||||
void Logger::fatal(std::string str) {
|
||||
BOOST_LOG_SEV(lg, logging::trivial::fatal) << str;
|
||||
Logger::file_sink->flush();
|
||||
Logger::console_sink->flush();
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include "catch.hpp"
|
||||
@@ -0,0 +1,4 @@
|
||||
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
|
||||
#include <catch.hpp>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user