Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
weefuzzy committed Mar 19, 2019
0 parents commit 721397e
Show file tree
Hide file tree
Showing 8 changed files with 371 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build
**/build/*
**/.DS_Store
59 changes: 59 additions & 0 deletions CMakeLists.txt
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 ()
11 changes: 11 additions & 0 deletions README.md
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] ..
```
Binary file added icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
267 changes: 267 additions & 0 deletions include/FluidCLIWrapper.hpp
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
11 changes: 11 additions & 0 deletions scripts/target_post.cmake
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})
11 changes: 11 additions & 0 deletions src/sines/CMakeLists.txt
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)
9 changes: 9 additions & 0 deletions src/sines/sines.cpp
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);
}

0 comments on commit 721397e

Please sign in to comment.