summaryrefslogtreecommitdiff
path: root/muse2/muse/steprec.cpp
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2011-05-25 17:27:35 +0000
committerFlorian Jung <flo@windfisch.org>2011-05-25 17:27:35 +0000
commit3948032d0a2e439069d9a6859f7f35eebb54944d (patch)
treec4bb531ecdd05e21333cedacbf27ea01686e7b69 /muse2/muse/steprec.cpp
parent5e47397a7d496b8dcc93e11b89cb0f9159f291e0 (diff)
added step recording for drum edit
step-recording stuff has been put into a easy-to-use StepRec class the midi-in and step-rec buttons are now fully functional again
Diffstat (limited to 'muse2/muse/steprec.cpp')
-rw-r--r--muse2/muse/steprec.cpp159
1 files changed, 159 insertions, 0 deletions
diff --git a/muse2/muse/steprec.cpp b/muse2/muse/steprec.cpp
new file mode 100644
index 00000000..29cb9540
--- /dev/null
+++ b/muse2/muse/steprec.cpp
@@ -0,0 +1,159 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// steprec.cpp
+// (C) Copyright 2011 Florian Jung (flo93@users.sourceforge.net)
+//=========================================================
+
+#include "steprec.h"
+#include "part.h"
+#include "event.h"
+#include "globals.h"
+
+#include "song.h"
+#include "audio.h"
+
+#include <set>
+
+#define CHORD_TIMEOUT 75
+
+StepRec::StepRec(bool* note_held_down_array)
+{
+ note_held_down=note_held_down_array;
+
+ chord_timer=new QTimer(this);
+ chord_timer->setSingleShot(true);
+ chord_timer->setInterval(CHORD_TIMEOUT);
+ chord_timer->stop();
+ connect(chord_timer, SIGNAL(timeout()), SLOT(timeout()));
+}
+
+void StepRec::timeout()
+{
+ if (chord_timer_set_to_tick != song->cpos())
+ {
+ Pos p(chord_timer_set_to_tick, true);
+ song->setPos(0, p, true, false, true);
+ }
+}
+
+void StepRec::record(Part* part, int pitch, int len, int step, int velo, bool ctrl, bool shift)
+{
+ unsigned tick = song->cpos();
+
+ if (pitch!=rcSteprecNote) {
+ chord_timer->stop();
+
+
+ //
+ // extend len of last note?
+ //
+ EventList* events = part->events();
+ if (ctrl) {
+ for (iEvent i = events->begin(); i != events->end(); ++i) {
+ Event ev = i->second;
+ if (!ev.isNote())
+ continue;
+ if (ev.pitch() == pitch && ((ev.tick() + ev.lenTick()) == tick)) {
+ Event e = ev.clone();
+ e.setLenTick(ev.lenTick() + len);
+ // Indicate do undo, and do not do port controller values and clone parts.
+ audio->msgChangeEvent(ev, e, part, true, false, false);
+
+ if (!shift) {
+ chord_timer_set_to_tick = tick + step;
+ chord_timer->start();
+ }
+ return;
+ }
+ }
+ }
+
+ //
+ // if we already entered the note, delete it
+ //
+ EventRange range = events->equal_range(tick);
+ for (iEvent i = range.first; i != range.second; ++i) {
+ Event ev = i->second;
+ if (ev.isNote() && ev.pitch() == pitch) {
+ // Indicate do undo, and do not do port controller values and clone parts.
+ //audio->msgDeleteEvent(ev, part);
+ audio->msgDeleteEvent(ev, part, true, false, false);
+
+ if (!shift) {
+ chord_timer_set_to_tick = tick + step;
+ chord_timer->start();
+ }
+
+ return;
+ }
+ }
+
+ Event e(Note);
+ e.setTick(tick - part->tick());
+ e.setPitch(pitch);
+ e.setVelo(velo);
+ e.setLenTick(len);
+ // Indicate do undo, and do not do port controller values and clone parts.
+ //audio->msgAddEvent(e, part);
+ audio->msgAddEvent(e, part, true, false, false);
+
+ if (! (globalKeyState & Qt::ShiftModifier)) {
+ chord_timer_set_to_tick = tick + step;
+ chord_timer->start();
+ }
+ }
+ else { // equals if (pitch==rcSteprecNote)
+ bool held_notes=false;
+ if (note_held_down!=NULL)
+ {
+ for (int i=0;i<128;i++)
+ if (note_held_down[i]) { held_notes=true; break; }
+ }
+ else
+ held_notes=false;
+
+
+ if (held_notes)
+ {
+ chord_timer->stop();
+
+ // extend len of last note(s)
+ using std::set;
+
+ set<Event*> extend_set;
+ EventList* events = part->events();
+ for (iEvent i = events->begin(); i != events->end(); ++i) {
+ Event& ev = i->second;
+ if (!ev.isNote())
+ continue;
+
+ if (note_held_down[ev.pitch()] && ((ev.tick() + ev.lenTick()) == tick))
+ extend_set.insert(&ev);
+ }
+ for (set<Event*>::iterator it=extend_set.begin(); it!=extend_set.end(); it++)
+ {
+ Event& ev=**it;
+ Event e = ev.clone();
+ e.setLenTick(ev.lenTick() + len);
+ // Indicate do undo, and do not do port controller values and clone parts.
+ audio->msgChangeEvent(ev, e, part, true, false, false);
+ }
+
+ if (!shift) {
+ chord_timer_set_to_tick = tick + step;
+ chord_timer->start();
+ }
+ return;
+
+ }
+ else // equals if (!held_notes)
+ {
+ chord_timer->stop();
+
+ //simply proceed, inserting a rest
+ Pos p(song->cpos() + step, true);
+ song->setPos(0, p, true, false, true);
+ }
+ }
+}