-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 721397e
Showing
8 changed files
with
371 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
build | ||
**/build/* | ||
**/.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
####### original SC Cmake file starts here | ||
cmake_minimum_required(VERSION 3.8) | ||
|
||
set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
set(CMAKE_CXX_STANDARD 14) | ||
set(CMAKE_CXX_EXTENSIONS OFF) | ||
|
||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -mavx -msse -msse2 -msse3 -msse4") | ||
# set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++") | ||
SET(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") | ||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.7" CACHE STRING "Minimum OS X deployment version") | ||
|
||
project (fluid_decomposition_cli LANGUAGES CXX) | ||
|
||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic") | ||
|
||
MACRO(SUBDIRLIST result curdir) | ||
FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) | ||
SET(dirlist "") | ||
FOREACH(child ${children}) | ||
IF(IS_DIRECTORY ${curdir}/${child}) | ||
LIST(APPEND dirlist ${child}) | ||
ENDIF() | ||
ENDFOREACH() | ||
SET(${result} ${dirlist}) | ||
ENDMACRO() | ||
|
||
set(FLUID_PATH "" CACHE PATH "The top level of the fluid_decomposition repo") | ||
set(LOCAL_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/include) | ||
|
||
get_filename_component(FLUID_ABS_PATH ${FLUID_PATH} ABSOLUTE) | ||
message(${FLUID_ABS_PATH}) | ||
# add_subdirectory("${FLUID_ABS_PATH}" build) | ||
# if (NOT DEFINED ${FLUID_DECOMP_PATH}) | ||
# message(FATAL_ERROR "Please set the path to the fluid_decomposition sources with -DFLUID_DECOMP_PATH=<path>") | ||
# endif() | ||
|
||
if (NOT (EXISTS "${FLUID_ABS_PATH}/build/fluid_decomposition-exports.cmake")) | ||
message(FATAL_ERROR "Can't find the fluid_decomposition CMake targets file at ${FLUID_ABS_PATH}/build/fluid_decomposition-expors.cmake. Please go to ${FLUID_ABS_PATH}/build and run CMake") | ||
endif() | ||
|
||
include("${FLUID_ABS_PATH}/build/fluid_decomposition-exports.cmake") | ||
|
||
add_library(FLUID_CLI_WRAPPER INTERFACE) | ||
|
||
target_include_directories (FLUID_CLI_WRAPPER INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include") | ||
|
||
target_sources(FLUID_CLI_WRAPPER | ||
INTERFACE | ||
"${CMAKE_CURRENT_SOURCE_DIR}/include/FluidCLIWrapper.hpp" | ||
) | ||
|
||
SUBDIRLIST(PROJECT_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src) | ||
foreach (project_dir ${PROJECT_DIRS}) | ||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/${project_dir}/CMakeLists.txt") | ||
message("Generating: ${project_dir}") | ||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/${project_dir}) | ||
endif () | ||
endforeach () |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
## Building Xcode project | ||
|
||
First, run CMake on your fluid_decomposition repo. | ||
|
||
Then | ||
|
||
``` | ||
mkdir build | ||
cd build | ||
cmake -GXcode -DFLUID_PATH:PATH=[path to top level of fluid decomp repo] .. | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,267 @@ | ||
|
||
#pragma once | ||
|
||
#include <clients/common/FluidBaseClient.hpp> | ||
#include <clients/common/OfflineClient.hpp> | ||
#include <clients/common/ParameterSet.hpp> | ||
#include <clients/common/ParameterTypes.hpp> | ||
|
||
#include <HISSTools_AudioFile/IAudioFile.h> | ||
#include <HISSTools_AudioFile/OAudioFile.h> | ||
|
||
#include <iostream> | ||
#include <string> | ||
#include <vector> | ||
#include <utility> | ||
|
||
namespace fluid { | ||
namespace client { | ||
|
||
class CLIBufferAdaptor : public BufferAdaptor | ||
{ | ||
|
||
public: | ||
|
||
CLIBufferAdaptor(const std::string str) | ||
: mPath(str), mWrite(false), mAcquired(false), mRank(1) | ||
{ | ||
// TODO: only read if needed!... | ||
|
||
HISSTools::IAudioFile file(mPath); | ||
|
||
if (file.isOpen()) | ||
{ | ||
resize(file.getFrames(), file.getChannels(), 1); | ||
mWrite = false; | ||
|
||
for (auto i = 0; i < file.getChannels(); i++) | ||
{ | ||
file.seek(); | ||
file.readChannel(mData[i].data(), file.getFrames(), i); | ||
} | ||
} | ||
} | ||
|
||
~CLIBufferAdaptor() | ||
{ | ||
if (mWrite) | ||
{ | ||
if (numFrames()) | ||
{ | ||
// TODO: file extensions and sample rate | ||
|
||
constexpr auto fileType = HISSTools::BaseAudioFile::kAudioFileWAVE; | ||
constexpr auto depthType = HISSTools::BaseAudioFile::kAudioFileFloat32; | ||
|
||
HISSTools::OAudioFile file(mPath, fileType, depthType, mData.size(), 44100); | ||
|
||
if (file.isOpen()) | ||
{ | ||
for (auto i = 0; i < mData.size(); i++) | ||
{ | ||
file.seek(); | ||
file.writeChannel(mData[i].data(), static_cast<uint32_t>(numFrames()), i); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
private: | ||
|
||
bool acquire() override { return !mAcquired && (mAcquired = true); } | ||
void release() override { mAcquired = false; } | ||
|
||
bool valid() const override { return numFrames(); } | ||
bool exists() const override { return true; } | ||
|
||
void resize(size_t frames, size_t channels, size_t rank) override | ||
{ | ||
std::vector<std::vector<float>> newData; | ||
|
||
newData.resize(channels * rank); | ||
for (auto &&c : newData) | ||
c.resize(frames); | ||
|
||
std::swap(newData, mData); | ||
mWrite = true; | ||
} | ||
|
||
fluid::FluidTensorView<float, 1> samps(size_t channel, size_t rankIdx) override | ||
{ | ||
return {mData[rankIdx * numChans() + channel].data(), 0, numFrames()}; | ||
} | ||
|
||
fluid::FluidTensorView<float, 1> samps(size_t offset, size_t nframes, size_t chanoffset) override | ||
{ | ||
size_t length = offset > numFrames() ? 0 : numFrames() - offset; | ||
return {mData[chanoffset].data() + offset, 0, length}; | ||
} | ||
|
||
size_t numFrames() const override { return mData.size() ? mData[0].size() : 0; } | ||
size_t numChans() const override { return mData.size() / mRank; } | ||
size_t rank() const override { return mRank; } | ||
|
||
std::string mPath; | ||
bool mWrite; | ||
bool mAcquired; | ||
size_t mRank; | ||
std::vector<std::vector<float>> mData; | ||
}; | ||
|
||
template <template <typename T> class Client> | ||
class CLIWrapper | ||
{ | ||
enum ErrorType | ||
{ | ||
kErrNone, | ||
kErrNoOption, | ||
kErrUnknownOption, | ||
kErrMissingVals, | ||
kErrValType | ||
}; | ||
|
||
using ClientType = Client<float>; | ||
using ParamDescType = typename ClientType::ParamDescType; | ||
using ParamSetType = typename ClientType::ParamSetType; | ||
using ConstString = const std::string; | ||
|
||
template <size_t N> | ||
using ParamArgType = ParamLiteralType<typename ParamDescType::template DescriptorTypeAt<N>>; | ||
|
||
static constexpr auto getDescriptors() { return ClientType::getParameterDescriptors(); } | ||
|
||
static constexpr size_t nParams = getDescriptors().size(); | ||
|
||
template <size_t N> | ||
static constexpr size_t getParamSize() { return getDescriptors().template get<N>().fixedSize; } | ||
|
||
template <size_t N> | ||
static constexpr auto getParamDefault() { return getDescriptors().template get<N>().defaultValue; } | ||
|
||
template <size_t N> | ||
static std::string getOptionName() | ||
{ | ||
std::string str(getDescriptors().template name<N>()); | ||
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::tolower(c); }); | ||
str.insert(0, "-"); | ||
|
||
return str; | ||
} | ||
|
||
template <size_t L, size_t N = 0> | ||
struct ValidateParams | ||
{ | ||
bool numeric(ConstString s, bool d = true) | ||
{ | ||
return s.find_first_not_of("0123456789.", s[0] == '-', d ? 11 : 10) == std::string::npos; | ||
}; | ||
|
||
bool isOption(ConstString s) { return s[0] == '-' && !numeric(s); } | ||
|
||
bool testString(ConstString s, LongT::type) { return numeric(s, false); } | ||
bool testString(ConstString s, FloatT::type) { return numeric(s) && s.find(".") == s.find_last_of("."); } | ||
bool testString(ConstString s, BufferT::type) { return s[0] != '-'; } | ||
|
||
template<typename T> | ||
ErrorType checkValues(int& i, int argc, const char* argv[], size_t nArgs, T) | ||
{ | ||
if (!(i + nArgs < argc)) | ||
return kErrMissingVals; | ||
|
||
for (size_t j = 1; j <= nArgs; j++) | ||
if (!testString(argv[i + j], T())) | ||
return kErrValType; | ||
|
||
i += 1 + nArgs; | ||
return kErrNone; | ||
} | ||
|
||
ErrorType validate(int& i, int argc, const char* argv[]) | ||
{ | ||
if (!isOption(argv[i])) | ||
return kErrNoOption; | ||
|
||
if (!strcmp(argv[i], getOptionName<N>().c_str())) | ||
return checkValues(i, argc, argv, getParamSize<N>(), ParamArgType<N>()); | ||
|
||
return ValidateParams<L, N + 1>().validate(i, argc, argv); | ||
} | ||
}; | ||
|
||
template <size_t N> | ||
struct ValidateParams<N, N> | ||
{ | ||
ErrorType validate(int& i, int argc, const char* argv[]) { return kErrUnknownOption; } | ||
}; | ||
|
||
template <size_t N, typename T> | ||
struct Setter | ||
{ | ||
auto fromString(ConstString s, LongT::type) { return std::stol(s); } | ||
auto fromString(ConstString s, FloatT::type) { return std::stod(s); } | ||
auto fromString(ConstString s, BufferT::type) { return BufferT::type(new CLIBufferAdaptor(s)); } | ||
|
||
auto getArgs(int argc, const char* argv[]) | ||
{ | ||
std::vector<ParamLiteralType<T>> v; | ||
std::string name = getOptionName<N>(); | ||
|
||
for (auto i = 0; i < argc; i++) | ||
{ | ||
if (!strcmp(argv[i], name.c_str())) | ||
for (auto j = 1; j <= getParamSize<N>(); j++) | ||
v.push_back(fromString(argv[i + j], ParamLiteralType<T>())); | ||
} | ||
|
||
return v; | ||
} | ||
|
||
template <size_t... Is> | ||
typename T::type val(std::vector<ParamLiteralType<T>> &v, std::index_sequence<Is...>) | ||
{ | ||
return typename T::type{v[Is]...}; | ||
} | ||
|
||
typename T::type operator()(int argc, const char* argv[]) | ||
{ | ||
auto v = getArgs(argc, argv); | ||
return v.size() ? val(v, std::make_index_sequence<getParamSize<N>()>()) : getParamDefault<N>(); | ||
} | ||
}; | ||
|
||
public: | ||
|
||
static int run(int argc, const char* argv[]) | ||
{ | ||
ParamSetType params(getDescriptors()); | ||
ClientType client(params); | ||
|
||
for (int i = 1; i < argc; ) | ||
{ | ||
switch (ValidateParams<nParams>().validate(i, argc, argv)) | ||
{ | ||
case kErrNone: break; | ||
case kErrNoOption: std::cout << "Expected option, but found " << argv[i] << "\n"; return -2; | ||
case kErrUnknownOption: std::cout << "Unknown option " << argv[i] << "\n"; return -3; | ||
case kErrMissingVals: std::cout << "Missing values for option " << argv[i] << "\n"; return -4; | ||
case kErrValType: std::cout << "Values wrong type for option " << argv[i] << "\n"; return -5; | ||
} | ||
} | ||
|
||
// TODO: figure out what to do if values require constraints | ||
|
||
params.template setParameterValues<Setter>(false, argc, argv); | ||
params.constrainParameterValues(); | ||
|
||
auto result = client.process(); | ||
|
||
if (!result.ok()) | ||
std::cout << result.message() << "\n"; | ||
|
||
return result.ok() ? 0 : -1; | ||
} | ||
}; | ||
|
||
} // namespace client | ||
} // namespace fluid |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
|
||
target_link_libraries( | ||
${PROG} | ||
PUBLIC | ||
FLUID_DECOMPOSITION | ||
FLUID_CLI_WRAPPER | ||
HISSTools_AudioFile | ||
) | ||
|
||
get_property(HEADERS TARGET FLUID_DECOMPOSITION PROPERTY INTERFACE_SOURCES) | ||
source_group(TREE "${FLUID_PATH}/include" FILES ${HEADERS}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
cmake_minimum_required(VERSION 3.8) | ||
get_filename_component(PROG ${CMAKE_CURRENT_LIST_DIR} NAME_WE) | ||
message("Configuring ${PROG}") | ||
set(FILENAME ${PROG}.cpp) | ||
|
||
add_executable( | ||
${PROG} | ||
${FILENAME} | ||
) | ||
|
||
include(${CMAKE_CURRENT_LIST_DIR}/../../scripts/target_post.cmake) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
|
||
#include <FluidCLIWrapper.hpp> | ||
#include <clients/rt/SinesClient.hpp> | ||
|
||
int main(int argc, const char* argv[]) | ||
{ | ||
using namespace fluid::client; | ||
return CLIWrapper<NRTSines>::run(argc, argv); | ||
} |