diff options
author | David Robillard <d@drobilla.net> | 2007-12-06 19:06:54 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2007-12-06 19:06:54 +0000 |
commit | 33e9991326a1cd90a4956f3221f5a48d03d5af89 (patch) | |
tree | c0367028d619b64e6dfcaf64cf68b158031a5d0d /src/engine | |
parent | d0dbdee864a3d38e385906cf05c03fe4c264f5d8 (diff) | |
download | machina-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.cpp | 10 | ||||
-rw-r--r-- | src/engine/Machine.cpp | 19 | ||||
-rw-r--r-- | src/engine/Makefile.am | 4 | ||||
-rw-r--r-- | src/engine/Node.cpp | 18 | ||||
-rw-r--r-- | src/engine/Problem.cpp | 112 | ||||
-rw-r--r-- | src/engine/machina/ActionFactory.hpp | 1 | ||||
-rw-r--r-- | src/engine/machina/Edge.hpp | 2 | ||||
-rw-r--r-- | src/engine/machina/LearnRequest.hpp | 6 | ||||
-rw-r--r-- | src/engine/machina/Machine.hpp | 4 | ||||
-rw-r--r-- | src/engine/machina/MidiAction.hpp | 11 | ||||
-rw-r--r-- | src/engine/machina/Node.hpp | 4 | ||||
-rw-r--r-- | src/engine/machina/Problem.hpp | 56 |
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 |