# HG changeset patch # User Chris Cannam # Date 1396267242 -3600 # Node ID efbb6b8f943b4d85c95a2eb76508794c4cbad463 # Parent b6dc57688c72ae31cc7825cef0cf68d5d698c0aa# Parent 394caa98d21a66bdb9942dd60e8be684a73d338c Merge from branch tonioni diff -r b6dc57688c72 -r efbb6b8f943b layer/FlexiNoteLayer.cpp --- a/layer/FlexiNoteLayer.cpp Tue Mar 11 17:34:23 2014 +0000 +++ b/layer/FlexiNoteLayer.cpp Mon Mar 31 13:00:42 2014 +0100 @@ -1214,15 +1214,21 @@ return; } - // MM: simpler declaration - FlexiNote note(0); - if (!getPointToDrag(v, e->x(), e->y(), note)) return; + long frame = v->getFrameForX(e->x()); - long frame = v->getFrameForX(e->x()); + splitNotesAt(v, frame); +} + +void +FlexiNoteLayer::splitNotesAt(View *v, int frame) +{ + FlexiNoteModel::PointList onPoints = m_model->getPoints(frame); + if (onPoints.empty()) return; + + FlexiNote note(*onPoints.begin()); int gap = 0; // MM: I prefer a gap of 0, but we can decide later - // MM: changed this a bit, to make it slightly clearer (// GF: nice changes!) FlexiNote newNote1(note.frame, note.value, frame - note.frame - gap, note.level, note.label); @@ -1230,23 +1236,24 @@ FlexiNote newNote2(frame, note.value, note.duration - newNote1.duration, note.level, note.label); - - if (m_intelligentActions) { - updateNoteValue(v,newNote1); - updateNoteValue(v,newNote2); - } FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand (m_model, tr("Edit Point")); command->deletePoint(note); - if ((e->modifiers() & Qt::ShiftModifier)) { - finish(command); - return; + + if (m_intelligentActions) { + if (updateNoteValue(v, newNote1)) { + command->addPoint(newNote1); + } + if (updateNoteValue(v, newNote2)) { + command->addPoint(newNote2); + } + } else { + command->addPoint(newNote1); + command->addPoint(newNote2); } - command->addPoint(newNote1); - command->addPoint(newNote2); + finish(command); - } void @@ -1276,8 +1283,7 @@ } if (!m_intelligentActions || - m_model->getPoints(frame).empty() && duration > 0) - { + (m_model->getPoints(frame).empty() && duration > 0)) { FlexiNote newNote(frame, value, duration, 100, "new note"); FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand (m_model, tr("Add Point")); @@ -1286,31 +1292,137 @@ } } +SparseTimeValueModel * +FlexiNoteLayer::getAssociatedPitchModel(View *v) const +{ + // Better than we used to do, but still not very satisfactory + + cerr << "FlexiNoteLayer::getAssociatedPitchModel()" << endl; + + for (int i = 0; i < v->getLayerCount(); ++i) { + Layer *layer = v->getLayer(i); + if (layer && !layer->isLayerDormant(v) && + layer->getLayerPresentationName() != "candidate") { + cerr << "FlexiNoteLayer::getAssociatedPitchModel: looks like our layer is " << layer << endl; + SparseTimeValueModel *model = qobject_cast + (layer->getModel()); + cerr << "FlexiNoteLayer::getAssociatedPitchModel: and its model is " << model << endl; + if (model && model->getScaleUnits() == "Hz") { + cerr << "FlexiNoteLayer::getAssociatedPitchModel: it's good, returning " << model << endl; + return model; + } + } + } + return 0; +} void +FlexiNoteLayer::snapSelectedNotesToPitchTrack(View *v, Selection s) +{ + if (!m_model) return; + + FlexiNoteModel::PointList points = + m_model->getPoints(s.getStartFrame(), s.getEndFrame()); + + FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand + (m_model, tr("Snap Notes")); + + cerr << "snapSelectedNotesToPitchTrack: selection is from " << s.getStartFrame() << " to " << s.getEndFrame() << endl; + + for (FlexiNoteModel::PointList::iterator i = points.begin(); + i != points.end(); ++i) { + + FlexiNote note(*i); + + cerr << "snapSelectedNotesToPitchTrack: looking at note from " << note.frame << " to " << note.frame + note.duration << endl; + + if (!s.contains(note.frame) && + !s.contains(note.frame + note.duration - 1)) { + continue; + } + + FlexiNote newNote(note); + + command->deletePoint(note); + + if (updateNoteValue(v, newNote)) { + command->addPoint(newNote); + } + } + + finish(command); +} + +void +FlexiNoteLayer::mergeNotes(View *v, Selection s, bool inclusive) +{ + FlexiNoteModel::PointList points = + m_model->getPoints(s.getStartFrame(), s.getEndFrame()); + + FlexiNoteModel::PointList::iterator i = points.begin(); + if (inclusive) { + while (i != points.end() && i->frame + i->duration < s.getStartFrame()) { + ++i; + } + } else { + while (i != points.end() && i->frame < s.getStartFrame()) { + ++i; + } + } + + if (i == points.end()) return; + + FlexiNoteModel::EditCommand *command = + new FlexiNoteModel::EditCommand(m_model, tr("Merge Notes")); + + FlexiNote newNote(*i); + + while (i != points.end()) { + + if (inclusive) { + if (i->frame >= s.getEndFrame()) break; + } else { + if (i->frame + i->duration > s.getEndFrame()) break; + } + + newNote.duration = i->frame + i->duration - newNote.frame; + command->deletePoint(*i); + + ++i; + } + + updateNoteValue(v, newNote); + command->addPoint(newNote); + finish(command); +} + +bool FlexiNoteLayer::updateNoteValue(View *v, FlexiNoteModel::Point ¬e) const { - //GF: update the note value conforming the median of pitch values in the underlying note layer - Layer *layer = v->getLayer(1); // GF: !!! gross assumption about correct layer order - SparseTimeValueModel *model = 0; - if (layer && layer->getModel()) - model = dynamic_cast(layer->getModel()); - - if (!model) return; + SparseTimeValueModel *model = getAssociatedPitchModel(v); + if (!model) return false; std::cerr << model->getTypeName() << std::endl; - SparseModel::PointList dataPoints = model->getPoints(note.frame, note.frame + note.duration); - if (dataPoints.empty()) return; + SparseModel::PointList dataPoints = + model->getPoints(note.frame, note.frame + note.duration); - // std::cerr << "frame " << note.frame << ": " << dataPoints.size() << " candidate points" << std::endl; + std::cerr << "frame " << note.frame << ": " << dataPoints.size() << " candidate points" << std::endl; + if (dataPoints.empty()) return false; + std::vector pitchValues; - for (SparseModel::PointList::const_iterator i = dataPoints.begin(); - i != dataPoints.end(); ++i) { - pitchValues.push_back((*i).value); + for (SparseModel::PointList::const_iterator i = + dataPoints.begin(); i != dataPoints.end(); ++i) { + if (i->frame >= note.frame && + i->frame < note.frame + note.duration) { + pitchValues.push_back(i->value); + } } + + if (pitchValues.empty()) return false; + sort(pitchValues.begin(), pitchValues.end()); size_t size = pitchValues.size(); double median; @@ -1322,6 +1434,8 @@ } note.value = median; + + return true; } void diff -r b6dc57688c72 -r efbb6b8f943b layer/FlexiNoteLayer.h --- a/layer/FlexiNoteLayer.h Tue Mar 11 17:34:23 2014 +0000 +++ b/layer/FlexiNoteLayer.h Mon Mar 31 13:00:42 2014 +0100 @@ -28,7 +28,7 @@ class View; class QPainter; - +class SparseTimeValueModel; class FlexiNoteLayer : public SingleColourLayer, public VerticalScaleLayer @@ -78,6 +78,10 @@ virtual bool paste(View *v, const Clipboard &from, int frameOffset, bool interactive); + void splitNotesAt(View *v, int frame); + void snapSelectedNotesToPitchTrack(View *v, Selection s); + void mergeNotes(View *v, Selection s, bool inclusive); + virtual const Model *getModel() const { return m_model; } void setModel(FlexiNoteModel *model); @@ -169,7 +173,8 @@ bool getPointToDrag(View *v, int x, int y, FlexiNoteModel::Point &) const; bool getNoteToEdit(View *v, int x, int y, FlexiNoteModel::Point &) const; void getRelativeMousePosition(View *v, FlexiNoteModel::Point ¬e, int x, int y, bool &closeToLeft, bool &closeToRight, bool &closeToTop, bool &closeToBottom) const; - void updateNoteValue(View *v, FlexiNoteModel::Point ¬e) const; + SparseTimeValueModel *getAssociatedPitchModel(View *v) const; + bool updateNoteValue(View *v, FlexiNoteModel::Point ¬e) const; FlexiNoteModel *m_model; bool m_editing; diff -r b6dc57688c72 -r efbb6b8f943b widgets/KeyReference.cpp --- a/widgets/KeyReference.cpp Tue Mar 11 17:34:23 2014 +0000 +++ b/widgets/KeyReference.cpp Mon Mar 31 13:00:42 2014 +0100 @@ -172,7 +172,8 @@ m_text->setReadOnly(true); m_dialog = new QDialog; - m_dialog->setWindowTitle(tr("Sonic Visualiser: Key and Mouse Reference")); + m_dialog->setWindowTitle(tr("%1: Key and Mouse Reference") + .arg(QApplication::applicationName())); QVBoxLayout *layout = new QVBoxLayout; m_dialog->setLayout(layout);