| 243 | } |
| 244 | |
| 245 | void Notes::_addPitchBends(std::vector<Event>& inOutEvents, |
| 246 | const std::vector<std::vector<float>>& inContoursPG, |
| 247 | int inNumBinsTolerance) |
| 248 | { |
| 249 | for (auto& event: inOutEvents) { |
| 250 | // midi_pitch_to_contour_bin |
| 251 | int note_idx = |
| 252 | CONTOURS_BINS_PER_SEMITONE |
| 253 | * (event.pitch - 69 + 12 * static_cast<int>(std::round(std::log2(440.0f / ANNOTATIONS_BASE_FREQUENCY)))); |
| 254 | |
| 255 | static constexpr int N_FREQ_BINS_CONTOURS = NUM_FREQ_OUT * CONTOURS_BINS_PER_SEMITONE; |
| 256 | int note_start_idx = std::max(note_idx - inNumBinsTolerance, 0); |
| 257 | int note_end_idx = std::min(N_FREQ_BINS_CONTOURS, note_idx + inNumBinsTolerance + 1); |
| 258 | |
| 259 | const auto gauss_start = static_cast<float>(std::max(0, inNumBinsTolerance - note_idx)); |
| 260 | const auto pb_shift = inNumBinsTolerance - std::max(0, inNumBinsTolerance - note_idx); |
| 261 | |
| 262 | for (int i = event.startFrame; i < event.endFrame; i++) { |
| 263 | int bend = 0; |
| 264 | float max = 0; |
| 265 | for (int j = note_start_idx; j < note_end_idx; j++) { |
| 266 | int k = j - note_start_idx; |
| 267 | float x = gauss_start + static_cast<float>(k); |
| 268 | float n = x - static_cast<float>(inNumBinsTolerance); |
| 269 | |
| 270 | static constexpr float std = 5.0f; |
| 271 | |
| 272 | // Gaussian |
| 273 | float w = std::exp(-(n * n) / (2.0f * std * std)) * inContoursPG[i][j]; |
| 274 | |
| 275 | if (w > max) { |
| 276 | bend = k; |
| 277 | max = w; |
| 278 | } |
| 279 | } |
| 280 | event.bends.emplace_back(bend - pb_shift); |
| 281 | } |
| 282 | } |
| 283 | } |