Compare commits
2 Commits
eb95032dfa
...
16f1d8656b
Author | SHA1 | Date |
---|---|---|
bog | 16f1d8656b | |
bog | d023146c65 |
|
@ -2,8 +2,8 @@
|
|||
Signals
|
||||
=======
|
||||
|
||||
Signal Types
|
||||
------------
|
||||
Signal primitives
|
||||
-----------------
|
||||
|
||||
MuzGen use different kind of signals for sound design.
|
||||
|
||||
|
@ -39,3 +39,60 @@ To generate a sine, we can use the ``sine`` command.
|
|||
|
||||
# sine signal with a frequency of 440 and an amplitude of 1
|
||||
[sine 440 1]
|
||||
|
||||
|
||||
Noise
|
||||
^^^^^
|
||||
|
||||
The noise command generate uniform random frames.
|
||||
|
||||
.. code-block::
|
||||
|
||||
[noise]
|
||||
|
||||
|
||||
Signal operations
|
||||
-----------------
|
||||
|
||||
The signal operation commands allows us to combine signals in
|
||||
different ways.
|
||||
|
||||
Add
|
||||
^^^
|
||||
|
||||
The ``sum`` command takes two signals as input and outputs their sum.
|
||||
|
||||
.. code-block::
|
||||
|
||||
[sum [sine 220] [sine 220]]
|
||||
|
||||
|
||||
Sub
|
||||
^^^
|
||||
|
||||
The ``sub`` command takes two signals as input and outputs their
|
||||
difference.
|
||||
|
||||
.. code-block::
|
||||
|
||||
[sub [sine 460] [sine 80]]
|
||||
|
||||
|
||||
Mul
|
||||
^^^
|
||||
|
||||
The ``mul`` command takes two signals as input and output their product.
|
||||
|
||||
.. code-block::
|
||||
|
||||
[mul 0.7 [sine 220]]
|
||||
|
||||
|
||||
Div
|
||||
^^^
|
||||
|
||||
The ``div`` command takes two signals as input and output their ratio.
|
||||
|
||||
.. code-block::
|
||||
|
||||
[div [sine 220] 2]
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
#include "Add.hpp"
|
||||
|
||||
namespace muz
|
||||
{
|
||||
/*explicit*/ Add::Add(AudioConf const& conf,
|
||||
std::unique_ptr<Signal> lhs,
|
||||
std::unique_ptr<Signal> rhs)
|
||||
: m_conf { conf }
|
||||
, m_out_left { std::vector<float>(m_conf.channels(), 0.0f) }
|
||||
, m_out_right { std::vector<float>(m_conf.channels(), 0.0f) }
|
||||
, m_lhs { std::move(lhs) }
|
||||
, m_rhs { std::move(rhs) }
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Add::~Add()
|
||||
{
|
||||
}
|
||||
|
||||
void Add::next(std::vector<float>& out) /*override*/
|
||||
{
|
||||
m_lhs->next(m_out_left);
|
||||
m_rhs->next(m_out_right);
|
||||
|
||||
assert(m_out_left.size() == m_out_right.size());
|
||||
assert(m_out_left.size() == static_cast<size_t>(m_conf.channels()));
|
||||
|
||||
for (int i=0; i<m_conf.channels(); i++)
|
||||
{
|
||||
out[i] = m_out_left[i] + m_out_right[i];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef muz_ADD_HPP
|
||||
#define muz_ADD_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "Signal.hpp"
|
||||
#include "AudioConf.hpp"
|
||||
|
||||
namespace muz
|
||||
{
|
||||
/**
|
||||
* Sum of two input signals.
|
||||
**/
|
||||
class Add: public Signal
|
||||
{
|
||||
public:
|
||||
explicit Add(AudioConf const& conf,
|
||||
std::unique_ptr<Signal> lhs,
|
||||
std::unique_ptr<Signal> rhs);
|
||||
|
||||
virtual ~Add();
|
||||
|
||||
void next(std::vector<float>& out) override;
|
||||
private:
|
||||
AudioConf m_conf;
|
||||
std::vector<float> m_out_left;
|
||||
std::vector<float> m_out_right;
|
||||
std::unique_ptr<Signal> m_lhs;
|
||||
std::unique_ptr<Signal> m_rhs;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -5,6 +5,7 @@ namespace muz
|
|||
{
|
||||
/*explicit*/ AudioEngine::AudioEngine(AudioConf const& conf)
|
||||
: m_conf { conf }
|
||||
, m_frame { std::vector<float>(m_conf.channels(), 0.0f) }
|
||||
{
|
||||
check_error(Pa_Initialize());
|
||||
}
|
||||
|
@ -80,15 +81,9 @@ namespace muz
|
|||
return {0.0f, 0.0f};
|
||||
}
|
||||
|
||||
auto frame = m_sig_queue.back()->next();
|
||||
m_sig_queue.back()->next(m_frame);
|
||||
|
||||
if (frame.empty())
|
||||
{
|
||||
pop_signal();
|
||||
return next();
|
||||
}
|
||||
|
||||
return frame;
|
||||
return m_frame;
|
||||
}
|
||||
|
||||
/*static*/ int AudioEngine::callback(void const*, void* output,
|
||||
|
@ -103,7 +98,7 @@ namespace muz
|
|||
|
||||
for (size_t i=0; i<frames_per_buffer; i++)
|
||||
{
|
||||
auto frame = engine->next();
|
||||
auto const& frame = engine->next();
|
||||
|
||||
for (float val: frame)
|
||||
{
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace muz
|
|||
PaStream* m_stream = nullptr;
|
||||
std::vector<std::unique_ptr<Signal>> m_sig_queue;
|
||||
std::mutex m_sig_mtx;
|
||||
std::vector<float> m_frame;
|
||||
|
||||
/**
|
||||
* Throws an audio_error exception if err is an error.
|
||||
|
|
|
@ -9,13 +9,22 @@ configure_file(
|
|||
|
||||
add_library(muz-lib OBJECT
|
||||
# Audio
|
||||
# =====
|
||||
Signal.cpp
|
||||
AudioEngine.cpp
|
||||
AudioConf.cpp
|
||||
# signals
|
||||
# -------
|
||||
Constant.cpp
|
||||
Sine.cpp
|
||||
Noise.cpp
|
||||
Add.cpp
|
||||
Sub.cpp
|
||||
Mul.cpp
|
||||
Div.cpp
|
||||
|
||||
# Language
|
||||
# ========
|
||||
Node.cpp
|
||||
Lexer.cpp
|
||||
Parser.cpp
|
||||
|
|
127
lib/Compiler.cpp
127
lib/Compiler.cpp
|
@ -1,6 +1,14 @@
|
|||
#include "Compiler.hpp"
|
||||
|
||||
// signals
|
||||
// -------
|
||||
#include "Constant.hpp"
|
||||
#include "Sine.hpp"
|
||||
#include "Noise.hpp"
|
||||
#include "Add.hpp"
|
||||
#include "Sub.hpp"
|
||||
#include "Mul.hpp"
|
||||
#include "Div.hpp"
|
||||
|
||||
namespace muz
|
||||
{
|
||||
|
@ -38,23 +46,8 @@ namespace muz
|
|||
compile_node(node->child(i));
|
||||
}
|
||||
|
||||
if (name == "sine")
|
||||
{
|
||||
check_cmd_arity(*node, 2);
|
||||
execute_cmd(name, node);
|
||||
|
||||
auto one = pop();
|
||||
auto signal = std::make_unique<Sine>(m_conf,
|
||||
std::move(pop()),
|
||||
std::move(one));
|
||||
push(std::move(signal));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw compile_error {
|
||||
std::string()
|
||||
+ "cannot compile unknown command '" + name + "'."
|
||||
};
|
||||
}
|
||||
} break;
|
||||
|
||||
case NODE_DIR: {
|
||||
|
@ -67,10 +60,10 @@ namespace muz
|
|||
}
|
||||
else
|
||||
{
|
||||
throw compile_error {
|
||||
std::string()
|
||||
+ "cannot compile unknown directive '" + name + "'."
|
||||
};
|
||||
format_error<compile_error>(node->line(),
|
||||
"cannot compile unknown directive '"
|
||||
+ name
|
||||
+ "'.");
|
||||
}
|
||||
|
||||
} break;
|
||||
|
@ -84,6 +77,82 @@ namespace muz
|
|||
}
|
||||
}
|
||||
|
||||
void Compiler::execute_cmd(std::string const& name,
|
||||
std::shared_ptr<Node> node)
|
||||
{
|
||||
if (name == "sine")
|
||||
{
|
||||
check_cmd_arity(*node, 2);
|
||||
|
||||
auto one = pop();
|
||||
auto signal = std::make_unique<Sine>(m_conf,
|
||||
pop(),
|
||||
std::move(one));
|
||||
push(std::move(signal));
|
||||
}
|
||||
else if (name == "noise")
|
||||
{
|
||||
check_cmd_arity(*node, 0);
|
||||
auto signal = std::make_unique<Noise>(m_conf);
|
||||
push(std::move(signal));
|
||||
}
|
||||
else if (name == "add")
|
||||
{
|
||||
check_cmd_arity(*node, 2);
|
||||
|
||||
auto rhs = pop();
|
||||
auto lhs = pop();
|
||||
|
||||
auto signal = std::make_unique<Add>(m_conf,
|
||||
std::move(lhs),
|
||||
std::move(rhs));
|
||||
push(std::move(signal));
|
||||
}
|
||||
else if (name == "sub")
|
||||
{
|
||||
check_cmd_arity(*node, 2);
|
||||
|
||||
auto rhs = pop();
|
||||
auto lhs = pop();
|
||||
|
||||
auto signal = std::make_unique<Sub>(m_conf,
|
||||
std::move(lhs),
|
||||
std::move(rhs));
|
||||
push(std::move(signal));
|
||||
}
|
||||
else if (name == "mul")
|
||||
{
|
||||
check_cmd_arity(*node, 2);
|
||||
|
||||
auto rhs = pop();
|
||||
auto lhs = pop();
|
||||
|
||||
auto signal = std::make_unique<Mul>(m_conf,
|
||||
std::move(lhs),
|
||||
std::move(rhs));
|
||||
push(std::move(signal));
|
||||
}
|
||||
else if (name == "div")
|
||||
{
|
||||
check_cmd_arity(*node, 2);
|
||||
|
||||
auto rhs = pop();
|
||||
auto lhs = pop();
|
||||
|
||||
auto signal = std::make_unique<Div>(m_conf,
|
||||
std::move(lhs),
|
||||
std::move(rhs));
|
||||
push(std::move(signal));
|
||||
}
|
||||
else
|
||||
{
|
||||
format_error<compile_error>(node->line(),
|
||||
"cannot compile unknown command '"
|
||||
+ name
|
||||
+ "'.");
|
||||
}
|
||||
}
|
||||
|
||||
void Compiler::push(std::unique_ptr<Signal> signal)
|
||||
{
|
||||
m_signals.push_back(std::move(signal));
|
||||
|
@ -100,15 +169,15 @@ namespace muz
|
|||
{
|
||||
if (node.size() - 1 != static_cast<size_t>(arity))
|
||||
{
|
||||
throw compile_error {
|
||||
std::string()
|
||||
+ "arity mismatch for '"
|
||||
+ node.child(0)->value()
|
||||
+ "': expected <"
|
||||
+ std::to_string(arity)
|
||||
+ ">, got <"
|
||||
+ std::to_string(node.size() - 1)
|
||||
+ ">."};
|
||||
format_error<compile_error>(node.line(),
|
||||
"arity mismatch for '"
|
||||
+ node.child(0)->value()
|
||||
+ "': expected <"
|
||||
+ std::to_string(arity)
|
||||
+ ">, got <"
|
||||
+ std::to_string(node.size() - 1)
|
||||
+ ">.");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace muz
|
|||
|
||||
std::vector<std::unique_ptr<Signal>> compile(std::shared_ptr<Node> node);
|
||||
void compile_node(std::shared_ptr<Node> node);
|
||||
void execute_cmd(std::string const& name, std::shared_ptr<Node> node);
|
||||
|
||||
private:
|
||||
AudioConf const& m_conf;
|
||||
|
|
|
@ -12,15 +12,11 @@ namespace muz
|
|||
{
|
||||
}
|
||||
|
||||
std::vector<float> Constant::next() /*override*/
|
||||
void Constant::next(std::vector<float>& out) /*override*/
|
||||
{
|
||||
std::vector<float> out;
|
||||
|
||||
for (int i=0; i<m_conf.channels(); i++)
|
||||
{
|
||||
out.push_back(m_value);
|
||||
out[i] = m_value;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,11 @@ namespace muz
|
|||
explicit Constant(AudioConf const& conf, float value=0.0f);
|
||||
virtual ~Constant();
|
||||
|
||||
std::vector<float> next() override;
|
||||
void next(std::vector<float>& out) override;
|
||||
private:
|
||||
AudioConf m_conf;
|
||||
float m_value;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
#include "Div.hpp"
|
||||
|
||||
namespace muz
|
||||
{
|
||||
/*explicit*/ Div::Div(AudioConf const& conf,
|
||||
std::unique_ptr<Signal> lhs,
|
||||
std::unique_ptr<Signal> rhs)
|
||||
: m_conf { conf }
|
||||
, m_out_left { std::vector<float>(m_conf.channels(), 0.0f) }
|
||||
, m_out_right { std::vector<float>(m_conf.channels(), 0.0f) }
|
||||
, m_lhs { std::move(lhs) }
|
||||
, m_rhs { std::move(rhs) }
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Div::~Div()
|
||||
{
|
||||
}
|
||||
|
||||
void Div::next(std::vector<float>& out) /*override*/
|
||||
{
|
||||
m_lhs->next(m_out_left);
|
||||
m_rhs->next(m_out_right);
|
||||
|
||||
assert(m_out_left.size() == m_out_right.size());
|
||||
assert(m_out_left.size() == static_cast<size_t>(m_conf.channels()));
|
||||
|
||||
for (int i=0; i<m_conf.channels(); i++)
|
||||
{
|
||||
out[i] = m_out_left[i] / m_out_right[i];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef muz_DIV_HPP
|
||||
#define muz_DIV_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "Signal.hpp"
|
||||
#include "AudioConf.hpp"
|
||||
|
||||
namespace muz
|
||||
{
|
||||
/**
|
||||
* Division of two input signals.
|
||||
**/
|
||||
class Div: public Signal
|
||||
{
|
||||
public:
|
||||
explicit Div(AudioConf const& conf,
|
||||
std::unique_ptr<Signal> lhs,
|
||||
std::unique_ptr<Signal> rhs);
|
||||
virtual ~Div();
|
||||
|
||||
void next(std::vector<float>& out) override;
|
||||
|
||||
private:
|
||||
AudioConf m_conf;
|
||||
std::vector<float> m_out_left;
|
||||
std::vector<float> m_out_right;
|
||||
|
||||
std::unique_ptr<Signal> m_lhs;
|
||||
std::unique_ptr<Signal> m_rhs;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
#include "Mul.hpp"
|
||||
|
||||
namespace muz
|
||||
{
|
||||
/*explicit*/ Mul::Mul(AudioConf const& conf,
|
||||
std::unique_ptr<Signal> lhs,
|
||||
std::unique_ptr<Signal> rhs)
|
||||
: m_conf { conf }
|
||||
, m_out_left { std::vector<float>(m_conf.channels(), 0.0f) }
|
||||
, m_out_right { std::vector<float>(m_conf.channels(), 0.0f) }
|
||||
, m_lhs { std::move(lhs) }
|
||||
, m_rhs { std::move(rhs) }
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Mul::~Mul()
|
||||
{
|
||||
}
|
||||
|
||||
void Mul::next(std::vector<float>& out) /*override*/
|
||||
{
|
||||
m_lhs->next(m_out_left);
|
||||
m_rhs->next(m_out_right);
|
||||
|
||||
assert(m_out_left.size() == m_out_right.size());
|
||||
assert(m_out_left.size() == static_cast<size_t>(m_conf.channels()));
|
||||
|
||||
for (int i=0; i<m_conf.channels(); i++)
|
||||
{
|
||||
out[i] = m_out_left[i] * m_out_right[i];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef muz_MUL_HPP
|
||||
#define muz_MUL_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "Signal.hpp"
|
||||
#include "AudioConf.hpp"
|
||||
|
||||
namespace muz
|
||||
{
|
||||
/**
|
||||
* Product of two input signals.
|
||||
**/
|
||||
class Mul: public Signal
|
||||
{
|
||||
public:
|
||||
explicit Mul(AudioConf const& conf,
|
||||
std::unique_ptr<Signal> lhs,
|
||||
std::unique_ptr<Signal> rhs);
|
||||
virtual ~Mul();
|
||||
|
||||
void next(std::vector<float>& out) override;
|
||||
|
||||
private:
|
||||
AudioConf m_conf;
|
||||
std::vector<float> m_out_left;
|
||||
std::vector<float> m_out_right;
|
||||
std::unique_ptr<Signal> m_lhs;
|
||||
std::unique_ptr<Signal> m_rhs;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
#include "Noise.hpp"
|
||||
|
||||
namespace muz
|
||||
{
|
||||
/*explicit*/ Noise::Noise(AudioConf const& conf)
|
||||
: m_conf { conf }
|
||||
{
|
||||
m_rand.seed(std::chrono::steady_clock::now().time_since_epoch().count());
|
||||
}
|
||||
|
||||
/*virtual*/ Noise::~Noise()
|
||||
{
|
||||
}
|
||||
|
||||
void Noise::next(std::vector<float>& out) /*override*/
|
||||
{
|
||||
float value = m_distribution(m_rand);
|
||||
|
||||
for (int i=0; i<m_conf.channels(); i++)
|
||||
{
|
||||
out[i] = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef muz_NOISE_HPP
|
||||
#define muz_NOISE_HPP
|
||||
|
||||
#include <random>
|
||||
#include <chrono>
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "AudioConf.hpp"
|
||||
#include "Signal.hpp"
|
||||
|
||||
namespace muz
|
||||
{
|
||||
/**
|
||||
* White noise signal.
|
||||
* @see Signal
|
||||
**/
|
||||
class Noise: public Signal
|
||||
{
|
||||
public:
|
||||
explicit Noise(AudioConf const& conf);
|
||||
virtual ~Noise();
|
||||
|
||||
void next(std::vector<float>& out) override;
|
||||
private:
|
||||
AudioConf m_conf;
|
||||
std::mt19937 m_rand;
|
||||
std::uniform_real_distribution<float> m_distribution {-0.5f, 0.5f};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -19,11 +19,10 @@ namespace muz
|
|||
virtual ~Signal();
|
||||
|
||||
/**
|
||||
* Get the next sample.
|
||||
* @return std::vector<float> of size N for a sample of N channels or an empty vector at end.
|
||||
*
|
||||
* Get the next frame.
|
||||
* @param out the output buffer that will contain the next frame.
|
||||
**/
|
||||
virtual std::vector<float> next() = 0;
|
||||
virtual void next(std::vector<float>& out) = 0;
|
||||
private:
|
||||
};
|
||||
}
|
||||
|
|
21
lib/Sine.cpp
21
lib/Sine.cpp
|
@ -6,6 +6,8 @@ namespace muz
|
|||
std::unique_ptr<Signal> freq,
|
||||
std::unique_ptr<Signal> amplitude)
|
||||
: m_conf { conf }
|
||||
, m_out_freq {std::vector<float> (m_conf.channels(), 0.0f)}
|
||||
, m_out_amp {std::vector<float> (m_conf.channels(), 0.0f)}
|
||||
, m_freq { std::move(freq) }
|
||||
, m_amplitude { std::move(amplitude) }
|
||||
{
|
||||
|
@ -19,31 +21,28 @@ namespace muz
|
|||
{
|
||||
}
|
||||
|
||||
std::vector<float> Sine::next() /*override*/
|
||||
void Sine::next(std::vector<float>& out) /*override*/
|
||||
{
|
||||
assert(m_freq);
|
||||
assert(m_amplitude);
|
||||
|
||||
std::vector<float> out;
|
||||
auto freqs = m_freq->next();
|
||||
auto amps = m_amplitude->next();
|
||||
m_freq->next(m_out_freq);
|
||||
m_amplitude->next(m_out_amp);
|
||||
|
||||
if (freqs.size() != amps.size()
|
||||
|| freqs.size() != m_phases.size())
|
||||
if (m_out_freq.size() != m_out_amp.size()
|
||||
|| m_out_freq.size() != m_phases.size())
|
||||
{
|
||||
throw signal_error {"cannot generate sine: channel number mismatch"};
|
||||
}
|
||||
|
||||
for (size_t i=0; i<static_cast<size_t>(m_conf.channels()); i++)
|
||||
{
|
||||
float const value = amps[i] * std::sin(m_phases[i]);
|
||||
float const value = m_out_amp[i] * std::sin(m_phases[i]);
|
||||
|
||||
m_phases[i] += 2 * M_PI * freqs[i]
|
||||
m_phases[i] += 2 * M_PI * m_out_freq[i]
|
||||
/ static_cast<float>(m_conf.samplerate());
|
||||
|
||||
out.push_back(value);
|
||||
out[i] = value;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,12 @@ namespace muz
|
|||
std::unique_ptr<Signal> amplitude);
|
||||
virtual ~Sine();
|
||||
|
||||
std::vector<float> next() override;
|
||||
void next(std::vector<float>& out) override;
|
||||
private:
|
||||
AudioConf const& m_conf;
|
||||
std::vector<float> m_out_freq;
|
||||
std::vector<float> m_out_amp;
|
||||
|
||||
std::unique_ptr<Signal> m_freq;
|
||||
std::unique_ptr<Signal> m_amplitude;
|
||||
std::vector<float> m_phases;
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
#include "Sub.hpp"
|
||||
|
||||
namespace muz
|
||||
{
|
||||
/*explicit*/ Sub::Sub(AudioConf const& conf,
|
||||
std::unique_ptr<Signal> lhs,
|
||||
std::unique_ptr<Signal> rhs)
|
||||
: m_conf { conf }
|
||||
, m_out_left { std::vector<float>(m_conf.channels(), 0.0f) }
|
||||
, m_out_right { std::vector<float>(m_conf.channels(), 0.0f) }
|
||||
, m_lhs { std::move(lhs) }
|
||||
, m_rhs { std::move(rhs) }
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Sub::~Sub()
|
||||
{
|
||||
}
|
||||
|
||||
void Sub::next(std::vector<float>& out) /*override*/
|
||||
{
|
||||
m_lhs->next(m_out_left);
|
||||
m_rhs->next(m_out_right);
|
||||
|
||||
assert(m_out_left.size() == m_out_right.size());
|
||||
assert(m_out_left.size() == static_cast<size_t>(m_conf.channels()));
|
||||
|
||||
for (int i=0; i<m_conf.channels(); i++)
|
||||
{
|
||||
out[i] = m_out_left[i] - m_out_right[i];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef muz_SUB_HPP
|
||||
#define muz_SUB_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "Signal.hpp"
|
||||
#include "AudioConf.hpp"
|
||||
|
||||
namespace muz
|
||||
{
|
||||
/**
|
||||
* Substraction of two input signals.
|
||||
**/
|
||||
class Sub: public Signal
|
||||
{
|
||||
public:
|
||||
explicit Sub(AudioConf const& conf,
|
||||
std::unique_ptr<Signal> lhs,
|
||||
std::unique_ptr<Signal> rhs);
|
||||
virtual ~Sub();
|
||||
|
||||
void next(std::vector<float>& out) override;
|
||||
|
||||
private:
|
||||
AudioConf m_conf;
|
||||
std::vector<float> m_out_left;
|
||||
std::vector<float> m_out_right;
|
||||
std::unique_ptr<Signal> m_lhs;
|
||||
std::unique_ptr<Signal> m_rhs;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue