diff options
author | Florian Jung <flo@windfisch.org> | 2011-05-25 17:27:35 +0000 |
---|---|---|
committer | Florian Jung <flo@windfisch.org> | 2011-05-25 17:27:35 +0000 |
commit | 3948032d0a2e439069d9a6859f7f35eebb54944d (patch) | |
tree | c4bb531ecdd05e21333cedacbf27ea01686e7b69 /muse2/muse/steprec.cpp | |
parent | 5e47397a7d496b8dcc93e11b89cb0f9159f291e0 (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.cpp | 159 |
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); + } + } +} |