Mercurial > hg > silvet
comparison src/Silvet.cpp @ 320:7f9683c8de69 livemode
Refactor velocity calculations
author | Chris Cannam |
---|---|
date | Wed, 29 Apr 2015 09:51:09 +0100 |
parents | c37da62ba4e5 |
children | 213a51e197c8 |
comparison
equal
deleted
inserted
replaced
319:c37da62ba4e5 | 320:7f9683c8de69 |
---|---|
305 d.hasFixedBinCount = true; | 305 d.hasFixedBinCount = true; |
306 d.binCount = getPack(0).templateNoteCount; | 306 d.binCount = getPack(0).templateNoteCount; |
307 d.binNames.clear(); | 307 d.binNames.clear(); |
308 if (m_cq) { | 308 if (m_cq) { |
309 for (int i = 0; i < getPack(0).templateNoteCount; ++i) { | 309 for (int i = 0; i < getPack(0).templateNoteCount; ++i) { |
310 d.binNames.push_back(noteName(i, 0, 1)); | 310 d.binNames.push_back(getNoteName(i, 0, 1)); |
311 } | 311 } |
312 } | 312 } |
313 d.hasKnownExtents = false; | 313 d.hasKnownExtents = false; |
314 d.isQuantized = false; | 314 d.isQuantized = false; |
315 d.sampleType = OutputDescriptor::FixedSampleRate; | 315 d.sampleType = OutputDescriptor::FixedSampleRate; |
325 d.hasFixedBinCount = true; | 325 d.hasFixedBinCount = true; |
326 d.binCount = 12; | 326 d.binCount = 12; |
327 d.binNames.clear(); | 327 d.binNames.clear(); |
328 if (m_cq) { | 328 if (m_cq) { |
329 for (int i = 0; i < 12; ++i) { | 329 for (int i = 0; i < 12; ++i) { |
330 d.binNames.push_back(chromaName(i)); | 330 d.binNames.push_back(getChromaName(i)); |
331 } | 331 } |
332 } | 332 } |
333 d.hasKnownExtents = false; | 333 d.hasKnownExtents = false; |
334 d.isQuantized = false; | 334 d.isQuantized = false; |
335 d.sampleType = OutputDescriptor::FixedSampleRate; | 335 d.sampleType = OutputDescriptor::FixedSampleRate; |
369 | 369 |
370 return list; | 370 return list; |
371 } | 371 } |
372 | 372 |
373 std::string | 373 std::string |
374 Silvet::chromaName(int pitch) const | 374 Silvet::getChromaName(int pitch) const |
375 { | 375 { |
376 static const char *names[] = { | 376 static const char *names[] = { |
377 "A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#" | 377 "A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#" |
378 }; | 378 }; |
379 | 379 |
380 return names[pitch]; | 380 return names[pitch]; |
381 } | 381 } |
382 | 382 |
383 std::string | 383 std::string |
384 Silvet::noteName(int note, int shift, int shiftCount) const | 384 Silvet::getNoteName(int note, int shift, int shiftCount) const |
385 { | 385 { |
386 string n = chromaName(note % 12); | 386 string n = getChromaName(note % 12); |
387 | 387 |
388 int oct = (note + 9) / 12; | 388 int oct = (note + 9) / 12; |
389 | 389 |
390 char buf[30]; | 390 char buf[30]; |
391 | 391 |
392 float pshift = 0.f; | 392 float pshift = 0.f; |
393 if (shiftCount > 1) { | 393 if (shiftCount > 1) { |
394 // see noteFrequency below | 394 // see getNoteFrequency below |
395 pshift = | 395 pshift = |
396 float((shiftCount - shift) - int(shiftCount / 2) - 1) / shiftCount; | 396 float((shiftCount - shift) - int(shiftCount / 2) - 1) / shiftCount; |
397 } | 397 } |
398 | 398 |
399 if (pshift > 0.f) { | 399 if (pshift > 0.f) { |
406 | 406 |
407 return buf; | 407 return buf; |
408 } | 408 } |
409 | 409 |
410 float | 410 float |
411 Silvet::noteFrequency(int note, int shift, int shiftCount) const | 411 Silvet::getNoteFrequency(int note, int shift, int shiftCount) const |
412 { | 412 { |
413 // Convert shift number to a pitch shift. The given shift number | 413 // Convert shift number to a pitch shift. The given shift number |
414 // is an offset into the template array, which starts with some | 414 // is an offset into the template array, which starts with some |
415 // zeros, followed by the template, then some trailing zeros. | 415 // zeros, followed by the template, then some trailing zeros. |
416 // | 416 // |
1033 Silvet::emitNote(int start, int end, int note, int shiftCount, | 1033 Silvet::emitNote(int start, int end, int note, int shiftCount, |
1034 FeatureList ¬eFeatures) | 1034 FeatureList ¬eFeatures) |
1035 { | 1035 { |
1036 int partStart = start; | 1036 int partStart = start; |
1037 int partShift = 0; | 1037 int partShift = 0; |
1038 int partVelocity = 0; | 1038 double partStrength = 0; |
1039 | 1039 |
1040 int partThreshold = floor(0.05 * m_colsPerSec); | 1040 int partThreshold = floor(0.05 * m_colsPerSec); |
1041 | 1041 |
1042 for (int i = start; i != end; ++i) { | 1042 for (int i = start; i != end; ++i) { |
1043 | 1043 |
1061 noteFeatures.push_back(makeNoteFeature(partStart, | 1061 noteFeatures.push_back(makeNoteFeature(partStart, |
1062 i, | 1062 i, |
1063 note, | 1063 note, |
1064 partShift, | 1064 partShift, |
1065 shiftCount, | 1065 shiftCount, |
1066 partVelocity)); | 1066 partStrength)); |
1067 partStart = i; | 1067 partStart = i; |
1068 partShift = shift; | 1068 partShift = shift; |
1069 partVelocity = 0; | 1069 partStrength = 0; |
1070 } | 1070 } |
1071 } | 1071 } |
1072 | 1072 |
1073 int v; | 1073 if (strength > partStrength) { |
1074 if (m_mode == LiveMode) { | 1074 partStrength = strength; |
1075 v = round(strength * 20); | |
1076 } else { | |
1077 v = round(strength * 2); | |
1078 } | |
1079 if (v > partVelocity) { | |
1080 partVelocity = v; | |
1081 } | 1075 } |
1082 } | 1076 } |
1083 | 1077 |
1084 if (end >= partStart + partThreshold) { | 1078 if (end >= partStart + partThreshold) { |
1085 noteFeatures.push_back(makeNoteFeature(partStart, | 1079 noteFeatures.push_back(makeNoteFeature(partStart, |
1086 end, | 1080 end, |
1087 note, | 1081 note, |
1088 partShift, | 1082 partShift, |
1089 shiftCount, | 1083 shiftCount, |
1090 partVelocity)); | 1084 partStrength)); |
1091 } | 1085 } |
1092 } | 1086 } |
1093 | 1087 |
1094 void | 1088 void |
1095 Silvet::emitOnset(int start, int note, int shiftCount, | 1089 Silvet::emitOnset(int start, int note, int shiftCount, |
1096 FeatureList &onsetFeatures) | 1090 FeatureList &onsetFeatures) |
1097 { | 1091 { |
1098 int len = int(m_pianoRoll.size()); | 1092 int len = int(m_pianoRoll.size()); |
1099 int velocity = 0; | 1093 |
1094 double onsetStrength = 0; | |
1100 | 1095 |
1101 int shift = 0; | 1096 int shift = 0; |
1102 if (shiftCount > 1) { | 1097 if (shiftCount > 1) { |
1103 shift = m_pianoRollShifts[start][note]; | 1098 shift = m_pianoRollShifts[start][note]; |
1104 } | 1099 } |
1105 | 1100 |
1106 for (int i = start; i < len; ++i) { | 1101 for (int i = start; i < len; ++i) { |
1107 | |
1108 double strength = m_pianoRoll[i][note]; | 1102 double strength = m_pianoRoll[i][note]; |
1109 | 1103 if (strength > onsetStrength) { |
1110 int v; | 1104 onsetStrength = strength; |
1111 if (m_mode == LiveMode) { | |
1112 v = round(strength * 20); | |
1113 } else { | |
1114 v = round(strength * 2); | |
1115 } | |
1116 if (v > velocity) { | |
1117 velocity = v; | |
1118 } | 1105 } |
1119 } | 1106 } |
1120 | 1107 |
1121 onsetFeatures.push_back(makeOnsetFeature(start, | 1108 onsetFeatures.push_back(makeOnsetFeature(start, |
1122 note, | 1109 note, |
1123 shift, | 1110 shift, |
1124 shiftCount, | 1111 shiftCount, |
1125 velocity)); | 1112 onsetStrength)); |
1126 } | 1113 } |
1127 | 1114 |
1128 RealTime | 1115 RealTime |
1129 Silvet::getColumnTimestamp(int column) | 1116 Silvet::getColumnTimestamp(int column) |
1130 { | 1117 { |
1139 Silvet::makeNoteFeature(int start, | 1126 Silvet::makeNoteFeature(int start, |
1140 int end, | 1127 int end, |
1141 int note, | 1128 int note, |
1142 int shift, | 1129 int shift, |
1143 int shiftCount, | 1130 int shiftCount, |
1144 int velocity) | 1131 double strength) |
1145 { | 1132 { |
1146 Feature f; | 1133 Feature f; |
1147 | 1134 |
1148 f.hasTimestamp = true; | 1135 f.hasTimestamp = true; |
1149 f.timestamp = getColumnTimestamp(start); | 1136 f.timestamp = getColumnTimestamp(start); |
1150 | 1137 |
1151 f.hasDuration = true; | 1138 f.hasDuration = true; |
1152 f.duration = getColumnTimestamp(end) - f.timestamp; | 1139 f.duration = getColumnTimestamp(end) - f.timestamp; |
1153 | 1140 |
1154 f.values.clear(); | 1141 f.values.clear(); |
1155 | 1142 f.values.push_back(getNoteFrequency(note, shift, shiftCount)); |
1156 f.values.push_back | 1143 f.values.push_back(getVelocityFor(strength, start)); |
1157 (noteFrequency(note, shift, shiftCount)); | 1144 |
1158 | 1145 f.label = getNoteName(note, shift, shiftCount); |
1159 float inputGain = getInputGainAt(f.timestamp); | |
1160 // cerr << "adjusting velocity from " << velocity << " to " << round(velocity/inputGain) << endl; | |
1161 velocity = round(velocity / inputGain); | |
1162 if (velocity > 127) velocity = 127; | |
1163 if (velocity < 1) velocity = 1; | |
1164 f.values.push_back(velocity); | |
1165 | |
1166 f.label = noteName(note, shift, shiftCount); | |
1167 | 1146 |
1168 return f; | 1147 return f; |
1169 } | 1148 } |
1170 | 1149 |
1171 Silvet::Feature | 1150 Silvet::Feature |
1172 Silvet::makeOnsetFeature(int start, | 1151 Silvet::makeOnsetFeature(int start, |
1173 int note, | 1152 int note, |
1174 int shift, | 1153 int shift, |
1175 int shiftCount, | 1154 int shiftCount, |
1176 int velocity) | 1155 double strength) |
1177 { | 1156 { |
1178 Feature f; | 1157 Feature f; |
1179 | 1158 |
1180 f.hasTimestamp = true; | 1159 f.hasTimestamp = true; |
1181 f.timestamp = getColumnTimestamp(start); | 1160 f.timestamp = getColumnTimestamp(start); |
1182 | 1161 |
1183 f.hasDuration = false; | 1162 f.hasDuration = false; |
1184 | 1163 |
1185 f.values.clear(); | 1164 f.values.clear(); |
1186 | 1165 f.values.push_back(getNoteFrequency(note, shift, shiftCount)); |
1187 f.values.push_back | 1166 f.values.push_back(getVelocityFor(strength, start)); |
1188 (noteFrequency(note, shift, shiftCount)); | 1167 |
1189 | 1168 f.label = getNoteName(note, shift, shiftCount); |
1190 float inputGain = getInputGainAt(f.timestamp); | |
1191 velocity = round(velocity / inputGain); | |
1192 if (velocity > 127) velocity = 127; | |
1193 if (velocity < 1) velocity = 1; | |
1194 f.values.push_back(velocity); | |
1195 | |
1196 f.label = noteName(note, shift, shiftCount); | |
1197 | 1169 |
1198 return f; | 1170 return f; |
1171 } | |
1172 | |
1173 int | |
1174 Silvet::getVelocityFor(double strength, int column) | |
1175 { | |
1176 RealTime rt = getColumnTimestamp(column + 1); | |
1177 | |
1178 float inputGain = getInputGainAt(rt); | |
1179 | |
1180 double scale = 2.0; | |
1181 if (m_mode == LiveMode) scale = 20.0; | |
1182 | |
1183 double velocity = round((strength * scale) / inputGain); | |
1184 | |
1185 if (velocity > 127.0) velocity = 127.0; | |
1186 if (velocity < 1.0) velocity = 1.0; // assume surpassed 0 threshold already | |
1187 | |
1188 return int(velocity); | |
1199 } | 1189 } |
1200 | 1190 |
1201 float | 1191 float |
1202 Silvet::getInputGainAt(RealTime t) | 1192 Silvet::getInputGainAt(RealTime t) |
1203 { | 1193 { |