From deb38538f32489caa57081c097a18e691f81cbfe Mon Sep 17 00:00:00 2001 From: Werner Schweer Date: Thu, 30 Nov 2006 16:08:41 +0000 Subject: wave editor updates --- muse/awl/tcanvas.cpp | 3 +- muse/muse/midiedit/pianoroll.cpp | 1 - muse/muse/muse.cpp | 4 + muse/muse/muse.h | 1 + muse/muse/shortcuts.cpp | 8 ++ muse/muse/waveedit/waveedit.cpp | 30 ++++- muse/muse/waveedit/waveedit.h | 3 + muse/muse/waveedit/waveview.cpp | 255 +++++++++++++++++---------------------- muse/muse/waveedit/waveview.h | 2 + 9 files changed, 157 insertions(+), 150 deletions(-) diff --git a/muse/awl/tcanvas.cpp b/muse/awl/tcanvas.cpp index 286c5837..4b6b587f 100644 --- a/muse/awl/tcanvas.cpp +++ b/muse/awl/tcanvas.cpp @@ -818,7 +818,8 @@ void TimeCanvas::canvasPaintEvent(const QRect& r, QPainter& p) p.setBrushOrigin(QPoint(car.x() + wpos.x(), car.y() + wpos.y())); if (drawCanvasA) { if (canvasBackgroundPixmap.isNull()) { - if (type == TIME_CANVAS_DRUMEDIT || type == TIME_CANVAS_PIANOROLL) { + if (type == TIME_CANVAS_DRUMEDIT || type == TIME_CANVAS_PIANOROLL + || type == TIME_CANVAS_WAVEEDIT) { QRect rr(car); // paint inactive area different // (darker) diff --git a/muse/muse/midiedit/pianoroll.cpp b/muse/muse/midiedit/pianoroll.cpp index 51a1d01e..c9be06e9 100644 --- a/muse/muse/midiedit/pianoroll.cpp +++ b/muse/muse/midiedit/pianoroll.cpp @@ -58,7 +58,6 @@ PianoRoll::PianoRoll(PartList* pl, bool init) _quantLen = initQuantLen; deltaMode = false; - selPart = 0; quantConfig = 0; tcanvas = new PianoCanvas(this); diff --git a/muse/muse/muse.cpp b/muse/muse/muse.cpp index d5d0c45e..c15d2c82 100644 --- a/muse/muse/muse.cpp +++ b/muse/muse/muse.cpp @@ -559,6 +559,9 @@ MusE::MusE() pianoAction = getAction("open_pianoroll", this); connect(pianoAction, SIGNAL(triggered()), SLOT(startPianoroll())); + waveAction = getAction("open_waveedit", this); + connect(waveAction, SIGNAL(triggered()), SLOT(startWaveEditor())); + trackerAction = getAction("open_miditracker", this); connect(trackerAction, SIGNAL(triggered()), SLOT(startMidiTrackerEditor())); @@ -670,6 +673,7 @@ MusE::MusE() menuEdit->addSeparator(); menuEdit->addAction(pianoAction); + menuEdit->addAction(waveAction); menuEdit->addAction(trackerAction); a = menuEdit->addAction(QIcon(*edit_drummsIcon), tr("Drums")); diff --git a/muse/muse/muse.h b/muse/muse/muse.h index 67ae1e80..2249c5a3 100644 --- a/muse/muse/muse.h +++ b/muse/muse/muse.h @@ -70,6 +70,7 @@ class MusE : public QMainWindow // , public Ui::MuseBase QAction* fileSaveAction; QAction* fileOpenAction; QAction* pianoAction; + QAction* waveAction; QAction* trackerAction; QAction* fileNewAction; diff --git a/muse/muse/shortcuts.cpp b/muse/muse/shortcuts.cpp index dd9bdae9..b2d6a4c9 100644 --- a/muse/muse/shortcuts.cpp +++ b/muse/muse/shortcuts.cpp @@ -299,6 +299,14 @@ Shortcut MuseApplication::sc[] = { ARRANG_SHRT, Qt::CTRL + Qt::Key_D ), + Shortcut( + "open_waveedit", + QT_TR_NOOP("Open wave editor"), + ARRANG_SHRT, + 0, + QT_TR_NOOP("Wave Editor"), + QT_TR_NOOP("Wave Editor") + ), Shortcut( "open_listedit", QT_TR_NOOP("Open listeditor"), diff --git a/muse/muse/waveedit/waveedit.cpp b/muse/muse/waveedit/waveedit.cpp index bbea7e82..9a68b5cf 100644 --- a/muse/muse/waveedit/waveedit.cpp +++ b/muse/muse/waveedit/waveedit.cpp @@ -18,7 +18,6 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //============================================================================= - #include "waveedit.h" #include "waveview.h" #include "song.h" @@ -41,7 +40,9 @@ int WaveEdit::initHeight = WaveEdit::INIT_HEIGHT; WaveEdit::WaveEdit(PartList* pl, bool init) : Editor() { - _parts = pl; + _parts = pl; + selPart = 0; + //---------Pulldown Menu---------------------------- QMenuBar* mb = menuBar(); QAction* a; @@ -145,9 +146,8 @@ WaveEdit::WaveEdit(PartList* pl, bool init) p2 += AL::sigmap.ticksMeasure(p2.tick()); // show one more measure view->setTimeRange(p1, p2); +// view->selectFirst(); configChanged(); -// initSettings(); - if (init) ; // initFromPart(); else { @@ -162,8 +162,6 @@ WaveEdit::WaveEdit(PartList* pl, bool init) void WaveEdit::configChanged() { // view->setBg(config.waveEditBackgroundColor); -//TD select->setShortcut(shortcuts[SHRT_SELECT_ALL].key, CMD_SELECT_ALL); -// select->setShortcut(shortcuts[SHRT_SELECT_NONE].key, CMD_SELECT_NONE); } //--------------------------------------------------------- @@ -235,4 +233,24 @@ void WaveEdit::keyPressEvent(QKeyEvent* event) } } +//--------------------------------------------------------- +// write +//--------------------------------------------------------- + +void WaveEdit::write(Xml& xml) const + { + for (ciPart p = _parts->begin(); p != _parts->end(); ++p) { + Part* part = p->second; + Track* track = part->track(); + int trkIdx = song->tracks()->indexOf(track); + int partIdx = track->parts()->index(part); + xml.stag("part"); + xml.put("%d:%d", trkIdx, partIdx); + xml.etag("part"); + } + xml.stag(metaObject()->className()); + xml.writeProperties(this); + xml.etag(metaObject()->className()); + } + diff --git a/muse/muse/waveedit/waveedit.h b/muse/muse/waveedit/waveedit.h index bd98a6b7..85d9a726 100644 --- a/muse/muse/waveedit/waveedit.h +++ b/muse/muse/waveedit/waveedit.h @@ -42,6 +42,8 @@ class WaveEdit : public Editor { Q_OBJECT PartList* _parts; + Part* selPart; + WaveView* view; QToolBar* tools; QToolBar* tb1; @@ -68,6 +70,7 @@ class WaveEdit : public Editor { WaveEdit(PartList*, bool); ~WaveEdit(); PartList* parts() const { return _parts; } + void write(Xml& xml) const; enum { CMD_MUTE=0, CMD_NORMALIZE, CMD_FADE_IN, CMD_FADE_OUT, CMD_REVERSE, CMD_GAIN_FREE, CMD_GAIN_200, CMD_GAIN_150, CMD_GAIN_75, CMD_GAIN_50, CMD_GAIN_25, diff --git a/muse/muse/waveedit/waveview.cpp b/muse/muse/waveedit/waveview.cpp index 82c5ed32..1164df87 100644 --- a/muse/muse/waveedit/waveview.cpp +++ b/muse/muse/waveedit/waveview.cpp @@ -31,6 +31,8 @@ #include "gconfig.h" #include "part.h" +static const int partLabelHeight = 13; + //--------------------------------------------------------- // WaveView //--------------------------------------------------------- @@ -38,172 +40,147 @@ WaveView::WaveView(WaveEdit* pr) : TimeCanvas(TIME_CANVAS_WAVEEDIT) { + setMarkerList(song->marker()); selectionStart = 0; selectionStop = 0; lastGainvalue = 100; editor = pr; - if (editor->parts()->empty()) { - curPart = 0; - } - else { - curPart = editor->parts()->begin()->second; - } + curPart = editor->parts()->begin()->second; + setMouseTracking(true); songChanged(SC_TRACK_INSERTED); -#if 0 - int start = curPart->frame(); - int end = start + curPart->lenFrame(); - setTimeRange(start, end); -#endif } //--------------------------------------------------------- -// paint -//--------------------------------------------------------- - -void WaveView::paint(QPainter&, QRect) - { -// printf("paint\n"); - } - -//--------------------------------------------------------- -// draw +// drawWavePart +// y0 - start of track +// th - track height +// from - x pixel coordinate start drawing +// to - x end drawing +// +// redraw area is QRect(from, y0, to-from, th) //--------------------------------------------------------- -#if 0 -void WaveView::pdraw(QPainter& p, const QRect& rr) +void WaveView::drawWavePart(QPainter& p, Part* wp, int y0, int th, int from, int to) { - int x1 = rr.x(); - int x2 = rr.right() + 1; - if (x1 < 0) - x1 = 0; - if (x2 > width()) - x2 = width(); - int hh = height(); - int h = hh/2; - int y = rr.y() + h; - - for (iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip) { - Part* wp = ip->second; - int channels = wp->track()->channels(); - int px = wp->frame(); + int h = th/2; + int y = y0 + 1 + h; + int cc = th % 2 ? 0 : 1; + + const Pos pos(pix2pos(from)); + EventList* el = wp->events(); + for (iEvent e = el->begin(); e != el->end(); ++e) { + Event event = e->second; + SndFileR f = event.sndFile(); + if (f.isNull()) + continue; + unsigned channels = f.channels(); + if (channels == 0) { + printf("drawWavePart: channels==0! %s\n", f.finfo()->fileName().toLatin1().data()); + continue; + } - EventList* el = wp->events(); - for (iEvent e = el->begin(); e != el->end(); ++e) { - Event event = e->second; - if (event.empty()) - continue; - SndFileR f = event.sndFile(); - if (f.isNull()) - continue; - int xScale = xmag; - if (xScale < 0) - xScale = -xScale; - - int sx, ex; - sx = event.frame() + px + xScale/2 - startSample; - ex = sx + px + event.lenFrame(); - sx = sx / xScale - xpos; - ex = ex / xScale - xpos; - - if (sx < x1) - sx = x1; - if (ex > x2) - ex = x2; - - int pos = (xpos + sx) * xScale + event.spos() - event.frame() - px; - //printf("pos=%d xpos=%d sx=%d ex=%d xScale=%d event.spos=%d event.frame=%d px=%d\n", - // pos, xpos, sx, ex, xScale, event.spos(), event.frame(), px); - h = hh / (channels * 2); - int cc = hh % (channels * 2) ? 0 : 1; - - for (int i = sx; i < ex; i++) { - y = rr.y() + h; - SampleV sa[f.channels()]; - f.read(sa, xScale, pos); - pos += xScale; - if (pos < event.spos()) - continue; - - unsigned peoffset = px + event.frame() - event.spos(); - int selectionStartPos = selectionStart - peoffset; // Offset transformed to event coords - int selectionStopPos = selectionStop - peoffset; - - - - for (int k = 0; k < channels; ++k) { - int kk = k % f.channels(); - int peak = (sa[kk].peak * (h - 1)) / yScale; - int rms = (sa[kk].rms * (h - 1)) / yScale; - if (peak > h) - peak = h; - if (rms > h) - rms = h; - QColor peak_color = QColor(Qt::darkGray); - QColor rms_color = QColor(Qt::black); - if (pos > selectionStartPos && pos < selectionStopPos) { - peak_color = QColor(Qt::lightGray); - rms_color = QColor(Qt::white); - // Draw inverted - p.setPen(QColor(Qt::black)); - p.drawLine(i, y - h + cc, i, y + h - cc ); - } - p.setPen(peak_color); + int x1 = pos2pix(event.pos() + *wp); + int x2 = pos2pix(event.end() + *wp); + int w = x2 - x1; + if (w == 0) + continue; + + int samples = event.lenFrame(); + int xScale = (samples + w/2)/w; + int frame = pos.frame() - wp->frame() + - event.pos().frame() + event.spos(); + + if (h < 20) { + // + // combine multi channels into one waveform + // + for (int i = from; i < to; i++) { + SampleV sa[channels]; + f.read(sa, xScale, frame); + frame += xScale; + int peak = 0; + int rms = 0; + for (unsigned k = 0; k < channels; ++k) { + if (sa[k].peak > peak) + peak = sa[k].peak; + rms += sa[k].rms; + } + rms /= channels; + peak = (peak * (th-2)) >> 9; + rms = (rms * (th-2)) >> 9; + p.setPen(QColor(Qt::darkGray)); + p.drawLine(i, y - peak - cc, i, y + peak); + p.setPen(QColor(Qt::black)); + p.drawLine(i, y - rms - cc, i, y + rms); + } + } + else { + // + // multi channel display + // + h = th / (channels * 2); + int cc = th % (channels * 2) ? 0 : 1; + for (int i = from; i < to; i++) { + y = y0 + 1 + h; + SampleV sa[channels]; + f.read(sa, xScale, frame); + frame += xScale; + for (unsigned k = 0; k < channels; ++k) { + // peak = (sa[k].peak * h) / 256; + int peak = (sa[k].peak * (h - 1)) >> 8; + int rms = (sa[k].rms * (h - 1)) >> 8; + p.setPen(QColor(Qt::darkGray)); p.drawLine(i, y - peak - cc, i, y + peak); - p.setPen(rms_color); + p.setPen(QColor(Qt::black)); p.drawLine(i, y - rms - cc, i, y + rms); y += 2 * h; } } } } - View::pdraw(p, rr); } -#endif //--------------------------------------------------------- // draw //--------------------------------------------------------- -#if 0 -void WaveView::draw(QPainter& p, const QRect& r) +void WaveView::paint(QPainter& p, QRect r) { - unsigned x = r.x() < 0 ? 0 : r.x(); - unsigned y = r.y() < 0 ? 0 : r.y(); - int w = r.width(); - int h = r.height(); - - unsigned x2 = x + w; - unsigned y2 = y + h; - - // - // draw marker & centerline - // - p.setPen(Qt::red); - if (pos[0] >= x && pos[0] < x2) { - p.drawLine(pos[0], y, pos[0], y2); - } - p.setPen(Qt::blue); - if (pos[1] >= x && pos[1] < x2) { - p.drawLine(pos[1], y, pos[1], y2); - } - if (pos[2] >= x && pos[2] < x2) - p.drawLine(pos[2], y, pos[2], y2); - - int n = curPart->track()->channels(); - int hn = h / n; - int hh = hn / 2; - for (int i = 0; i < n; ++i) { - int h2 = hn * i; - int center = hh + h2; - p.setPen(QColor(i & i ? Qt::red : Qt::blue)); - p.drawLine(x, center, x2, center); - p.setPen(QColor(Qt::black)); - p.drawLine(x, h2, x2, h2); + QFont f = font(); + f.setPointSize(8); + p.setFont(f); + + int from = r.x(); + int to = from + r.width(); + + PartList* pl = editor->parts(); + for (iPart ip = pl->begin(); ip != pl->end(); ++ip) { + Part* part = ip->second; + int x1 = pos2pix(*part); + int x2 = pos2pix(part->end()); + int len = x2 - x1; + + if (x2 <= from) + continue; + if (x1 > to) + break; + + int h = rCanvasA.height(); + int xx1 = x1; + if (xx1 < from) + xx1 = from; + int xx2 = x2; + if (xx2 > to) + xx2 = to; + drawWavePart(p, part, 0, h, xx1, xx2); + int yy = h - partLabelHeight; + p.drawText(x1 + 3, yy, len - 6, + partLabelHeight-1, Qt::AlignVCenter | Qt::AlignLeft, + part->name()); } } -#endif //--------------------------------------------------------- // getCaption @@ -239,12 +216,6 @@ void WaveView::songChanged(int flags) // if (flags & SC_CLIP_MODIFIED) { // update(); // Boring, but the only thing possible to do // } -/* if (flags & SC_TEMPO) { - setPos(0, song->cpos(), false); - setPos(1, song->lpos(), false); - setPos(2, song->rpos(), false); - } -*/ setPart(*curPart, curPart->end()); widget()->update(); } diff --git a/muse/muse/waveedit/waveview.h b/muse/muse/waveedit/waveview.h index 6e4ad747..617a8744 100644 --- a/muse/muse/waveedit/waveview.h +++ b/muse/muse/waveedit/waveview.h @@ -89,6 +89,8 @@ class WaveView : public TimeCanvas { //void applyLadspa(unsigned channels, float** data, unsigned length); //!< Apply LADSPA plugin on selection + void drawWavePart(QPainter& p, Part* wp, int y0, int th, int from, int to); + public slots: void songChanged(int type); -- cgit v1.2.3