summaryrefslogtreecommitdiffstats
path: root/src/djinterop/performance_data.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/djinterop/performance_data.cpp')
-rw-r--r--src/djinterop/performance_data.cpp88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/djinterop/performance_data.cpp b/src/djinterop/performance_data.cpp
new file mode 100644
index 0000000..6656919
--- /dev/null
+++ b/src/djinterop/performance_data.cpp
@@ -0,0 +1,88 @@
+/*
+ This file is part of libdjinterop.
+
+ libdjinterop is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ libdjinterop is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libdjinterop. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <algorithm>
+#include <cmath>
+
+#include <djinterop/djinterop.hpp>
+
+namespace djinterop
+{
+namespace enginelibrary
+{
+std::vector<beatgrid_marker> normalize_beatgrid(
+ std::vector<beatgrid_marker> beatgrid, int64_t sample_count)
+{
+ if (beatgrid.empty())
+ {
+ return beatgrid; // Named RVO
+ }
+
+ {
+ auto last_marker_iter = std::find_if(
+ beatgrid.begin(), beatgrid.end(),
+ [sample_count](const beatgrid_marker &marker) {
+ return marker.sample_offset > sample_count;
+ });
+ if (last_marker_iter != beatgrid.end())
+ {
+ beatgrid.erase(last_marker_iter + 1, beatgrid.end());
+ }
+ }
+
+ {
+ auto after_first_marker_iter = std::find_if(
+ beatgrid.begin(), beatgrid.end(),
+ [](const beatgrid_marker &marker) {
+ return marker.sample_offset > 0;
+ });
+ if (after_first_marker_iter != beatgrid.begin())
+ {
+ beatgrid.erase(beatgrid.begin(), after_first_marker_iter - 1);
+ }
+ }
+
+ if (beatgrid.size() < 2)
+ {
+ throw std::invalid_argument{
+ "Attempted to normalize a misplaced beadgrid"};
+ }
+
+ {
+ double samples_per_beat =
+ (beatgrid[1].sample_offset - beatgrid[0].sample_offset) /
+ (beatgrid[1].index - beatgrid[0].index);
+ beatgrid[0].sample_offset -= (4 + beatgrid[0].index) * samples_per_beat;
+ beatgrid[0].index = -4;
+ }
+
+ {
+ int32_t last = static_cast<int32_t>(beatgrid.size() - 1);
+ double samples_per_beat =
+ (beatgrid[last].sample_offset - beatgrid[last - 1].sample_offset) /
+ (beatgrid[last].index - beatgrid[last - 1].index);
+ int32_t index_adjustment = static_cast<int32_t>(std::ceil(
+ (sample_count - beatgrid[last].sample_offset) / samples_per_beat));
+ beatgrid[last].sample_offset += index_adjustment * samples_per_beat;
+ beatgrid[last].index += index_adjustment;
+ }
+
+ return beatgrid; // Named RVO
+}
+
+} // namespace enginelibrary
+} // namespace djinterop