aboutsummaryrefslogtreecommitdiffstats
path: root/src/engine
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-12-06 19:06:54 +0000
committerDavid Robillard <d@drobilla.net>2007-12-06 19:06:54 +0000
commit33e9991326a1cd90a4956f3221f5a48d03d5af89 (patch)
treec0367028d619b64e6dfcaf64cf68b158031a5d0d /src/engine
parentd0dbdee864a3d38e385906cf05c03fe4c264f5d8 (diff)
downloadmachina-33e9991326a1cd90a4956f3221f5a48d03d5af89.tar.gz
machina-33e9991326a1cd90a4956f3221f5a48d03d5af89.tar.bz2
machina-33e9991326a1cd90a4956f3221f5a48d03d5af89.zip
Added missing files.
git-svn-id: http://svn.drobilla.net/lad/machina@956 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/ActionFactory.cpp10
-rw-r--r--src/engine/Machine.cpp19
-rw-r--r--src/engine/Makefile.am4
-rw-r--r--src/engine/Node.cpp18
-rw-r--r--src/engine/Problem.cpp112
-rw-r--r--src/engine/machina/ActionFactory.hpp1
-rw-r--r--src/engine/machina/Edge.hpp2
-rw-r--r--src/engine/machina/LearnRequest.hpp6
-rw-r--r--src/engine/machina/Machine.hpp4
-rw-r--r--src/engine/machina/MidiAction.hpp11
-rw-r--r--src/engine/machina/Node.hpp4
-rw-r--r--src/engine/machina/Problem.hpp56
12 files changed, 228 insertions, 19 deletions
diff --git a/src/engine/ActionFactory.cpp b/src/engine/ActionFactory.cpp
index 4ca1a3e..6632b3c 100644
--- a/src/engine/ActionFactory.cpp
+++ b/src/engine/ActionFactory.cpp
@@ -20,6 +20,16 @@
namespace Machina {
+SharedPtr<Action>
+ActionFactory::copy(SharedPtr<Action> copy)
+{
+ SharedPtr<MidiAction> ma = PtrCast<MidiAction>(copy);
+ if (ma)
+ return SharedPtr<Action>(new MidiAction(ma->event_size(), ma->event()));
+ else
+ return SharedPtr<Action>();
+}
+
SharedPtr<Action>
ActionFactory::note_on(unsigned char note)
diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp
index 44e8446..fbda9ad 100644
--- a/src/engine/Machine.cpp
+++ b/src/engine/Machine.cpp
@@ -38,6 +38,25 @@ Machine::Machine()
}
+/** Copy a Machine.
+ *
+ * Creates a deep copy which is the 'same' machine, but with
+ * fresh state (deactivated, rewound)
+ */
+Machine::Machine(const Machine& copy)
+ : Raul::Stateful() // don't copy RDF ID
+ , _is_activated(false)
+ , _is_finished(false)
+ , _time(0)
+ , _sink(copy._sink)
+{
+ for (Nodes::const_iterator i = copy._nodes.begin(); i != copy._nodes.end(); ++i) {
+ SharedPtr<Machina::Node> node(new Machina::Node(*i->get()));
+ _nodes.push_back(node);
+ }
+}
+
+
Machine::~Machine()
{
}
diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am
index 879c00d..c46ffed 100644
--- a/src/engine/Makefile.am
+++ b/src/engine/Makefile.am
@@ -2,8 +2,8 @@ SUBDIRS = machina
lib_LTLIBRARIES = libmachina.la
-libmachina_la_CXXFLAGS = @REDLANDMM_CFLAGS@ @RAUL_CFLAGS@ @JACK_CFLAGS@ @GLIBMM_CFLAGS@
-libmachina_la_LIBADD = @REDLANDMM_LIBS@ @RAUL_LIBS@ @JACK_LIBS@ @GLIBMM_LIBS@
+libmachina_la_CXXFLAGS = @EUGENE_CFLAGS@ @REDLANDMM_CFLAGS@ @RAUL_CFLAGS@ @JACK_CFLAGS@ @GLIBMM_CFLAGS@
+libmachina_la_LIBADD = @EUGENE_LIBS@ @RAUL_LIBS@ @JACK_LIBS@ @GLIBMM_LIBS@
libmachina_la_SOURCES = \
Action.cpp \
diff --git a/src/engine/Node.cpp b/src/engine/Node.cpp
index 0eca0e6..f965aff 100644
--- a/src/engine/Node.cpp
+++ b/src/engine/Node.cpp
@@ -21,6 +21,7 @@
#include <redlandmm/Model.hpp>
#include <machina/Node.hpp>
#include <machina/Edge.hpp>
+#include <machina/ActionFactory.hpp>
namespace Machina {
@@ -35,6 +36,23 @@ Node::Node(BeatCount duration, bool initial)
}
+Node::Node(const Node& copy)
+ : Raul::Stateful() // don't copy RDF ID
+ , _is_initial(copy._is_initial)
+ , _is_selector(copy._is_selector)
+ , _is_active(false)
+ , _enter_time(0)
+ , _duration(copy._duration)
+ , _enter_action(ActionFactory::copy(copy._enter_action))
+ , _exit_action(ActionFactory::copy(copy._exit_action))
+{
+ for (Edges::const_iterator i = copy._edges.begin(); i != copy._edges.end(); ++i) {
+ SharedPtr<Edge> edge(new Edge(*i->get()));
+ _edges.push_back(edge);
+ }
+}
+
+
/** Always returns an edge, unless there are none */
SharedPtr<Edge>
Node::random_edge()
diff --git a/src/engine/Problem.cpp b/src/engine/Problem.cpp
new file mode 100644
index 0000000..f57aa15
--- /dev/null
+++ b/src/engine/Problem.cpp
@@ -0,0 +1,112 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * Machina is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Machina is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <iostream>
+#include <machina/Problem.hpp>
+#include <machina/Machine.hpp>
+#include <raul/SMFReader.hpp>
+#include <raul/midi_events.h>
+
+using namespace std;
+
+namespace Machina {
+
+
+Problem::Problem(const std::string& target_midi)
+ : _target(*this)
+{
+ Raul::SMFReader smf;
+ const bool opened = smf.open(target_midi);
+ assert(opened);
+
+ smf.seek_to_track(2); // FIXME: kluge
+
+ uint8_t buf[4];
+ uint32_t ev_size;
+ uint32_t delta_time;
+ while (smf.read_event(4, buf, &ev_size, &delta_time) >= 0) {
+ if ((buf[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
+ const uint8_t note = buf[1];
+ ++_target._note_frequency[note];
+ ++_target._n_notes;
+ }
+ }
+
+ _target.compute();
+}
+
+
+float
+Problem::fitness(Machine& machine)
+{
+ SharedPtr<Evaluator> eval(new Evaluator(*this));
+
+ machine.reset(0.0f);
+ machine.set_sink(eval);
+
+ // FIXME: timing stuff here isn't right at all...
+
+ unsigned ppqn = 19200;
+ Raul::TimeSlice time(ppqn, 120);
+ time.set_start(0);
+ time.set_length(ppqn);
+
+ while (time.start_ticks() < _target._n_notes * ppqn) {
+ machine.run(time);
+ time.set_start(time.start_ticks() + ppqn);
+ }
+
+ eval->compute();
+
+ float f = 0;
+
+ // Punish for frequency differences.
+ // Optimal fitness = 0 (max)
+ for (uint8_t i=0; i < 128; ++i)
+ f -= fabs(_target._note_frequency[i] - eval->_note_frequency[i]);
+
+ return f;
+}
+
+
+void
+Problem::Evaluator::write_event(Raul::BeatTime time,
+ size_t ev_size,
+ const uint8_t* ev) throw (std::logic_error)
+{
+ if ((ev[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
+ const uint8_t note = ev[1];
+ ++_note_frequency[note];
+ ++_n_notes;
+ }
+}
+
+
+void
+Problem::Evaluator::compute()
+{
+ for (uint8_t i=0; i < 128; ++i) {
+ if (_note_frequency[i] > 0) {
+ _note_frequency[i] /= (float)_n_notes;
+ //cout << (int)i << ":\t" << _note_frequency[i] << endl;
+ }
+ }
+}
+
+
+} // namespace Machina
+
diff --git a/src/engine/machina/ActionFactory.hpp b/src/engine/machina/ActionFactory.hpp
index b0aa1f9..f47a626 100644
--- a/src/engine/machina/ActionFactory.hpp
+++ b/src/engine/machina/ActionFactory.hpp
@@ -26,6 +26,7 @@ class Action;
namespace ActionFactory {
+ SharedPtr<Action> copy(SharedPtr<Action> copy);
SharedPtr<Action> note_on(unsigned char note);
SharedPtr<Action> note_off(unsigned char note);
}
diff --git a/src/engine/machina/Edge.hpp b/src/engine/machina/Edge.hpp
index 3f564ef..1b52dc7 100644
--- a/src/engine/machina/Edge.hpp
+++ b/src/engine/machina/Edge.hpp
@@ -31,7 +31,7 @@ namespace Machina {
class Node;
-class Edge : public Raul::Stateful, public boost::noncopyable {
+class Edge : public Raul::Stateful {
public:
Edge(WeakPtr<Node> tail, SharedPtr<Node> head)
diff --git a/src/engine/machina/LearnRequest.hpp b/src/engine/machina/LearnRequest.hpp
index 4ec22ff..f6bc60f 100644
--- a/src/engine/machina/LearnRequest.hpp
+++ b/src/engine/machina/LearnRequest.hpp
@@ -58,9 +58,11 @@ private:
LearnRequest(SharedPtr<Raul::Maid> maid, SharedPtr<Node> node)
: _started(false)
, _node(node)
- , _enter_action(MidiAction::create(maid, 4, NULL))
- , _exit_action(MidiAction::create(maid, 4, NULL))
+ , _enter_action(new MidiAction(4, NULL))
+ , _exit_action(new MidiAction(4, NULL))
{
+ maid->manage(_enter_action);
+ maid->manage(_exit_action);
}
bool _started;
diff --git a/src/engine/machina/Machine.hpp b/src/engine/machina/Machine.hpp
index 889dc1a..4544090 100644
--- a/src/engine/machina/Machine.hpp
+++ b/src/engine/machina/Machine.hpp
@@ -20,6 +20,7 @@
#include <boost/utility.hpp>
#include <raul/SharedPtr.hpp>
+#include <raul/WeakPtr.hpp>
#include <raul/List.hpp>
#include <raul/TimeSlice.hpp>
#include <redlandmm/Model.hpp>
@@ -32,9 +33,10 @@ namespace Machina {
/** A (Finite State) Machine.
*/
-class Machine : public Raul::Stateful, public boost::noncopyable {
+class Machine : public Raul::Stateful {
public:
Machine();
+ Machine(const Machine& copy);
~Machine();
// Main context
diff --git a/src/engine/machina/MidiAction.hpp b/src/engine/machina/MidiAction.hpp
index 5639532..1a3f176 100644
--- a/src/engine/machina/MidiAction.hpp
+++ b/src/engine/machina/MidiAction.hpp
@@ -18,8 +18,6 @@
#ifndef MACHINA_MIDIACTION_HPP
#define MACHINA_MIDIACTION_HPP
-#include <raul/Maid.hpp>
-#include <raul/WeakPtr.hpp>
#include <raul/AtomicPtr.hpp>
#include <raul/TimeSlice.hpp>
#include "types.hpp"
@@ -37,15 +35,6 @@ public:
MidiAction(size_t size,
const unsigned char* event);
- static SharedPtr<MidiAction>
- create(SharedPtr<Raul::Maid> maid,
- size_t size, const unsigned char* event)
- {
- SharedPtr<MidiAction> ret(new MidiAction(size, event));
- maid->manage(ret);
- return ret;
- }
-
size_t event_size() { return _size; }
byte* event() { return _event.get(); }
diff --git a/src/engine/machina/Node.hpp b/src/engine/machina/Node.hpp
index 5926a50..1f0face 100644
--- a/src/engine/machina/Node.hpp
+++ b/src/engine/machina/Node.hpp
@@ -18,7 +18,6 @@
#ifndef MACHINA_NODE_HPP
#define MACHINA_NODE_HPP
-#include <boost/utility.hpp>
#include <raul/SharedPtr.hpp>
#include <raul/List.hpp>
#include <raul/Stateful.hpp>
@@ -41,11 +40,12 @@ using Raul::BeatTime;
* Initial nodes do not have enter actions (since they are entered at
* an undefined point in time <= 0).
*/
-class Node : public Raul::Stateful, public boost::noncopyable {
+class Node : public Raul::Stateful {
public:
typedef std::string ID;
Node(BeatCount duration=0, bool initial=false);
+ Node(const Node& copy);
void set_enter_action(SharedPtr<Action> action);
void set_exit_action(SharedPtr<Action> action);
diff --git a/src/engine/machina/Problem.hpp b/src/engine/machina/Problem.hpp
new file mode 100644
index 0000000..d221e5c
--- /dev/null
+++ b/src/engine/machina/Problem.hpp
@@ -0,0 +1,56 @@
+/* This file is part of Machina.
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * Machina is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Machina is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef MACHINA_PROBLEM_HPP
+#define MACHINA_PROBLEM_HPP
+
+#include <raul/MIDISink.hpp>
+
+namespace Machina {
+
+class Machine;
+
+
+class Problem {
+public:
+ Problem(const std::string& target_midi);
+
+ float fitness(Machine& machine);
+
+private:
+ struct Evaluator : public Raul::MIDISink {
+ Evaluator(Problem& problem) : _problem(problem), _n_notes(0) {
+ for (uint8_t i=0; i < 128; ++i)
+ _note_frequency[i] = 0;
+ }
+ void write_event(Raul::BeatTime time,
+ size_t ev_size,
+ const uint8_t* ev) throw (std::logic_error);
+ void compute();
+ Problem& _problem;
+
+ float _note_frequency[128];
+ size_t _n_notes;
+ };
+
+ Evaluator _target;
+};
+
+
+} // namespace Machina
+
+#endif // MACHINA_PROBLEM_HPP