diff options
author | David Robillard <d@drobilla.net> | 2007-12-05 23:45:51 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2007-12-05 23:45:51 +0000 |
commit | a96b70b1c92b7f2622ebeff9d34c92ba089997f1 (patch) | |
tree | 732a8c2b225f619394ef5bb3d4a4a27d682409db /src/engine | |
parent | f673a148c7104b3aaee4b1332a3631ac15f5f769 (diff) | |
download | machina-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.cpp | 2 | ||||
-rw-r--r-- | src/engine/Machine.cpp | 5 | ||||
-rw-r--r-- | src/engine/MachineBuilder.cpp | 8 | ||||
-rw-r--r-- | src/engine/MachineMutation.cpp | 69 | ||||
-rw-r--r-- | src/engine/Node.cpp | 15 | ||||
-rw-r--r-- | src/engine/machina/MachineMutation.hpp | 4 | ||||
-rw-r--r-- | src/engine/machina/Node.hpp | 5 |
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); |