Compare commits

..

No commits in common. "16f1d8656b68b5f46636f36824981368e86ed598" and "eb95032dfa68254768e91198bf82d1e9e41b9123" have entirely different histories.

21 changed files with 63 additions and 509 deletions

View File

@ -2,8 +2,8 @@
Signals
=======
Signal primitives
-----------------
Signal Types
------------
MuzGen use different kind of signals for sound design.
@ -39,60 +39,3 @@ 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]

View File

@ -1,33 +0,0 @@
#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];
}
}
}

View File

@ -1,32 +0,0 @@
#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

View File

@ -5,7 +5,6 @@ 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());
}
@ -81,9 +80,15 @@ namespace muz
return {0.0f, 0.0f};
}
m_sig_queue.back()->next(m_frame);
auto frame = m_sig_queue.back()->next();
return m_frame;
if (frame.empty())
{
pop_signal();
return next();
}
return frame;
}
/*static*/ int AudioEngine::callback(void const*, void* output,
@ -98,7 +103,7 @@ namespace muz
for (size_t i=0; i<frames_per_buffer; i++)
{
auto const& frame = engine->next();
auto frame = engine->next();
for (float val: frame)
{

View File

@ -47,7 +47,6 @@ 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.

View File

@ -9,22 +9,13 @@ 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

View File

@ -1,14 +1,6 @@
#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
{
@ -46,8 +38,23 @@ namespace muz
compile_node(node->child(i));
}
execute_cmd(name, node);
if (name == "sine")
{
check_cmd_arity(*node, 2);
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: {
@ -60,10 +67,10 @@ namespace muz
}
else
{
format_error<compile_error>(node->line(),
"cannot compile unknown directive '"
+ name
+ "'.");
throw compile_error {
std::string()
+ "cannot compile unknown directive '" + name + "'."
};
}
} break;
@ -77,82 +84,6 @@ 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));
@ -169,15 +100,15 @@ namespace muz
{
if (node.size() - 1 != static_cast<size_t>(arity))
{
format_error<compile_error>(node.line(),
"arity mismatch for '"
throw compile_error {
std::string()
+ "arity mismatch for '"
+ node.child(0)->value()
+ "': expected <"
+ std::to_string(arity)
+ ">, got <"
+ std::to_string(node.size() - 1)
+ ">.");
+ ">."};
}
}
}

View File

@ -24,7 +24,6 @@ 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;

View File

@ -12,11 +12,15 @@ namespace muz
{
}
void Constant::next(std::vector<float>& out) /*override*/
std::vector<float> Constant::next() /*override*/
{
std::vector<float> out;
for (int i=0; i<m_conf.channels(); i++)
{
out[i] = m_value;
}
out.push_back(m_value);
}
return out;
}
}

View File

@ -15,11 +15,10 @@ namespace muz
explicit Constant(AudioConf const& conf, float value=0.0f);
virtual ~Constant();
void next(std::vector<float>& out) override;
std::vector<float> next() override;
private:
AudioConf m_conf;
float m_value;
};
}

View File

@ -1,33 +0,0 @@
#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];
}
}
}

View File

@ -1,33 +0,0 @@
#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

View File

@ -1,33 +0,0 @@
#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];
}
}
}

View File

@ -1,32 +0,0 @@
#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

View File

@ -1,24 +0,0 @@
#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;
}
}
}

View File

@ -1,31 +0,0 @@
#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

View File

@ -19,10 +19,11 @@ namespace muz
virtual ~Signal();
/**
* Get the next frame.
* @param out the output buffer that will contain the next frame.
* Get the next sample.
* @return std::vector<float> of size N for a sample of N channels or an empty vector at end.
*
**/
virtual void next(std::vector<float>& out) = 0;
virtual std::vector<float> next() = 0;
private:
};
}

View File

@ -6,8 +6,6 @@ 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) }
{
@ -21,28 +19,31 @@ namespace muz
{
}
void Sine::next(std::vector<float>& out) /*override*/
std::vector<float> Sine::next() /*override*/
{
assert(m_freq);
assert(m_amplitude);
m_freq->next(m_out_freq);
m_amplitude->next(m_out_amp);
std::vector<float> out;
auto freqs = m_freq->next();
auto amps = m_amplitude->next();
if (m_out_freq.size() != m_out_amp.size()
|| m_out_freq.size() != m_phases.size())
if (freqs.size() != amps.size()
|| freqs.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 = m_out_amp[i] * std::sin(m_phases[i]);
float const value = amps[i] * std::sin(m_phases[i]);
m_phases[i] += 2 * M_PI * m_out_freq[i]
m_phases[i] += 2 * M_PI * freqs[i]
/ static_cast<float>(m_conf.samplerate());
out[i] = value;
}
out.push_back(value);
}
return out;
}
}

View File

@ -18,12 +18,9 @@ namespace muz
std::unique_ptr<Signal> amplitude);
virtual ~Sine();
void next(std::vector<float>& out) override;
std::vector<float> next() 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;

View File

@ -1,33 +0,0 @@
#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];
}
}
}

View File

@ -1,32 +0,0 @@
#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