aboutsummaryrefslogtreecommitdiffstats
path: root/src/engine
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-12-05 23:45:51 +0000
committerDavid Robillard <d@drobilla.net>2007-12-05 23:45:51 +0000
commita96b70b1c92b7f2622ebeff9d34c92ba089997f1 (patch)
tree732a8c2b225f619394ef5bb3d4a4a27d682409db /src/engine
parentf673a148c7104b3aaee4b1332a3631ac15f5f769 (diff)
downloadmachina-a96b70b1c92b7f2622ebeff9d34c92ba089997f1.tar.gz
machina-a96b70b1c92b7f2622ebeff9d34c92ba089997f1.tar.bz2
machina-a96b70b1c92b7f2622ebeff9d34c92ba089997f1.zip
Working mutation operators.
git-svn-id: http://svn.drobilla.net/lad/machina@952 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/Loader.cpp2
-rw-r--r--src/engine/Machine.cpp5
-rw-r--r--src/engine/MachineBuilder.cpp8
-rw-r--r--src/engine/MachineMutation.cpp69
-rw-r--r--src/engine/Node.cpp15
-rw-r--r--src/engine/machina/MachineMutation.hpp4
-rw-r--r--src/engine/machina/Node.hpp5
7 files changed, 96 insertions, 12 deletions
diff --git a/src/engine/Loader.cpp b/src/engine/Loader.cpp
index 27b95fd..3b60223 100644
--- a/src/engine/Loader.cpp
+++ b/src/engine/Loader.cpp
@@ -171,7 +171,7 @@ Loader::load(const Glib::ustring& uri)
SharedPtr<Edge> edge(new Edge(src, dst));
edge->set_probability(prob);
- src->add_outgoing_edge(edge);
+ src->add_edge(edge);
} else {
cerr << "[Loader] WARNING: Ignored edge between unknown nodes "
diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp
index 7a99b58..44e8446 100644
--- a/src/engine/Machine.cpp
+++ b/src/engine/Machine.cpp
@@ -59,6 +59,9 @@ Machine::set_sink(SharedPtr<Raul::MIDISink> sink)
SharedPtr<Node>
Machine::random_node()
{
+ if (_nodes.empty())
+ return SharedPtr<Node>();
+
size_t i = rand() % _nodes.size();
// FIXME: O(n) worst case :(
@@ -79,7 +82,7 @@ Machine::random_edge()
for (size_t i = 0; i < _nodes.size() && tail->edges().empty(); ++i)
tail = random_node();
- return tail->random_edge();
+ return tail ? tail->random_edge() : SharedPtr<Edge>();
}
diff --git a/src/engine/MachineBuilder.cpp b/src/engine/MachineBuilder.cpp
index fd53487..7f0da03 100644
--- a/src/engine/MachineBuilder.cpp
+++ b/src/engine/MachineBuilder.cpp
@@ -94,16 +94,16 @@ MachineBuilder::connect_nodes(SharedPtr<Machine> m,
if (is_delay_node(tail) && tail->edges().size() == 0) {
// Tail is a delay node, just accumulate the time difference into it
set_node_duration(tail, tail->duration() + head_start_time - tail_end_time);
- tail->add_outgoing_edge(SharedPtr<Edge>(new Edge(tail, head)));
+ tail->add_edge(SharedPtr<Edge>(new Edge(tail, head)));
} else if (head_start_time == tail_end_time) {
// Connect directly
- tail->add_outgoing_edge(SharedPtr<Edge>(new Edge(tail, head)));
+ tail->add_edge(SharedPtr<Edge>(new Edge(tail, head)));
} else {
// Need to actually create a delay node
delay_node = SharedPtr<Node>(new Node());
set_node_duration(delay_node, head_start_time - tail_end_time);
- tail->add_outgoing_edge(SharedPtr<Edge>(new Edge(tail, delay_node)));
- delay_node->add_outgoing_edge(SharedPtr<Edge>(new Edge(delay_node, head)));
+ tail->add_edge(SharedPtr<Edge>(new Edge(tail, delay_node)));
+ delay_node->add_edge(SharedPtr<Edge>(new Edge(delay_node, head)));
m->add_node(delay_node);
}
diff --git a/src/engine/MachineMutation.cpp b/src/engine/MachineMutation.cpp
index 6e98ee0..3c899bc 100644
--- a/src/engine/MachineMutation.cpp
+++ b/src/engine/MachineMutation.cpp
@@ -20,6 +20,7 @@
#include "machina/Edge.hpp"
#include "machina/Machine.hpp"
#include "machina/MachineMutation.hpp"
+#include "machina/ActionFactory.hpp"
using namespace std;
@@ -28,16 +29,80 @@ namespace Mutation {
void
+Compress::mutate(Machine& machine)
+{
+ // Trim disconnected nodes
+ for (Machine::Nodes::iterator i = machine.nodes().begin(); i != machine.nodes().end() ;) {
+ Machine::Nodes::iterator next = i;
+ ++next;
+
+ if ((*i)->edges().empty())
+ machine.remove_node(*i);
+
+ i = next;
+ }
+}
+
+
+void
+AddNode::mutate(Machine& machine)
+{
+ // Create random node
+ SharedPtr<Node> node(new Node(1.0));
+ uint8_t note = rand() % 128;
+ node->set_enter_action(ActionFactory::note_on(note));
+ node->set_exit_action(ActionFactory::note_off(note));
+ machine.add_node(node);
+
+ // Add as a successor to some other random node
+ SharedPtr<Node> tail = machine.random_node();
+ if (tail && tail != node)
+ tail->add_edge(boost::shared_ptr<Edge>(new Edge(tail, node)));
+}
+
+
+void
+RemoveNode::mutate(Machine& machine)
+{
+ SharedPtr<Node> node = machine.random_node();
+ machine.remove_node(node);
+}
+
+
+void
+AdjustNode::mutate(Machine& machine)
+{
+ SharedPtr<Node> node = machine.random_node();
+ if (node) {
+ SharedPtr<MidiAction> enter_action = PtrCast<MidiAction>(node->enter_action());
+ SharedPtr<MidiAction> exit_action = PtrCast<MidiAction>(node->exit_action());
+ if (enter_action && exit_action) {
+ const uint8_t note = rand() % 128;
+ enter_action->event()[1] = note;
+ exit_action->event()[1] = note;
+ }
+ node->set_changed();
+ }
+}
+
+
+void
AddEdge::mutate(Machine& machine)
{
- cout << "ADD" << endl;
+ SharedPtr<Node> tail = machine.random_node();
+ SharedPtr<Node> head = machine.random_node();
+
+ if (tail && head && tail != head && !tail->connected_to(head))
+ tail->add_edge(boost::shared_ptr<Edge>(new Edge(tail, head)));
}
void
RemoveEdge::mutate(Machine& machine)
{
- cout << "REMOVE" << endl;
+ SharedPtr<Node> tail = machine.random_node();
+ if (tail)
+ tail->remove_edge(tail->random_edge());
}
diff --git a/src/engine/Node.cpp b/src/engine/Node.cpp
index fd784e5..0eca0e6 100644
--- a/src/engine/Node.cpp
+++ b/src/engine/Node.cpp
@@ -119,7 +119,7 @@ Node::exit(SharedPtr<Raul::MIDISink> sink, BeatTime time)
void
-Node::add_outgoing_edge(SharedPtr<Edge> edge)
+Node::add_edge(SharedPtr<Edge> edge)
{
assert(edge->tail().lock().get() == this);
@@ -128,11 +128,22 @@ Node::add_outgoing_edge(SharedPtr<Edge> edge)
void
-Node::remove_outgoing_edge(SharedPtr<Edge> edge)
+Node::remove_edge(SharedPtr<Edge> edge)
{
_edges.erase(_edges.find(edge));
}
+
+bool
+Node::connected_to(SharedPtr<Node> node)
+{
+ for (Edges::const_iterator i = _edges.begin(); i != _edges.end(); ++i)
+ if ((*i)->head() == node)
+ return true;
+
+ return false;
+}
+
void
Node::remove_edges_to(SharedPtr<Node> node)
diff --git a/src/engine/machina/MachineMutation.hpp b/src/engine/machina/MachineMutation.hpp
index 34eda30..0a9731c 100644
--- a/src/engine/machina/MachineMutation.hpp
+++ b/src/engine/machina/MachineMutation.hpp
@@ -26,6 +26,10 @@ namespace Mutation {
struct Mutation { virtual void mutate(Machine& machine) = 0; };
+struct Compress { static void mutate(Machine& machine); };
+struct AddNode { static void mutate(Machine& machine); };
+struct RemoveNode { static void mutate(Machine& machine); };
+struct AdjustNode { static void mutate(Machine& machine); };
struct AddEdge { static void mutate(Machine& machine); };
struct RemoveEdge { static void mutate(Machine& machine); };
struct AdjustEdge { static void mutate(Machine& machine); };
diff --git a/src/engine/machina/Node.hpp b/src/engine/machina/Node.hpp
index a916eb6..5926a50 100644
--- a/src/engine/machina/Node.hpp
+++ b/src/engine/machina/Node.hpp
@@ -56,9 +56,10 @@ public:
void enter(SharedPtr<Raul::MIDISink> driver, BeatTime time);
void exit(SharedPtr<Raul::MIDISink> driver, BeatTime time);
- void add_outgoing_edge(SharedPtr<Edge> edge);
- void remove_outgoing_edge(SharedPtr<Edge> edge);
+ void add_edge(SharedPtr<Edge> edge);
+ void remove_edge(SharedPtr<Edge> edge);
void remove_edges_to(SharedPtr<Node> node);
+ bool connected_to(SharedPtr<Node> node);
void write_state(Redland::Model& model);