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 &note) const 1409 FlexiNoteLayer::updateNoteValue(View *v, FlexiNoteModel::Point &note) 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 {