Mercurial > hg > svgui
comparison layer/FlexiNoteLayer.cpp @ 756:9cfcb2924ee3 tony_integration
Merge from branch tonioni
author | Chris Cannam |
---|---|
date | Wed, 02 Apr 2014 08:51:33 +0100 |
parents | 09e2677e34e7 |
children | 6388ddae6ce3 |
comparison
equal
deleted
inserted
replaced
755:ad01e7d4a956 | 756:9cfcb2924ee3 |
---|---|
1041 | 1041 |
1042 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; | 1042 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; |
1043 m_originalPoint = FlexiNote(m_editingPoint); | 1043 m_originalPoint = FlexiNote(m_editingPoint); |
1044 | 1044 |
1045 if (m_editMode == RightBoundary) { | 1045 if (m_editMode == RightBoundary) { |
1046 m_dragPointX = v->getXForFrame(m_editingPoint.frame + m_editingPoint.duration); | 1046 m_dragPointX = v->getXForFrame(m_editingPoint.frame + m_editingPoint.duration); |
1047 } else { | 1047 } else { |
1048 m_dragPointX = v->getXForFrame(m_editingPoint.frame); | 1048 m_dragPointX = v->getXForFrame(m_editingPoint.frame); |
1049 } | 1049 } |
1050 m_dragPointY = getYForValue(v, m_editingPoint.value); | 1050 m_dragPointY = getYForValue(v, m_editingPoint.value); |
1051 | 1051 |
1077 if (currentNote.frame > offset) { | 1077 if (currentNote.frame > offset) { |
1078 m_smallestRightNeighbourFrame = currentNote.frame; | 1078 m_smallestRightNeighbourFrame = currentNote.frame; |
1079 break; | 1079 break; |
1080 } | 1080 } |
1081 } | 1081 } |
1082 std::cerr << "note frame: " << onset << ", left boundary: " << m_greatestLeftNeighbourFrame << ", right boundary: " << m_smallestRightNeighbourFrame << std::endl; | 1082 std::cerr << "editStart: mode is " << m_editMode << ", note frame: " << onset << ", left boundary: " << m_greatestLeftNeighbourFrame << ", right boundary: " << m_smallestRightNeighbourFrame << std::endl; |
1083 } | 1083 } |
1084 | 1084 |
1085 void | 1085 void |
1086 FlexiNoteLayer::editDrag(View *v, QMouseEvent *e) | 1086 FlexiNoteLayer::editDrag(View *v, QMouseEvent *e) |
1087 { | 1087 { |
1212 if (xdist != 0 || ydist != 0) { | 1212 if (xdist != 0 || ydist != 0) { |
1213 std::cerr << "mouse moved" << std::endl; | 1213 std::cerr << "mouse moved" << std::endl; |
1214 return; | 1214 return; |
1215 } | 1215 } |
1216 | 1216 |
1217 // MM: simpler declaration | |
1218 FlexiNote note(0); | |
1219 if (!getPointToDrag(v, e->x(), e->y(), note)) return; | |
1220 | |
1221 long frame = v->getFrameForX(e->x()); | 1217 long frame = v->getFrameForX(e->x()); |
1222 | 1218 |
1223 int gap = 0; // MM: I prefer a gap of 0, but we can decide later | 1219 splitNotesAt(v, frame, e); |
1224 | 1220 } |
1225 // MM: changed this a bit, to make it slightly clearer (// GF: nice changes!) | 1221 |
1226 FlexiNote newNote1(note.frame, note.value, | 1222 void |
1227 frame - note.frame - gap, | 1223 FlexiNoteLayer::splitNotesAt(View *v, int frame) |
1228 note.level, note.label); | 1224 { |
1229 | 1225 splitNotesAt(v, frame, 0); |
1230 FlexiNote newNote2(frame, note.value, | 1226 } |
1231 note.duration - newNote1.duration, | 1227 |
1232 note.level, note.label); | 1228 void |
1233 | 1229 FlexiNoteLayer::splitNotesAt(View *v, int frame, QMouseEvent *e) |
1234 if (m_intelligentActions) { | 1230 { |
1235 updateNoteValue(v,newNote1); | 1231 FlexiNoteModel::PointList onPoints = m_model->getPoints(frame); |
1236 updateNoteValue(v,newNote2); | 1232 if (onPoints.empty()) return; |
1237 } | 1233 |
1234 FlexiNote note(*onPoints.begin()); | |
1238 | 1235 |
1239 FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand | 1236 FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand |
1240 (m_model, tr("Edit Point")); | 1237 (m_model, tr("Edit Point")); |
1241 command->deletePoint(note); | 1238 command->deletePoint(note); |
1242 if ((e->modifiers() & Qt::ShiftModifier)) { | 1239 |
1243 finish(command); | 1240 if (!e || !(e->modifiers() & Qt::ShiftModifier)) { |
1244 return; | 1241 |
1245 } | 1242 int gap = 0; // MM: I prefer a gap of 0, but we can decide later |
1246 command->addPoint(newNote1); | 1243 |
1247 command->addPoint(newNote2); | 1244 FlexiNote newNote1(note.frame, note.value, |
1245 frame - note.frame - gap, | |
1246 note.level, note.label); | |
1247 | |
1248 FlexiNote newNote2(frame, note.value, | |
1249 note.duration - newNote1.duration, | |
1250 note.level, note.label); | |
1251 | |
1252 if (m_intelligentActions) { | |
1253 if (updateNoteValue(v, newNote1)) { | |
1254 command->addPoint(newNote1); | |
1255 } | |
1256 if (updateNoteValue(v, newNote2)) { | |
1257 command->addPoint(newNote2); | |
1258 } | |
1259 } else { | |
1260 command->addPoint(newNote1); | |
1261 command->addPoint(newNote2); | |
1262 } | |
1263 } | |
1264 | |
1248 finish(command); | 1265 finish(command); |
1249 | |
1250 } | 1266 } |
1251 | 1267 |
1252 void | 1268 void |
1253 FlexiNoteLayer::addNote(View *v, QMouseEvent *e) | 1269 FlexiNoteLayer::addNote(View *v, QMouseEvent *e) |
1254 { | 1270 { |
1274 duration = std::min(smallestRightNeighbourFrame - frame + 1, duration); | 1290 duration = std::min(smallestRightNeighbourFrame - frame + 1, duration); |
1275 duration = (duration > 0) ? duration : 0; | 1291 duration = (duration > 0) ? duration : 0; |
1276 } | 1292 } |
1277 | 1293 |
1278 if (!m_intelligentActions || | 1294 if (!m_intelligentActions || |
1279 m_model->getPoints(frame).empty() && duration > 0) | 1295 (m_model->getPoints(frame).empty() && duration > 0)) { |
1280 { | |
1281 FlexiNote newNote(frame, value, duration, 100, "new note"); | 1296 FlexiNote newNote(frame, value, duration, 100, "new note"); |
1282 FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand | 1297 FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand |
1283 (m_model, tr("Add Point")); | 1298 (m_model, tr("Add Point")); |
1284 command->addPoint(newNote); | 1299 command->addPoint(newNote); |
1285 finish(command); | 1300 finish(command); |
1286 } | 1301 } |
1287 } | 1302 } |
1288 | 1303 |
1289 | 1304 SparseTimeValueModel * |
1290 void | 1305 FlexiNoteLayer::getAssociatedPitchModel(View *v) const |
1306 { | |
1307 // Better than we used to do, but still not very satisfactory | |
1308 | |
1309 cerr << "FlexiNoteLayer::getAssociatedPitchModel()" << endl; | |
1310 | |
1311 for (int i = 0; i < v->getLayerCount(); ++i) { | |
1312 Layer *layer = v->getLayer(i); | |
1313 if (layer && !layer->isLayerDormant(v) && | |
1314 layer->getLayerPresentationName() != "candidate") { | |
1315 cerr << "FlexiNoteLayer::getAssociatedPitchModel: looks like our layer is " << layer << endl; | |
1316 SparseTimeValueModel *model = qobject_cast<SparseTimeValueModel *> | |
1317 (layer->getModel()); | |
1318 cerr << "FlexiNoteLayer::getAssociatedPitchModel: and its model is " << model << endl; | |
1319 if (model && model->getScaleUnits() == "Hz") { | |
1320 cerr << "FlexiNoteLayer::getAssociatedPitchModel: it's good, returning " << model << endl; | |
1321 return model; | |
1322 } | |
1323 } | |
1324 } | |
1325 return 0; | |
1326 } | |
1327 | |
1328 void | |
1329 FlexiNoteLayer::snapSelectedNotesToPitchTrack(View *v, Selection s) | |
1330 { | |
1331 if (!m_model) return; | |
1332 | |
1333 FlexiNoteModel::PointList points = | |
1334 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); | |
1335 | |
1336 FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand | |
1337 (m_model, tr("Snap Notes")); | |
1338 | |
1339 cerr << "snapSelectedNotesToPitchTrack: selection is from " << s.getStartFrame() << " to " << s.getEndFrame() << endl; | |
1340 | |
1341 for (FlexiNoteModel::PointList::iterator i = points.begin(); | |
1342 i != points.end(); ++i) { | |
1343 | |
1344 FlexiNote note(*i); | |
1345 | |
1346 cerr << "snapSelectedNotesToPitchTrack: looking at note from " << note.frame << " to " << note.frame + note.duration << endl; | |
1347 | |
1348 if (!s.contains(note.frame) && | |
1349 !s.contains(note.frame + note.duration - 1)) { | |
1350 continue; | |
1351 } | |
1352 | |
1353 FlexiNote newNote(note); | |
1354 | |
1355 command->deletePoint(note); | |
1356 | |
1357 if (updateNoteValue(v, newNote)) { | |
1358 command->addPoint(newNote); | |
1359 } | |
1360 } | |
1361 | |
1362 finish(command); | |
1363 } | |
1364 | |
1365 void | |
1366 FlexiNoteLayer::mergeNotes(View *v, Selection s, bool inclusive) | |
1367 { | |
1368 FlexiNoteModel::PointList points = | |
1369 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); | |
1370 | |
1371 FlexiNoteModel::PointList::iterator i = points.begin(); | |
1372 if (inclusive) { | |
1373 while (i != points.end() && i->frame + i->duration < s.getStartFrame()) { | |
1374 ++i; | |
1375 } | |
1376 } else { | |
1377 while (i != points.end() && i->frame < s.getStartFrame()) { | |
1378 ++i; | |
1379 } | |
1380 } | |
1381 | |
1382 if (i == points.end()) return; | |
1383 | |
1384 FlexiNoteModel::EditCommand *command = | |
1385 new FlexiNoteModel::EditCommand(m_model, tr("Merge Notes")); | |
1386 | |
1387 FlexiNote newNote(*i); | |
1388 | |
1389 while (i != points.end()) { | |
1390 | |
1391 if (inclusive) { | |
1392 if (i->frame >= s.getEndFrame()) break; | |
1393 } else { | |
1394 if (i->frame + i->duration > s.getEndFrame()) break; | |
1395 } | |
1396 | |
1397 newNote.duration = i->frame + i->duration - newNote.frame; | |
1398 command->deletePoint(*i); | |
1399 | |
1400 ++i; | |
1401 } | |
1402 | |
1403 updateNoteValue(v, newNote); | |
1404 command->addPoint(newNote); | |
1405 finish(command); | |
1406 } | |
1407 | |
1408 bool | |
1291 FlexiNoteLayer::updateNoteValue(View *v, FlexiNoteModel::Point ¬e) const | 1409 FlexiNoteLayer::updateNoteValue(View *v, FlexiNoteModel::Point ¬e) const |
1292 { | 1410 { |
1293 //GF: update the note value conforming the median of pitch values in the underlying note layer | 1411 SparseTimeValueModel *model = getAssociatedPitchModel(v); |
1294 Layer *layer = v->getLayer(1); // GF: !!! gross assumption about correct layer order | 1412 if (!model) return false; |
1295 SparseTimeValueModel *model = 0; | |
1296 if (layer && layer->getModel()) | |
1297 model = dynamic_cast<SparseTimeValueModel *>(layer->getModel()); | |
1298 | |
1299 if (!model) return; | |
1300 | 1413 |
1301 std::cerr << model->getTypeName() << std::endl; | 1414 std::cerr << model->getTypeName() << std::endl; |
1302 | 1415 |
1303 SparseModel<TimeValuePoint>::PointList dataPoints = model->getPoints(note.frame, note.frame + note.duration); | 1416 SparseModel<TimeValuePoint>::PointList dataPoints = |
1304 if (dataPoints.empty()) return; | 1417 model->getPoints(note.frame, note.frame + note.duration); |
1305 | 1418 |
1306 // std::cerr << "frame " << note.frame << ": " << dataPoints.size() << " candidate points" << std::endl; | 1419 std::cerr << "frame " << note.frame << ": " << dataPoints.size() << " candidate points" << std::endl; |
1307 | 1420 |
1421 if (dataPoints.empty()) return false; | |
1422 | |
1308 std::vector<float> pitchValues; | 1423 std::vector<float> pitchValues; |
1309 | 1424 |
1310 for (SparseModel<TimeValuePoint>::PointList::const_iterator i = dataPoints.begin(); | 1425 for (SparseModel<TimeValuePoint>::PointList::const_iterator i = |
1311 i != dataPoints.end(); ++i) { | 1426 dataPoints.begin(); i != dataPoints.end(); ++i) { |
1312 pitchValues.push_back((*i).value); | 1427 if (i->frame >= note.frame && |
1313 } | 1428 i->frame < note.frame + note.duration) { |
1429 pitchValues.push_back(i->value); | |
1430 } | |
1431 } | |
1432 | |
1433 if (pitchValues.empty()) return false; | |
1434 | |
1314 sort(pitchValues.begin(), pitchValues.end()); | 1435 sort(pitchValues.begin(), pitchValues.end()); |
1315 size_t size = pitchValues.size(); | 1436 size_t size = pitchValues.size(); |
1316 double median; | 1437 double median; |
1317 | 1438 |
1318 if (size % 2 == 0) { | 1439 if (size % 2 == 0) { |
1320 } else { | 1441 } else { |
1321 median = pitchValues[size/2]; | 1442 median = pitchValues[size/2]; |
1322 } | 1443 } |
1323 | 1444 |
1324 note.value = median; | 1445 note.value = median; |
1446 | |
1447 return true; | |
1325 } | 1448 } |
1326 | 1449 |
1327 void | 1450 void |
1328 FlexiNoteLayer::mouseMoveEvent(View *v, QMouseEvent *e) | 1451 FlexiNoteLayer::mouseMoveEvent(View *v, QMouseEvent *e) |
1329 { | 1452 { |