# HG changeset patch # User Chris Cannam # Date 1144432233 0 # Node ID 45ba0b381c5d2a854b36fc13df6904b35650e15f # Parent dfdbf336bb376aa2b56bc67eaf182ec3d21d5bc2 * Fix long-standing off-by-1 bug in WaveFileModel that was getting us the wrong values for almost all audio data when merging channels (channel == -1) * Implement cut, copy and paste * Make draw mode work properly in time value layer * Minor fixes to CSV import diff -r dfdbf336bb37 -r 45ba0b381c5d layer/Colour3DPlotLayer.cpp --- a/layer/Colour3DPlotLayer.cpp Thu Apr 06 12:12:41 2006 +0000 +++ b/layer/Colour3DPlotLayer.cpp Fri Apr 07 17:50:33 2006 +0000 @@ -333,6 +333,9 @@ paint.setPen(Qt::black);//!!! } } + +// std::cout << "rect " << rx0 << "," << (ry0 - h / sh - 1) << " " +// << w << "x" << (h / sh + 1) << std::endl; paint.drawRect(r); diff -r dfdbf336bb37 -r 45ba0b381c5d layer/NoteLayer.cpp --- a/layer/NoteLayer.cpp Thu Apr 06 12:12:41 2006 +0000 +++ b/layer/NoteLayer.cpp Fri Apr 07 17:50:33 2006 +0000 @@ -727,6 +727,72 @@ command->finish(); } +void +NoteLayer::deleteSelection(Selection s) +{ + NoteModel::EditCommand *command = + new NoteModel::EditCommand(m_model, tr("Delete Selected Points")); + + NoteModel::PointList points = + m_model->getPoints(s.getStartFrame(), s.getEndFrame()); + + for (NoteModel::PointList::iterator i = points.begin(); + i != points.end(); ++i) { + + if (s.contains(i->frame)) { + command->deletePoint(*i); + } + } + + command->finish(); +} + +void +NoteLayer::copy(Selection s, Clipboard &to) +{ + NoteModel::PointList points = + m_model->getPoints(s.getStartFrame(), s.getEndFrame()); + + for (NoteModel::PointList::iterator i = points.begin(); + i != points.end(); ++i) { + if (s.contains(i->frame)) { + Clipboard::Point point(i->frame, i->label); + to.addPoint(point); + } + } +} + +void +NoteLayer::paste(const Clipboard &from, int frameOffset) +{ + const Clipboard::PointList &points = from.getPoints(); + + NoteModel::EditCommand *command = + new NoteModel::EditCommand(m_model, tr("Paste")); + + for (Clipboard::PointList::const_iterator i = points.begin(); + i != points.end(); ++i) { + + if (!i->haveFrame()) continue; + size_t frame = 0; + if (frameOffset > 0 || -frameOffset < i->getFrame()) { + frame = i->getFrame() + frameOffset; + } + NoteModel::Point newPoint(frame); + + if (i->haveLabel()) newPoint.label = i->getLabel(); + if (i->haveValue()) newPoint.value = i->getValue(); + else newPoint.value = (m_model->getValueMinimum() + + m_model->getValueMaximum()) / 2; + if (i->haveDuration()) newPoint.duration = i->getDuration(); + else newPoint.duration = m_model->getResolution(); //!!! + + command->addPoint(newPoint); + } + + command->finish(); +} + QString NoteLayer::toXmlString(QString indent, QString extraAttributes) const { diff -r dfdbf336bb37 -r 45ba0b381c5d layer/NoteLayer.h --- a/layer/NoteLayer.h Thu Apr 06 12:12:41 2006 +0000 +++ b/layer/NoteLayer.h Fri Apr 07 17:50:33 2006 +0000 @@ -52,6 +52,10 @@ virtual void moveSelection(Selection s, size_t newStartFrame); virtual void resizeSelection(Selection s, Selection newSize); + virtual void deleteSelection(Selection s); + + virtual void copy(Selection s, Clipboard &to); + virtual void paste(const Clipboard &from, int frameOffset); virtual const Model *getModel() const { return m_model; } void setModel(NoteModel *model); diff -r dfdbf336bb37 -r 45ba0b381c5d layer/TextLayer.cpp --- a/layer/TextLayer.cpp Thu Apr 06 12:12:41 2006 +0000 +++ b/layer/TextLayer.cpp Fri Apr 07 17:50:33 2006 +0000 @@ -651,6 +651,65 @@ command->finish(); } +void +TextLayer::deleteSelection(Selection s) +{ + TextModel::EditCommand *command = + new TextModel::EditCommand(m_model, tr("Delete Selection")); + + TextModel::PointList points = + m_model->getPoints(s.getStartFrame(), s.getEndFrame()); + + for (TextModel::PointList::iterator i = points.begin(); + i != points.end(); ++i) { + if (s.contains(i->frame)) command->deletePoint(*i); + } + + command->finish(); +} + +void +TextLayer::copy(Selection s, Clipboard &to) +{ + TextModel::PointList points = + m_model->getPoints(s.getStartFrame(), s.getEndFrame()); + + for (TextModel::PointList::iterator i = points.begin(); + i != points.end(); ++i) { + if (s.contains(i->frame)) { + Clipboard::Point point(i->frame, i->height, i->label); + to.addPoint(point); + } + } +} + +void +TextLayer::paste(const Clipboard &from, int frameOffset) +{ + const Clipboard::PointList &points = from.getPoints(); + + TextModel::EditCommand *command = + new TextModel::EditCommand(m_model, tr("Paste")); + + for (Clipboard::PointList::const_iterator i = points.begin(); + i != points.end(); ++i) { + + if (!i->haveFrame()) continue; + size_t frame = 0; + if (frameOffset > 0 || -frameOffset < i->getFrame()) { + frame = i->getFrame() + frameOffset; + } + TextModel::Point newPoint(frame); + if (i->haveValue()) newPoint.height = i->haveValue(); + if (i->haveLabel()) newPoint.label = i->getLabel(); + else newPoint.label = tr("New Point"); + + command->addPoint(newPoint); + } + + command->finish(); +} + QString TextLayer::toXmlString(QString indent, QString extraAttributes) const { diff -r dfdbf336bb37 -r 45ba0b381c5d layer/TextLayer.h --- a/layer/TextLayer.h Thu Apr 06 12:12:41 2006 +0000 +++ b/layer/TextLayer.h Fri Apr 07 17:50:33 2006 +0000 @@ -50,6 +50,10 @@ virtual void moveSelection(Selection s, size_t newStartFrame); virtual void resizeSelection(Selection s, Selection newSize); + virtual void deleteSelection(Selection s); + + virtual void copy(Selection s, Clipboard &to); + virtual void paste(const Clipboard &from, int frameOffset); virtual void editOpen(View *, QMouseEvent *); // on double-click diff -r dfdbf336bb37 -r 45ba0b381c5d layer/TimeInstantLayer.cpp --- a/layer/TimeInstantLayer.cpp Thu Apr 06 12:12:41 2006 +0000 +++ b/layer/TimeInstantLayer.cpp Fri Apr 07 17:50:33 2006 +0000 @@ -19,6 +19,7 @@ #include "base/RealTime.h" #include "base/View.h" #include "base/Profiler.h" +#include "base/Clipboard.h" #include "model/SparseOneDimensionalModel.h" @@ -689,7 +690,46 @@ command->finish(); } - + +void +TimeInstantLayer::copy(Selection s, Clipboard &to) +{ + SparseOneDimensionalModel::PointList points = + m_model->getPoints(s.getStartFrame(), s.getEndFrame()); + + for (SparseOneDimensionalModel::PointList::iterator i = points.begin(); + i != points.end(); ++i) { + if (s.contains(i->frame)) { + Clipboard::Point point(i->frame, i->label); + to.addPoint(point); + } + } +} + +void +TimeInstantLayer::paste(const Clipboard &from, int frameOffset) +{ + const Clipboard::PointList &points = from.getPoints(); + + SparseOneDimensionalModel::EditCommand *command = + new SparseOneDimensionalModel::EditCommand(m_model, tr("Paste")); + + for (Clipboard::PointList::const_iterator i = points.begin(); + i != points.end(); ++i) { + + if (!i->haveFrame()) continue; + size_t frame = 0; + if (frameOffset > 0 || -frameOffset < i->getFrame()) { + frame = i->getFrame() + frameOffset; + } + SparseOneDimensionalModel::Point newPoint(frame); + if (i->haveLabel()) newPoint.label = i->getLabel(); + + command->addPoint(newPoint); + } + + command->finish(); +} QString TimeInstantLayer::toXmlString(QString indent, QString extraAttributes) const diff -r dfdbf336bb37 -r 45ba0b381c5d layer/TimeInstantLayer.h --- a/layer/TimeInstantLayer.h Thu Apr 06 12:12:41 2006 +0000 +++ b/layer/TimeInstantLayer.h Fri Apr 07 17:50:33 2006 +0000 @@ -54,6 +54,9 @@ virtual void resizeSelection(Selection s, Selection newSize); virtual void deleteSelection(Selection s); + virtual void copy(Selection s, Clipboard &to); + virtual void paste(const Clipboard &from, int frameOffset); + virtual const Model *getModel() const { return m_model; } void setModel(SparseOneDimensionalModel *model); diff -r dfdbf336bb37 -r 45ba0b381c5d layer/TimeValueLayer.cpp --- a/layer/TimeValueLayer.cpp Thu Apr 06 12:12:41 2006 +0000 +++ b/layer/TimeValueLayer.cpp Fri Apr 07 17:50:33 2006 +0000 @@ -502,7 +502,8 @@ int y = getYForValue(v, p.value); bool haveNext = false; - int nx = v->getXForFrame(m_model->getEndFrame()); + int nx = v->getXForFrame(v->getModelsEndFrame()); +// m_model->getEndFrame()); int ny = y; SparseTimeValueModel::PointList::const_iterator j = i; @@ -513,7 +514,10 @@ nx = v->getXForFrame(q.frame); ny = getYForValue(v, q.value); haveNext = true; - } + } + +// std::cout << "frame = " << p.frame << ", x = " << x << ", haveNext = " << haveNext +// << ", nx = " << nx << std::endl; int labelY = y; @@ -608,6 +612,8 @@ } if (m_plotStyle == PlotSegmentation) { + +// std::cerr << "drawing rect" << std::endl; if (nx <= x) continue; @@ -728,18 +734,40 @@ if (!m_model) return; long frame = v->getFrameForX(e->x()); + long resolution = m_model->getResolution(); if (frame < 0) frame = 0; - frame = frame / m_model->getResolution() * m_model->getResolution(); + frame = (frame / resolution) * resolution; float value = getValueForY(v, e->y()); - m_editingPoint = SparseTimeValueModel::Point(frame, value, tr("New Point")); + bool havePoint = false; + + SparseTimeValueModel::PointList points = getLocalPoints(v, e->x()); + if (!points.empty()) { + for (SparseTimeValueModel::PointList::iterator i = points.begin(); + i != points.end(); ++i) { + if (((i->frame / resolution) * resolution) != frame) { + std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl; + continue; + } + m_editingPoint = *i; + havePoint = true; + } + } + + if (!havePoint) { + m_editingPoint = SparseTimeValueModel::Point + (frame, value, tr("New Point")); + } + m_originalPoint = m_editingPoint; if (m_editingCommand) m_editingCommand->finish(); m_editingCommand = new SparseTimeValueModel::EditCommand(m_model, tr("Draw Point")); - m_editingCommand->addPoint(m_editingPoint); + if (!havePoint) { + m_editingCommand->addPoint(m_editingPoint); + } m_editing = true; } @@ -752,12 +780,45 @@ if (!m_model || !m_editing) return; long frame = v->getFrameForX(e->x()); + long resolution = m_model->getResolution(); if (frame < 0) frame = 0; - frame = frame / m_model->getResolution() * m_model->getResolution(); + frame = (frame / resolution) * resolution; float value = getValueForY(v, e->y()); - m_editingCommand->deletePoint(m_editingPoint); + SparseTimeValueModel::PointList points = getLocalPoints(v, e->x()); + + std::cerr << points.size() << " points" << std::endl; + + bool havePoint = false; + + if (!points.empty()) { + for (SparseTimeValueModel::PointList::iterator i = points.begin(); + i != points.end(); ++i) { + if (i->frame == m_editingPoint.frame && + i->value == m_editingPoint.value) { + std::cerr << "ignoring current editing point at " << i->frame << ", " << i->value << std::endl; + continue; + } + if (((i->frame / resolution) * resolution) != frame) { + std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl; + continue; + } + std::cerr << "adjusting to new point at " << i->frame << ", " << i->value << std::endl; + m_editingPoint = *i; + m_originalPoint = m_editingPoint; + m_editingCommand->deletePoint(m_editingPoint); + havePoint = true; + } + } + + if (!havePoint) { + if (frame == m_editingPoint.frame) { + m_editingCommand->deletePoint(m_editingPoint); + } + } + +// m_editingCommand->deletePoint(m_editingPoint); m_editingPoint.frame = frame; m_editingPoint.value = value; m_editingCommand->addPoint(m_editingPoint); @@ -941,6 +1002,71 @@ command->finish(); } +void +TimeValueLayer::deleteSelection(Selection s) +{ + SparseTimeValueModel::EditCommand *command = + new SparseTimeValueModel::EditCommand(m_model, + tr("Delete Selected Points")); + + SparseTimeValueModel::PointList points = + m_model->getPoints(s.getStartFrame(), s.getEndFrame()); + + for (SparseTimeValueModel::PointList::iterator i = points.begin(); + i != points.end(); ++i) { + + if (s.contains(i->frame)) { + command->deletePoint(*i); + } + } + + command->finish(); +} + +void +TimeValueLayer::copy(Selection s, Clipboard &to) +{ + SparseTimeValueModel::PointList points = + m_model->getPoints(s.getStartFrame(), s.getEndFrame()); + + for (SparseTimeValueModel::PointList::iterator i = points.begin(); + i != points.end(); ++i) { + if (s.contains(i->frame)) { + Clipboard::Point point(i->frame, i->label); + to.addPoint(point); + } + } +} + +void +TimeValueLayer::paste(const Clipboard &from, int frameOffset) +{ + const Clipboard::PointList &points = from.getPoints(); + + SparseTimeValueModel::EditCommand *command = + new SparseTimeValueModel::EditCommand(m_model, tr("Paste")); + + for (Clipboard::PointList::const_iterator i = points.begin(); + i != points.end(); ++i) { + + if (!i->haveFrame()) continue; + size_t frame = 0; + if (frameOffset > 0 || -frameOffset < i->getFrame()) { + frame = i->getFrame() + frameOffset; + } + SparseTimeValueModel::Point newPoint(frame); + + if (i->haveLabel()) newPoint.label = i->getLabel(); + if (i->haveValue()) newPoint.value = i->getValue(); + else newPoint.value = (m_model->getValueMinimum() + + m_model->getValueMaximum()) / 2; + + command->addPoint(newPoint); + } + + command->finish(); +} + QString TimeValueLayer::toXmlString(QString indent, QString extraAttributes) const { diff -r dfdbf336bb37 -r 45ba0b381c5d layer/TimeValueLayer.h --- a/layer/TimeValueLayer.h Thu Apr 06 12:12:41 2006 +0000 +++ b/layer/TimeValueLayer.h Fri Apr 07 17:50:33 2006 +0000 @@ -55,6 +55,10 @@ virtual void moveSelection(Selection s, size_t newStartFrame); virtual void resizeSelection(Selection s, Selection newSize); + virtual void deleteSelection(Selection s); + + virtual void copy(Selection s, Clipboard &to); + virtual void paste(const Clipboard &from, int frameOffset); virtual const Model *getModel() const { return m_model; } void setModel(SparseTimeValueModel *model); diff -r dfdbf336bb37 -r 45ba0b381c5d layer/WaveformLayer.cpp --- a/layer/WaveformLayer.cpp Thu Apr 06 12:12:41 2006 +0000 +++ b/layer/WaveformLayer.cpp Fri Apr 07 17:50:33 2006 +0000 @@ -892,18 +892,31 @@ else label = tr("Channel %1").arg(ch + 1); } - int min = int(range.min * 1000); - int max = int(range.max * 1000); + bool singleValue = false; + float min, max; + + if (fabs(range.min) < 0.01) { + min = range.min; + max = range.max; + singleValue = (min == max); + } else { + int imin = int(range.min * 1000); + int imax = int(range.max * 1000); + singleValue = (imin == imax); + min = float(imin)/1000; + max = float(imax)/1000; + } + int db = int(AudioLevel::multiplier_to_dB(std::max(fabsf(range.min), fabsf(range.max))) * 100); - if (min != max) { + if (!singleValue) { text += tr("\n%1\t%2 - %3 (%4 dB peak)") - .arg(label).arg(float(min)/1000).arg(float(max)/1000).arg(float(db)/100); + .arg(label).arg(min).arg(max).arg(float(db)/100); } else { text += tr("\n%1\t%2 (%3 dB peak)") - .arg(label).arg(float(min)/1000).arg(float(db)/100); + .arg(label).arg(min).arg(float(db)/100); } } diff -r dfdbf336bb37 -r 45ba0b381c5d widgets/PluginParameterDialog.cpp --- a/widgets/PluginParameterDialog.cpp Thu Apr 06 12:12:41 2006 +0000 +++ b/widgets/PluginParameterDialog.cpp Fri Apr 07 17:50:33 2006 +0000 @@ -131,7 +131,7 @@ channelLayout->addWidget(new QLabel(tr("This plugin only has a single channel input,\nbut the source has %1 channels.").arg(sourceChannels))); QComboBox *channelCombo = new QComboBox; - channelCombo->addItem(tr("Use sum of source channels")); + channelCombo->addItem(tr("Use mean of source channels")); for (int i = 0; i < sourceChannels; ++i) { channelCombo->addItem(tr("Use channel %1 only").arg(i + 1)); }