1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#include <QtDebug>
#include <QStringList>
#include "track/beatgrid.h"
#include "track/beatmap.h"
#include "track/beatfactory.h"
#include "track/beatutils.h"
namespace {
const QString kRoundingVersion = QStringLiteral("V4");
} // namespace
mixxx::BeatsPointer BeatFactory::loadBeatsFromByteArray(
mixxx::audio::SampleRate sampleRate,
const QString& beatsVersion,
const QString& beatsSubVersion,
const QByteArray& beatsSerialized) {
if (beatsVersion == BEAT_GRID_1_VERSION ||
beatsVersion == BEAT_GRID_2_VERSION) {
auto pGrid = mixxx::BeatGrid::makeBeatGrid(sampleRate, beatsSubVersion, beatsSerialized);
qDebug() << "Successfully deserialized BeatGrid";
return pGrid;
} else if (beatsVersion == BEAT_MAP_VERSION) {
auto pMap = mixxx::BeatMap::makeBeatMap(sampleRate, beatsSubVersion, beatsSerialized);
qDebug() << "Successfully deserialized BeatMap";
return pMap;
}
qDebug() << "BeatFactory::loadBeatsFromByteArray could not parse serialized beats.";
return mixxx::BeatsPointer();
}
mixxx::BeatsPointer BeatFactory::makeBeatGrid(
mixxx::audio::SampleRate sampleRate,
mixxx::Bpm bpm,
mixxx::audio::FramePos firstBeatFramePos) {
DEBUG_ASSERT(firstBeatFramePos.isValid());
DEBUG_ASSERT(!firstBeatFramePos.isFractional());
return mixxx::BeatGrid::makeBeatGrid(sampleRate, QString(), bpm, firstBeatFramePos);
}
// static
QString BeatFactory::getPreferredVersion(bool fixedTempo) {
if (fixedTempo) {
return BEAT_GRID_2_VERSION;
}
return BEAT_MAP_VERSION;
}
QString BeatFactory::getPreferredSubVersion(
const QHash<QString, QString>& extraVersionInfo) {
const char* kSubVersionKeyValueSeparator = "=";
const char* kSubVersionFragmentSeparator = "|";
QStringList fragments;
QHashIterator<QString, QString> it(extraVersionInfo);
while (it.hasNext()) {
it.next();
if (it.key().contains(kSubVersionKeyValueSeparator) ||
it.key().contains(kSubVersionFragmentSeparator) ||
it.value().contains(kSubVersionKeyValueSeparator) ||
it.value().contains(kSubVersionFragmentSeparator)) {
qDebug() << "ERROR: Your analyzer key/value contains invalid "
"characters:"
<< it.key() << ":" << it.value() << "Skipping.";
continue;
}
fragments << QString("%1%2%3").arg(
it.key(), kSubVersionKeyValueSeparator, it.value());
}
fragments << QString("rounding%1%2")
.arg(kSubVersionKeyValueSeparator, kRoundingVersion);
std::sort(fragments.begin(), fragments.end());
return (fragments.size() > 0) ? fragments.join(kSubVersionFragmentSeparator)
: "";
}
mixxx::BeatsPointer BeatFactory::makePreferredBeats(
const QVector<mixxx::audio::FramePos>& beats,
const QHash<QString, QString>& extraVersionInfo,
bool fixedTempo,
mixxx::audio::SampleRate sampleRate) {
const QString version = getPreferredVersion(fixedTempo);
const QString subVersion = getPreferredSubVersion(extraVersionInfo);
#ifdef DEBUG_PRINT_BEATS
for (mixxx::audio::FramePos beat : beats) {
qDebug().noquote() << QString::number(beat.value(), 'g', 8);
}
#endif
QVector<BeatUtils::ConstRegion> constantRegions =
BeatUtils::retrieveConstRegions(beats, sampleRate);
#ifdef DEBUG_PRINT_BEATS
for (auto& region : constantRegions) {
qDebug().noquote() << QString::number(region.firstBeat.value(), 'g', 8)
<< QString::number(region.beatLength, 'g', 8);
}
#endif
if (version == BEAT_GRID_2_VERSION) {
mixxx::audio::FramePos firstBeat = mixxx::audio::kStartFramePos;
const mixxx::Bpm constBPM = BeatUtils::makeConstBpm(
constantRegions, sampleRate, &firstBeat);
firstBeat = BeatUtils::adjustPhase(firstBeat, constBPM, sampleRate, beats);
auto pGrid = mixxx::BeatGrid::makeBeatGrid(
sampleRate, subVersion, constBPM, firstBeat);
return pGrid;
} else if (version == BEAT_MAP_VERSION) {
QVector<mixxx::audio::FramePos> ironedBeats = BeatUtils::getBeats(constantRegions);
auto pBeatMap = mixxx::BeatMap::makeBeatMap(sampleRate, subVersion, ironedBeats);
return pBeatMap;
} else {
qDebug() << "ERROR: Could not determine what type of beatgrid to create.";
return mixxx::BeatsPointer();
}
}
|