82 switch (m_operation) {
84 case MathematicalOperation::GAIN: {
85 const auto a = get_parameter_or<double>(
"gain_factor", 1.0);
86 return apply_per_channel(input, [
a](std::span<double> ch) {
87 D::linear(ch,
a, 0.0);
91 case MathematicalOperation::OFFSET: {
92 const auto b = get_parameter_or<double>(
"offset_value", 0.0);
93 return apply_per_channel(input, [
b](std::span<double> ch) {
94 D::linear(ch, 1.0,
b);
98 case MathematicalOperation::POWER: {
99 const auto exp = get_parameter_or<double>(
"exponent", 2.0);
100 return apply_per_channel(input, [exp](std::span<double> ch) {
105 case MathematicalOperation::LOGARITHMIC: {
106 const auto a = get_parameter_or<double>(
"scale", 1.0);
107 const auto b = get_parameter_or<double>(
"input_scale", 1.0);
108 const auto c = get_parameter_or<double>(
"offset", 1.0);
109 const auto base = get_parameter_or<double>(
"base", std::numbers::e);
110 return apply_per_channel(input, [
a,
b, c, base](std::span<double> ch) {
111 D::logarithmic(ch,
a,
b, c, base);
115 case MathematicalOperation::EXPONENTIAL: {
116 const auto a = get_parameter_or<double>(
"scale", 1.0);
117 const auto b = get_parameter_or<double>(
"rate", 1.0);
118 const auto base = get_parameter_or<double>(
"base", std::numbers::e);
119 return apply_per_channel(input, [
a,
b, base](std::span<double> ch) {
120 D::exponential(ch,
a,
b, base);
124 case MathematicalOperation::TRIGONOMETRIC: {
125 const auto fn = get_parameter_or<std::string>(
"trig_function",
"sin");
126 const auto freq = get_parameter_or<double>(
"frequency", 1.0);
127 const auto amp = get_parameter_or<double>(
"amplitude", 1.0);
128 const auto ph = get_parameter_or<double>(
"phase", 0.0);
130 return apply_per_channel(input, [freq, amp, ph](std::span<double> ch) {
131 D::apply_trig(ch, [](
double x) {
return std::cos(x); }, freq, amp, ph);
134 return apply_per_channel(input, [freq, amp, ph](std::span<double> ch) {
135 D::apply_trig(ch, [](
double x) {
return std::tan(x); }, freq, amp, ph);
137 return apply_per_channel(input, [freq, amp, ph](std::span<double> ch) {
138 D::apply_trig(ch, [](
double x) {
return std::sin(x); }, freq, amp, ph);
142 case MathematicalOperation::QUANTIZE: {
143 const auto bits = get_parameter_or<uint8_t>(
"bits", 16);
144 return apply_per_channel(input, [bits](std::span<double> ch) {
145 D::quantize(ch, bits);
149 case MathematicalOperation::NORMALIZE: {
150 const auto peak = get_parameter_or<double>(
"target_peak", 1.0);
151 return apply_per_channel(input, [
peak](std::span<double> ch) {
156 case MathematicalOperation::POLYNOMIAL: {
157 const auto coeffs = get_parameter_or<std::vector<double>>(
158 "coefficients", std::vector<double> { 0.0, 1.0 });
159 auto poly = std::make_shared<Nodes::Generator::Polynomial>(coeffs);
160 return apply_per_channel(input, [&poly](std::span<double> ch) {
161 std::ranges::transform(ch, ch.begin(),
162 [&poly](
double x) { return poly->process_sample(x); });
167 return create_output(input);
211 auto [channels, structure_info] = OperationHelper::extract_structured_double(input);
212 m_working_buffer.resize(channels.size());
213 for (
size_t i = 0; i < channels.size(); ++i) {
214 m_working_buffer[i].assign(channels[i].begin(), channels[i].end());
215 func(std::span<double> { m_working_buffer[i] });
217 if (this->is_in_place())
218 for (
size_t i = 0; i < channels.size(); ++i)
219 std::ranges::copy(m_working_buffer[i], channels[i].begin());
220 return create_output(
221 OperationHelper::reconstruct_from_double<InputType>(m_working_buffer, structure_info));