aboutsummaryrefslogtreecommitdiffstats
path: root/src/engine
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-03-12 21:36:32 +0000
committerDavid Robillard <d@drobilla.net>2007-03-12 21:36:32 +0000
commit1c4f8c131dec109677d0a9b2b008c39a66d08158 (patch)
treee3843ac691ef5009810921ac81617076dc9c4cae /src/engine
parentcc78e514acdf2e3587d38bcdb42f091c0c7c4ebe (diff)
downloadmachina-1c4f8c131dec109677d0a9b2b008c39a66d08158.tar.gz
machina-1c4f8c131dec109677d0a9b2b008c39a66d08158.tar.bz2
machina-1c4f8c131dec109677d0a9b2b008c39a66d08158.zip
Export to DOT file.
Fixed loading of useless initial nodes. git-svn-id: http://svn.drobilla.net/lad/machina@358 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/Engine.cpp2
-rw-r--r--src/engine/SMFDriver.cpp73
-rw-r--r--src/engine/machina/SMFDriver.hpp7
3 files changed, 67 insertions, 15 deletions
diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp
index 289abd3..5991276 100644
--- a/src/engine/Engine.cpp
+++ b/src/engine/Engine.cpp
@@ -46,7 +46,7 @@ SharedPtr<Machine>
Engine::learn_midi(const Glib::ustring& uri)
{
SharedPtr<SMFDriver> file_driver(new SMFDriver());
- SharedPtr<Machine> m = file_driver->learn(uri);
+ SharedPtr<Machine> m = file_driver->learn(uri, 32.0);
m->activate();
_driver->set_machine(m);
return m;
diff --git a/src/engine/SMFDriver.cpp b/src/engine/SMFDriver.cpp
index abd0fb2..d2fcabb 100644
--- a/src/engine/SMFDriver.cpp
+++ b/src/engine/SMFDriver.cpp
@@ -38,7 +38,7 @@ namespace Machina {
* @return the resulting machine.
*/
SharedPtr<Machine>
-SMFDriver::learn(const Glib::ustring& uri, unsigned track)
+SMFDriver::learn(const Glib::ustring& uri, unsigned track, Raul::BeatTime max_duration)
{
const string filename = Glib::filename_from_uri(uri);
@@ -50,7 +50,7 @@ SMFDriver::learn(const Glib::ustring& uri, unsigned track)
if (track > reader.num_tracks())
return SharedPtr<Machine>();
else
- learn_track(m, reader, track);
+ learn_track(m, reader, track, max_duration);
if (m->nodes().size() > 1)
return m;
@@ -64,7 +64,7 @@ SMFDriver::learn(const Glib::ustring& uri, unsigned track)
* This will result in a disjoint subgraph in the machine, one for each track.
*/
SharedPtr<Machine>
-SMFDriver::learn(const Glib::ustring& uri)
+SMFDriver::learn(const Glib::ustring& uri, Raul::BeatTime max_duration)
{
const string filename = Glib::filename_from_uri(uri);
@@ -74,7 +74,7 @@ SMFDriver::learn(const Glib::ustring& uri)
reader.open(filename);
for (unsigned t=1; t <= reader.num_tracks(); ++t) {
- learn_track(m, reader, t);
+ learn_track(m, reader, t, max_duration);
}
if (m->nodes().size() > 1)
@@ -87,7 +87,8 @@ SMFDriver::learn(const Glib::ustring& uri)
void
SMFDriver::learn_track(SharedPtr<Machine> m,
Raul::SMFReader& reader,
- unsigned track)
+ unsigned track,
+ Raul::BeatTime max_duration)
{
const bool found_track = reader.seek_to_track(track);
assert(found_track);
@@ -95,9 +96,13 @@ SMFDriver::learn_track(SharedPtr<Machine> m,
list<SharedPtr<Node> > active_nodes;
SharedPtr<Node> initial_node(new Node());
- m->add_node(initial_node);
+ initial_node->set_initial(true);
+ //m->add_node(initial_node);
SharedPtr<Node> connect_node = initial_node;
+ Raul::BeatTime connect_node_end_time = 0;
+
+ unsigned added_nodes = 0;
Raul::BeatTime t = 0;
unsigned char buf[4];
@@ -105,13 +110,31 @@ SMFDriver::learn_track(SharedPtr<Machine> m,
uint32_t ev_time;
while (reader.read_event(4, buf, &ev_size, &ev_time) >= 0) {
t += ev_time / (double)reader.ppqn();
+
+ if (t > max_duration)
+ break;
+
//cerr << "t = " << t << endl;
if (ev_size > 0) {
if ((buf[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
- //cerr << "NOTE ON: " << (int)buf[1] << endl;
+ cerr << "NOTE ON: " << (int)buf[1] << ", channel = " << (int)(buf[0] & 0x0F) << endl;
SharedPtr<Node> node(new Node());
node->add_enter_action(SharedPtr<Action>(new MidiAction(ev_size, buf)));
- connect_node->add_outgoing_edge(SharedPtr<Edge>(new Edge(connect_node, node)));
+ assert(connect_node_end_time <= t);
+
+ if (t == connect_node_end_time) {
+ connect_node->add_outgoing_edge(SharedPtr<Edge>(new Edge(connect_node, node)));
+ } else {
+ SharedPtr<Node> delay_node(new Node());
+ delay_node->set_duration(t - connect_node_end_time);
+ connect_node->add_outgoing_edge(SharedPtr<Edge>(new Edge(connect_node, delay_node)));
+ delay_node->add_outgoing_edge(SharedPtr<Edge>(new Edge(delay_node, node)));
+ m->add_node(delay_node);
+ ++added_nodes;
+ connect_node = delay_node;
+ connect_node_end_time = t;
+ }
+
node->enter(SharedPtr<Raul::MIDISink>(), t);
active_nodes.push_back(node);
} else if ((buf[0] & 0xF0) == MIDI_CMD_NOTE_OFF) {
@@ -125,14 +148,19 @@ SMFDriver::learn_track(SharedPtr<Machine> m,
const size_t ev_size = action->event_size();
const unsigned char* ev = action->event();
if (ev_size == 3 && (ev[0] & 0xF0) == MIDI_CMD_NOTE_ON
- && ev[1] == buf[1]) {
+ && (ev[0] & 0x0F) == (buf[0] & 0x0F) // same channel
+ && ev[1] == buf[1]) // same note
+ {
//cerr << "FOUND MATCHING NOTE ON!\n";
(*i)->add_exit_action(SharedPtr<Action>(new MidiAction(ev_size, buf)));
(*i)->set_duration(t - (*i)->enter_time());
(*i)->exit(SharedPtr<Raul::MIDISink>(), t);
m->add_node((*i));
- if (active_nodes.size() == 1)
+ ++added_nodes;
+ if (active_nodes.size() == 1) {
connect_node = (*i);
+ connect_node_end_time = t;
+ }
active_nodes.erase(i);
break;
}
@@ -141,7 +169,30 @@ SMFDriver::learn_track(SharedPtr<Machine> m,
}
}
- initial_node->set_initial(true);
+ // Resolve any stuck notes when the rest of the machine is finished
+ if ( ! active_nodes.empty()) {
+ for (list<SharedPtr<Node> >::iterator i = active_nodes.begin(); i != active_nodes.end(); ++i) {
+ cerr << "WARNING: Resolving stuck note from MIDI file." << endl;
+ SharedPtr<MidiAction> action = PtrCast<MidiAction>((*i)->enter_action());
+ if (!action)
+ continue;
+
+ const size_t ev_size = action->event_size();
+ const unsigned char* ev = action->event();
+ if (ev_size == 3 && (ev[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
+ unsigned char note_off[3] = { ((MIDI_CMD_NOTE_OFF & 0xF0) | (ev[0] & 0x0F)), ev[1], 0x40 };
+ (*i)->add_exit_action(SharedPtr<Action>(new MidiAction(3, note_off)));
+ (*i)->set_duration(t - (*i)->enter_time());
+ (*i)->exit(SharedPtr<Raul::MIDISink>(), t);
+ m->add_node((*i));
+ ++added_nodes;
+ }
+ }
+ active_nodes.clear();
+ }
+
+ if (added_nodes > 0)
+ m->add_node(initial_node);
}
diff --git a/src/engine/machina/SMFDriver.hpp b/src/engine/machina/SMFDriver.hpp
index f9b266b..28d2277 100644
--- a/src/engine/machina/SMFDriver.hpp
+++ b/src/engine/machina/SMFDriver.hpp
@@ -35,15 +35,16 @@ class Machine;
class SMFDriver : public Raul::SMFWriter,
public boost::enable_shared_from_this<SMFDriver> {
public:
- SharedPtr<Machine> learn(const Glib::ustring& uri);
- SharedPtr<Machine> learn(const Glib::ustring& uri, unsigned track);
+ SharedPtr<Machine> learn(const Glib::ustring& uri, Raul::BeatTime max_duration);
+ SharedPtr<Machine> learn(const Glib::ustring& uri, unsigned track, Raul::BeatTime max_duration);
void run(SharedPtr<Machine> machine, Raul::BeatTime max_time);
private:
void learn_track(SharedPtr<Machine> machine,
Raul::SMFReader& reader,
- unsigned track);
+ unsigned track,
+ Raul::BeatTime max_duration);
};