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 &noteFeatures) 1034 FeatureList &noteFeatures)
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 {