Mercurial > hg > silvet
comparison src/Silvet.cpp @ 343:460cabb27bf7
Make the onset/offset output consistent with the notes output in terms of restarting notes when a shift changes
author | Chris Cannam |
---|---|
date | Wed, 12 Aug 2015 14:50:30 +0100 |
parents | 705d807ca2ca |
children | c9a0015413e2 |
comparison
equal
deleted
inserted
replaced
342:ad45b18427e0 | 343:460cabb27bf7 |
---|---|
1081 } | 1081 } |
1082 | 1082 |
1083 if (active.find(note) == active.end()) { | 1083 if (active.find(note) == active.end()) { |
1084 // the note was playing but just ended | 1084 // the note was playing but just ended |
1085 m_current.erase(note); | 1085 m_current.erase(note); |
1086 emitNote(start, end, note, noteFeatures); | 1086 emitNoteAndOffset(start, end, note, noteFeatures, onOffsetFeatures); |
1087 emitOffset(start, end, note, onOffsetFeatures); | |
1088 } else { // still playing | 1087 } else { // still playing |
1089 // repeated note detection: if level is greater than this | 1088 // repeated note detection: if level is greater than this |
1090 // multiple of its previous value, then we end the note and | 1089 // multiple of its previous value, then we end the note and |
1091 // restart it with the same pitch | 1090 // restart it with the same pitch |
1092 double restartFactor = 1.5; | 1091 double restartFactor = 1.5; |
1093 if (duration >= durationThreshold * 2 && | 1092 if (duration >= durationThreshold * 2 && |
1094 (active.find(note)->second > | 1093 (active.find(note)->second > |
1095 restartFactor * m_pianoRoll[width-1][note])) { | 1094 restartFactor * m_pianoRoll[width-1][note])) { |
1096 m_current.erase(note); | 1095 m_current.erase(note); |
1097 emitNote(start, end-1, note, noteFeatures); | 1096 emitNoteAndOffset(start, end-1, note, noteFeatures, onOffsetFeatures); |
1098 emitOffset(start, end-1, note, onOffsetFeatures); | |
1099 // and remove this so that we start counting the new | 1097 // and remove this so that we start counting the new |
1100 // note's duration from the current position | 1098 // note's duration from the current position |
1101 m_pianoRoll[width-1].erase(note); | 1099 m_pianoRoll[width-1].erase(note); |
1102 } | 1100 } |
1103 } | 1101 } |
1107 | 1105 |
1108 return { noteFeatures, onsetFeatures, onOffsetFeatures }; | 1106 return { noteFeatures, onsetFeatures, onOffsetFeatures }; |
1109 } | 1107 } |
1110 | 1108 |
1111 void | 1109 void |
1112 Silvet::emitNote(int start, int end, int note, FeatureList ¬eFeatures) | 1110 Silvet::emitNoteAndOffset(int start, int end, int note, |
1113 { | 1111 FeatureList ¬eFeatures, |
1112 FeatureList &onOffsetFeatures) | |
1113 { | |
1114 // Emit the complete note-event feature, and its offset. We have | |
1115 // already emitted the note onset when it started -- that process | |
1116 // is separated out in order to get a faster response during live | |
1117 // tracking. However, if the note shift changes within the note | |
1118 // (which can happen only if we have fine-tuning switched on), we | |
1119 // emit an offset and then a new onset with the new shift. | |
1120 | |
1114 int partStart = start; | 1121 int partStart = start; |
1115 int partShift = 0; | 1122 int partShift = 0; |
1116 double partStrength = 0; | 1123 double partStrength = 0; |
1117 | 1124 |
1125 // NB this *must* be less than durationThreshold above | |
1118 int partThreshold = floor(0.05 * m_colsPerSec); | 1126 int partThreshold = floor(0.05 * m_colsPerSec); |
1119 | 1127 |
1120 for (int i = start; i != end; ++i) { | 1128 for (int i = start; i != end; ++i) { |
1121 | 1129 |
1122 double strength = m_pianoRoll[i][note]; | 1130 double strength = m_pianoRoll[i][note]; |
1130 if (i == partStart) { | 1138 if (i == partStart) { |
1131 partShift = shift; | 1139 partShift = shift; |
1132 } | 1140 } |
1133 | 1141 |
1134 if (i > partStart + partThreshold && shift != partShift) { | 1142 if (i > partStart + partThreshold && shift != partShift) { |
1135 | |
1136 // cerr << "i = " << i << ", partStart = " << partStart << ", shift = " << shift << ", partShift = " << partShift << endl; | |
1137 | 1143 |
1138 // pitch has changed, emit an intermediate note | 1144 // pitch has changed, emit an intermediate note |
1139 noteFeatures.push_back(makeNoteFeature(partStart, | 1145 noteFeatures.push_back(makeNoteFeature(partStart, |
1140 i, | 1146 i, |
1141 note, | 1147 note, |
1142 partShift, | 1148 partShift, |
1143 partStrength)); | 1149 partStrength)); |
1150 | |
1151 onOffsetFeatures.push_back(makeOffsetFeature(i, | |
1152 note, | |
1153 partShift)); | |
1154 | |
1144 partStart = i; | 1155 partStart = i; |
1145 partShift = shift; | 1156 partShift = shift; |
1157 | |
1158 onOffsetFeatures.push_back(makeOnsetFeature(i, | |
1159 note, | |
1160 partShift, | |
1161 partStrength)); | |
1162 | |
1146 partStrength = 0; | 1163 partStrength = 0; |
1147 } | 1164 } |
1148 } | 1165 } |
1149 | 1166 |
1150 if (strength > partStrength) { | 1167 if (strength > partStrength) { |
1151 partStrength = strength; | 1168 partStrength = strength; |
1152 } | 1169 } |
1153 } | 1170 } |
1154 | 1171 |
1155 if (end >= partStart + partThreshold) { | 1172 if (end >= partStart + partThreshold) { |
1173 | |
1156 noteFeatures.push_back(makeNoteFeature(partStart, | 1174 noteFeatures.push_back(makeNoteFeature(partStart, |
1157 end, | 1175 end, |
1158 note, | 1176 note, |
1159 partShift, | 1177 partShift, |
1160 partStrength)); | 1178 partStrength)); |
1179 | |
1180 onOffsetFeatures.push_back(makeOffsetFeature(end, | |
1181 note, | |
1182 partShift)); | |
1161 } | 1183 } |
1162 } | 1184 } |
1163 | 1185 |
1164 void | 1186 void |
1165 Silvet::emitOnset(int start, int note, FeatureList &onOffsetFeatures) | 1187 Silvet::emitOnset(int start, int note, FeatureList &onOffsetFeatures) |
1184 | 1206 |
1185 onOffsetFeatures.push_back(makeOnsetFeature(start, | 1207 onOffsetFeatures.push_back(makeOnsetFeature(start, |
1186 note, | 1208 note, |
1187 shift, | 1209 shift, |
1188 onsetStrength)); | 1210 onsetStrength)); |
1189 } | |
1190 | |
1191 void | |
1192 Silvet::emitOffset(int start, int end, int note, FeatureList &onOffsetFeatures) | |
1193 { | |
1194 int shift = 0; | |
1195 if (getShiftCount() > 1) { | |
1196 shift = m_pianoRollShifts[start][note]; | |
1197 } | |
1198 | |
1199 onOffsetFeatures.push_back(makeOffsetFeature(end, | |
1200 note, | |
1201 shift)); | |
1202 } | 1211 } |
1203 | 1212 |
1204 RealTime | 1213 RealTime |
1205 Silvet::getColumnTimestamp(int column) | 1214 Silvet::getColumnTimestamp(int column) |
1206 { | 1215 { |