/** * @file device_formula.cpp * @brief Function for filling generator buffer using a mathematical formula. * This is kept in its own file as exprtk.hpp takes forever to compile. * * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. * If not, see . */ #include "stmdsp.hpp" #include #include #include #include #ifndef STMDSP_DISABLE_FORMULAS #define exprtk_disable_comments #define exprtk_disable_break_continue #define exprtk_disable_sc_andor #define exprtk_disable_return_statement #define exprtk_disable_enhanced_features //#define exprtk_disable_string_capabilities #define exprtk_disable_superscalar_unroll #define exprtk_disable_rtl_io_file #define exprtk_disable_rtl_vecops //#define exprtk_disable_caseinsensitivity #include "exprtk.hpp" static std::random_device randomDevice; std::vector deviceGenLoadFormulaEval(const std::string& formulaString) { double x = 0; exprtk::symbol_table symbol_table; exprtk::function_compositor compositor (symbol_table); exprtk::expression expression; exprtk::parser parser; symbol_table.add_constants(); symbol_table.add_variable("x", x); symbol_table.add_function("random", [](double l, double h) -> double { return std::uniform_real_distribution(l, h)(randomDevice); }); compositor.add(exprtk::function_compositor::function() .name("square") .var("X") .expression("ceil(sin(pi*X))")); compositor.add(exprtk::function_compositor::function() .name("triangle") .var("X") .expression("ceil(sin(pi*X))*(X-floor(X))+ceil(-sin(pi*X))*(-X-floor(-X))")); compositor.add(exprtk::function_compositor::function() .name("pulse") .var("L") .var("X") .expression("if(X<=L,1,0)")); expression.register_symbol_table(symbol_table); parser.compile(formulaString, expression); const auto genFun = [&x, &expression] { const auto s = std::clamp(expression.value(), -1., 1.) * 2048. + 2048.; ++x; return static_cast(std::min(s, 4095.)); }; std::vector samples (stmdsp::SAMPLES_MAX); std::generate(samples.begin(), samples.end(), genFun); return samples; } #else // no formula support std::vector deviceGenLoadFormulaEval(const std::string&) { return {}; } #endif // STMDSP_DISABLE_FORMULAS