summaryrefslogtreecommitdiff
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
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
-rw-r--r--muse2/muse/CMakeLists.txt2
-rw-r--r--muse2/muse/midiedit/dcanvas.cpp24
-rw-r--r--muse2/muse/midiedit/dcanvas.h8
-rw-r--r--muse2/muse/midiedit/drumedit.cpp7
-rw-r--r--muse2/muse/midiedit/prcanvas.cpp161
-rw-r--r--muse2/muse/midiedit/prcanvas.h7
-rw-r--r--muse2/muse/steprec.cpp159
-rw-r--r--muse2/muse/steprec.h36
8 files changed, 237 insertions, 167 deletions
diff --git a/muse2/muse/CMakeLists.txt b/muse2/muse/CMakeLists.txt
index e6a90a59..cea95083 100644
--- a/muse2/muse/CMakeLists.txt
+++ b/muse2/muse/CMakeLists.txt
@@ -63,6 +63,7 @@ QT4_WRAP_CPP ( muse_moc_headers
song.h
transport.h
value.h
+ steprec.h
)
##
@@ -135,6 +136,7 @@ file (GLOB core_source_files
waveevent.cpp
wavetrack.cpp
xml.cpp
+ steprec.cpp
)
file (GLOB main_source_files
main.cpp
diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp
index eea29b46..4f904be1 100644
--- a/muse2/muse/midiedit/dcanvas.cpp
+++ b/muse2/muse/midiedit/dcanvas.cpp
@@ -88,7 +88,11 @@ DrumCanvas::DrumCanvas(MidiEditor* pr, QWidget* parent, int sx,
setVirt(false);
cursorPos= QPoint(0,0);
_stepSize=1;
+
+ steprec=new StepRec(NULL);
+
songChanged(SC_TRACK_INSERTED);
+ connect(song, SIGNAL(midiNote(int, int)), SLOT(midiNote(int,int)));
}
//---------------------------------------------------------
@@ -1063,6 +1067,10 @@ void DrumCanvas::keyPressed(int index, int velocity)
// play note:
MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity);
audio->msgPlayMidiEvent(&e);
+
+ if (_steprec && pos[0] >= start_tick && pos[0] < end_tick && curPart)
+ steprec->record(curPart,index,drumMap[index].len,editor->raster(),velocity,globalKeyState&Qt::ControlModifier,globalKeyState&Qt::ShiftModifier);
+
}
//---------------------------------------------------------
@@ -1503,3 +1511,19 @@ void DrumCanvas::moveAwayUnused()
used.erase(it++);
}
}
+
+
+//---------------------------------------------------------
+// midiNote
+//---------------------------------------------------------
+void DrumCanvas::midiNote(int pitch, int velo)
+ {
+ if (debugMsg) printf("DrumCanvas::midiNote: pitch=%i, velo=%i\n", pitch, velo);
+
+ if (_midiin && _steprec && curPart
+ && !audio->isPlaying() && velo && pos[0] >= start_tick
+ && pos[0] < end_tick
+ && !(globalKeyState & Qt::AltModifier)) {
+ steprec->record(curPart,drumInmap[pitch],drumMap[(int)drumInmap[pitch]].len,editor->raster(),velo,globalKeyState&Qt::ControlModifier,globalKeyState&Qt::ShiftModifier);
+ }
+ }
diff --git a/muse2/muse/midiedit/dcanvas.h b/muse2/muse/midiedit/dcanvas.h
index b86bc2d7..5a1fefeb 100644
--- a/muse2/muse/midiedit/dcanvas.h
+++ b/muse2/muse/midiedit/dcanvas.h
@@ -10,6 +10,7 @@
#include "ecanvas.h"
#include "song.h"
+#include "steprec.h"
#define TH 18
@@ -40,7 +41,9 @@ class PianoRoll;
//---------------------------------------------------------
class DrumCanvas : public EventCanvas {
-
+
+ StepRec* steprec;
+
// Cursor tool position
QPoint cursorPos;
int _stepSize;
@@ -77,6 +80,9 @@ class DrumCanvas : public EventCanvas {
signals:
void newWidth(int);
+ private slots:
+ void midiNote(int pitch, int velo);
+
public slots:
void mapChanged(int, int);
void keyPressed(int, int);
diff --git a/muse2/muse/midiedit/drumedit.cpp b/muse2/muse/midiedit/drumedit.cpp
index 4d632984..4d2fae93 100644
--- a/muse2/muse/midiedit/drumedit.cpp
+++ b/muse2/muse/midiedit/drumedit.cpp
@@ -295,21 +295,14 @@ DrumEdit::DrumEdit(PartList* pl, QWidget* parent, const char* name, unsigned ini
srec->setToolTip(tr("Step Record"));
srec->setIcon(*steprecIcon);
srec->setCheckable(true);
- srec->setEnabled(false); //disabled by flo93 (see below)
tools->addWidget(srec);
midiin = new QToolButton();
midiin->setToolTip(tr("Midi Input"));
midiin->setIcon(*midiinIcon);
midiin->setCheckable(true);
- midiin->setEnabled(false); //disabled by flo93 (see below)
tools->addWidget(midiin);
- // I disabled these buttons because they're without function;
- // muse should not lie to the user pretending some functionality
- // it doesn't have; they should be enabled as soon step-recording
- // has been implemented.
-
tools2 = new EditToolBar(this, drumeditTools);
addToolBar(tools2);
diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp
index 7794c520..75ad3c06 100644
--- a/muse2/muse/midiedit/prcanvas.cpp
+++ b/muse2/muse/midiedit/prcanvas.cpp
@@ -37,8 +37,6 @@
#include "song.h"
#include "audio.h"
-#define CHORD_TIMEOUT 75
-
//---------------------------------------------------------
// NEvent
//---------------------------------------------------------
@@ -87,13 +85,8 @@ PianoCanvas::PianoCanvas(MidiEditor* pr, QWidget* parent, int sx, int sy)
playedPitch = -1;
for (int i=0;i<128;i++) noteHeldDown[i]=false;
- chordTimer = new QTimer(this);
- chordTimer->setSingleShot(true);
- chordTimer->setInterval(CHORD_TIMEOUT);
- chordTimer->stop();
+ steprec=new StepRec(noteHeldDown);
- connect(chordTimer, SIGNAL(timeout()), SLOT(chordTimerTimedOut()));
-
songChanged(SC_TRACK_INSERTED);
connect(song, SIGNAL(midiNote(int, int)), SLOT(midiNote(int,int)));
}
@@ -778,27 +771,9 @@ void PianoCanvas::pianoPressed(int pitch, int velocity, bool shift)
//MidiPlayEvent e(0, port, channel, 0x90, pitch, 127);
MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity);
audio->msgPlayMidiEvent(&e);
-
- if (_steprec && pos[0] >= start_tick && pos[0] < end_tick) {
- if (curPart) {
- int len = editor->raster();
- unsigned tick = pos[0] - curPart->tick(); //CDW
- if (shift)
- tick -= editor->rasterStep(tick);
- Event e(Note);
- e.setTick(tick);
- e.setPitch(pitch);
- e.setVelo(127);
- e.setLenTick(len);
- // Indicate do undo, and do not do port controller values and clone parts.
- //audio->msgAddEvent(e, curPart);
- audio->msgAddEvent(e, curPart, true, false, false);
- tick += editor->rasterStep(tick) + curPart->tick();
- if (tick != song->cpos()) {
- Pos p(tick, true);
- song->setPos(0, p, true, false, true);
- }
- }
+
+ if (_steprec && pos[0] >= start_tick && pos[0] < end_tick && curPart) {
+ steprec->record(curPart,pitch,editor->raster(),editor->raster(),velocity,globalKeyState&Qt::ControlModifier,shift);
}
}
@@ -1077,136 +1052,10 @@ void PianoCanvas::midiNote(int pitch, int velo)
&& !audio->isPlaying() && velo && pos[0] >= start_tick
&& pos[0] < end_tick
&& !(globalKeyState & Qt::AltModifier)) {
-
- if (pitch!=rcSteprecNote) {
- chordTimer->stop();
-
- //len has been changed by flo: set to raster() instead of quant()
- //reason: the quant-toolbar has been removed; the flexibility you
- //lose with this can be re-gained by applying a "modify note len"
- //on the notes you have entered.
- unsigned int len = editor->raster();//prevent compiler warning: comparison singed/unsigned
- unsigned tick = pos[0]; //CDW
- unsigned starttick = tick;
-
- //
- // extend len of last note?
- //
- EventList* events = curPart->events();
- if (globalKeyState & Qt::ControlModifier) {
- 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()) == /*(int)*/starttick)) {
- Event e = ev.clone();
- e.setLenTick(ev.lenTick() + editor->rasterStep(starttick));
- // Indicate do undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(ev, e, curPart);
- audio->msgChangeEvent(ev, e, curPart, true, false, false);
-
- if (! (globalKeyState & Qt::ShiftModifier)) {
- chordTimer_setToTick = tick + editor->rasterStep(tick);
- chordTimer->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, curPart);
- audio->msgDeleteEvent(ev, curPart, true, false, false);
-
- if (! (globalKeyState & Qt::ShiftModifier)) {
- chordTimer_setToTick = tick + editor->rasterStep(tick);
- chordTimer->start();
- }
-
- return;
- }
- }
- Event e(Note);
- e.setTick(tick - curPart->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, curPart);
- audio->msgAddEvent(e, curPart, true, false, false);
-
- if (! (globalKeyState & Qt::ShiftModifier)) {
- chordTimer_setToTick = tick + editor->rasterStep(tick);
- chordTimer->start();
- }
- }
- else { // equals if (pitch==rcSteprecNote)
- bool held_notes=false;
- for (int i=0;i<128;i++)
- if (noteHeldDown[i]) { held_notes=true; break; }
-
- if (held_notes)
- {
- chordTimer->stop();
-
- unsigned tick = pos[0];
-
- // extend len of last note(s)
- using std::set;
-
- set<Event*> extend_set;
- EventList* events = curPart->events();
- for (iEvent i = events->begin(); i != events->end(); ++i) {
- Event& ev = i->second;
- if (!ev.isNote())
- continue;
-
- if (noteHeldDown[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() + editor->rasterStep(tick));
- // Indicate do undo, and do not do port controller values and clone parts.
- audio->msgChangeEvent(ev, e, curPart, true, false, false);
- }
-
- if (! (globalKeyState & Qt::ShiftModifier)) {
- chordTimer_setToTick = tick + editor->rasterStep(tick);
- chordTimer->start();
- }
- return;
-
- }
- else // equals if (!held_notes)
- {
- chordTimer->stop();
-
- //simply proceed, inserting a rest
- Pos p(pos[0] + editor->rasterStep(pos[0]), true);
- song->setPos(0, p, true, false, true);
- }
- }
+ steprec->record(curPart,pitch,editor->raster(),editor->raster(),velo,globalKeyState&Qt::ControlModifier,globalKeyState&Qt::ShiftModifier);
}
}
-void PianoCanvas::chordTimerTimedOut()
-{
- if (chordTimer_setToTick != song->cpos())
- {
- Pos p(chordTimer_setToTick, true);
- song->setPos(0, p, true, false, true);
- }
-}
/*
//---------------------------------------------------------
diff --git a/muse2/muse/midiedit/prcanvas.h b/muse2/muse/midiedit/prcanvas.h
index c6d84e88..b9da00c6 100644
--- a/muse2/muse/midiedit/prcanvas.h
+++ b/muse2/muse/midiedit/prcanvas.h
@@ -17,6 +17,8 @@
#include <QDragLeaveEvent>
#include <QTimer>
+#include "steprec.h"
+
#define KH 13
//---------------------------------------------------------
@@ -41,9 +43,9 @@ class PianoCanvas : public EventCanvas {
int colorMode;
int playedPitch;
- QTimer* chordTimer;
- unsigned chordTimer_setToTick;
bool noteHeldDown[128];
+
+ StepRec* steprec;
Q_OBJECT
virtual void viewMouseDoubleClickEvent(QMouseEvent*);
@@ -77,7 +79,6 @@ class PianoCanvas : public EventCanvas {
private slots:
void midiNote(int pitch, int velo);
- void chordTimerTimedOut();
signals:
void quantChanged(int);
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);
+ }
+ }
+}
diff --git a/muse2/muse/steprec.h b/muse2/muse/steprec.h
new file mode 100644
index 00000000..b09a9edd
--- /dev/null
+++ b/muse2/muse/steprec.h
@@ -0,0 +1,36 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// steprec.h
+// (C) Copyright 2011 Florian Jung (flo93@users.sourceforge.net)
+//=========================================================
+
+#ifndef __STEPREC_H__
+#define __STEPREC_H__
+
+#include <QObject>
+#include <QTimer>
+
+#include "part.h"
+
+
+class StepRec : public QObject
+{
+ Q_OBJECT
+
+ public:
+ StepRec(bool* note_held_down_array);
+
+ void record(Part* part, int pitch, int len, int step, int velo=80, bool ctrl=false, bool shift=false);
+
+ private slots:
+ void timeout();
+
+ private:
+ QTimer* chord_timer;
+ int chord_timer_set_to_tick;
+ bool* note_held_down;
+
+};
+
+#endif