summaryrefslogtreecommitdiff
path: root/test/dgreftest/midiinputengine.cc
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2016-05-14 20:27:56 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2016-05-14 20:27:56 +0200
commit36a62ae3403f7cfb02bd8dde43b6b2fa96fe867b (patch)
treec4ea5f2f97e94688bd0ac96dbb198a8f1eb67491 /test/dgreftest/midiinputengine.cc
parent7bbc7520ecb2ff4fc020189c1fdfebd7d3bb8e42 (diff)
Make all components use the same Random instance and add seed method on DrumGizmo class. Added dgreftest application for doing reference midifile rendering tests.
Diffstat (limited to 'test/dgreftest/midiinputengine.cc')
-rw-r--r--test/dgreftest/midiinputengine.cc192
1 files changed, 192 insertions, 0 deletions
diff --git a/test/dgreftest/midiinputengine.cc b/test/dgreftest/midiinputengine.cc
new file mode 100644
index 0000000..bc0fa87
--- /dev/null
+++ b/test/dgreftest/midiinputengine.cc
@@ -0,0 +1,192 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * midiinputengine.cc
+ *
+ * Sat May 14 13:26:23 CEST 2016
+ * Copyright 2016 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "midiinputengine.h"
+
+#include <iostream>
+
+static int const NOTE_ON = 0x90;
+
+MidifileInputEngine::MidifileInputEngine()
+ : AudioInputEngineMidi{}
+ , smf{nullptr}
+ , current_event{nullptr}
+ , file{}
+ , speed{1.f}
+ , track{-1} // all tracks
+ , loop{false}
+ , offset{0.0}
+ , samplerate{44100.0} // todo: via ctor arg
+{
+}
+
+MidifileInputEngine::~MidifileInputEngine()
+{
+ if(smf != nullptr)
+ {
+ smf_delete(smf);
+ }
+}
+
+bool MidifileInputEngine::init(const Instruments& instruments)
+{
+ if(file == "")
+ {
+ std::cerr << "[MidifileInputEngine] Missing midi filename\n";
+ return false;
+ }
+ //if(midimap_filename == "")
+ //{
+ // std::cerr << "[MidifileInputEngine] Missing midimap filename\n";
+ // return false;
+ //}
+ smf = smf_load(file.c_str());
+ if(smf == nullptr)
+ {
+ std::cerr << "[MidifileInputEngine] Failed to load midifile '" << file
+ << "'\n";
+ return false;
+ }
+ //if(!loadMidiMap(midimap_filename, instruments))
+ //{
+ // std::cerr << "[MidifileInputEngine] Failed to parse midimap '"
+ // << midimap_filename << "'\n";
+ // return false;
+ //}
+
+ return true;
+}
+
+void MidifileInputEngine::setParm(const std::string& parm, const std::string& value)
+{
+ if(parm == "file")
+ {
+ // apply midi input filename
+ file = value;
+ }
+ else if(parm == "speed")
+ {
+ // try to apply speed
+ try
+ {
+ speed = std::stof(value);
+ }
+ catch(...)
+ {
+ std::cerr << "[MidifileInputEngine] Invalid speed " << value
+ << "\n";
+ }
+ }
+ //else if(parm == "midimap")
+ //{
+ // // apply midimap filename
+ // midimap_filename = value;
+ //}
+ else if(parm == "loop")
+ {
+ // apply looping
+ loop = true;
+ }
+ else
+ {
+ std::cerr << "[MidifileInputEngine] Unsupported parameter '" << parm
+ << "'\n";
+ }
+}
+
+bool MidifileInputEngine::start()
+{
+ return true;
+}
+
+void MidifileInputEngine::stop()
+{
+}
+
+void MidifileInputEngine::pre()
+{
+}
+
+void MidifileInputEngine::run(size_t pos, size_t len, std::vector<event_t>& events)
+{
+ assert(events.empty());
+
+ double current_max_time = (1.0 + pos + len) / (samplerate / speed);
+ current_max_time -= offset;
+
+ if(!current_event)
+ {
+ current_event = smf_get_next_event(smf);
+ }
+
+ while(current_event && current_event->time_seconds < current_max_time)
+ {
+ if(!smf_event_is_metadata(current_event))
+ {
+ if((current_event->midi_buffer_length == 3) &&
+ ((current_event->midi_buffer[0] & NOTE_ON) == NOTE_ON) &&
+ (track == -1 || current_event->track_number == track) &&
+ current_event->midi_buffer[2] > 0)
+ {
+ int key = current_event->midi_buffer[1];
+ int velocity = current_event->midi_buffer[2];
+
+ events.emplace_back();
+ auto& event = events.back();
+ event.type = TYPE_ONSET;
+ size_t evpos = current_event->time_seconds * (samplerate / speed);
+ event.offset = evpos - pos;
+
+ int i = mmap.lookup(key);
+ if(i != -1)
+ {
+ event.instrument = i;
+ event.velocity = velocity / 127.0;
+ }
+ }
+ }
+
+ current_event = smf_get_next_event(smf);
+ }
+
+ if(!current_event)
+ {
+ if(loop)
+ {
+ smf_rewind(smf);
+ offset += current_max_time;
+ }
+ else
+ {
+ assert(len >= 1);
+ events.push_back({TYPE_STOP, 0, len-1, 0.f});
+ }
+ }
+}
+
+void MidifileInputEngine::post()
+{
+}