summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Holthuis <jan.holthuis@ruhr-uni-bochum.de>2021-03-18 21:08:50 +0100
committerJan Holthuis <jan.holthuis@ruhr-uni-bochum.de>2021-03-18 21:17:59 +0100
commit7f0718585a1e491d42eea30da5163ba5672f890c (patch)
treed64b92d6d989c59763ff015bdfc80610b57cca23
parent3b8507081084a39f026f1fd38f61a7d6efbdc94e (diff)
SeratoTags: Use SignalInfo/Duration instead of StreamInfo
For FLAC files, the StreamInfo might be invalid because the bitrate is invalid, because it is read by TagLib, not the sound source. We don't actually need the Bitrate for exporting Serato Tags, but the signal info alone does not suffice either, because we also need the duration to serialize the beatgrid. Hence, instead of using the StreamInfo wrapper (which also has the irrelevant Bitrate member) we use SignalInfo and Duration directly.
-rw-r--r--src/test/seratobeatgridtest.cpp17
-rw-r--r--src/track/serato/beatgrid.cpp17
-rw-r--r--src/track/serato/beatgrid.h6
-rw-r--r--src/track/serato/tags.h5
-rw-r--r--src/track/track.cpp15
5 files changed, 32 insertions, 28 deletions
diff --git a/src/test/seratobeatgridtest.cpp b/src/test/seratobeatgridtest.cpp
index 2c36239a94..105d02e7c2 100644
--- a/src/test/seratobeatgridtest.cpp
+++ b/src/test/seratobeatgridtest.cpp
@@ -109,14 +109,12 @@ TEST_F(SeratoBeatGridTest, SerializeBeatgrid) {
const auto sampleRate = mixxx::audio::SampleRate(44100);
EXPECT_EQ(sampleRate.isValid(), true);
const auto pBeats = mixxx::BeatGrid::makeBeatGrid(sampleRate, QString("Test"), bpm, 0);
- const auto streamInfo = mixxx::audio::StreamInfo(
- mixxx::audio::SignalInfo(mixxx::audio::ChannelCount(2), sampleRate),
- mixxx::audio::Bitrate(320),
- mixxx::Duration::fromSeconds<int>(300));
+ const auto signalInfo = mixxx::audio::SignalInfo(mixxx::audio::ChannelCount(2), sampleRate);
+ const auto duration = mixxx::Duration::fromSeconds<int>(300);
// Serialize that beatgrid into Serato BeatGrid data and check if it's correct
mixxx::SeratoBeatGrid seratoBeatGrid;
- seratoBeatGrid.setBeats(pBeats, streamInfo, 0);
+ seratoBeatGrid.setBeats(pBeats, signalInfo, duration, 0);
EXPECT_EQ(seratoBeatGrid.nonTerminalMarkers().size(), 0);
EXPECT_NE(seratoBeatGrid.terminalMarker(), nullptr);
EXPECT_FLOAT_EQ(seratoBeatGrid.terminalMarker()->bpm(), static_cast<float>(bpm));
@@ -127,13 +125,10 @@ TEST_F(SeratoBeatGridTest, SerializeBeatMap) {
constexpr double bpm = 100.0;
const auto sampleRate = mixxx::audio::SampleRate(44100);
const auto signalInfo = mixxx::audio::SignalInfo(mixxx::audio::ChannelCount(2), sampleRate);
+ const auto duration = mixxx::Duration::fromSeconds<int>(300);
const double framesPerMinute = signalInfo.getSampleRate() * 60;
const double framesPerBeat = framesPerMinute / bpm;
- const auto streamInfo = mixxx::audio::StreamInfo(signalInfo,
- mixxx::audio::Bitrate(320),
- mixxx::Duration::fromSeconds<int>(300));
-
QVector<double> beatPositionsFrames;
double beatPositionFrames = 0;
// Add 2 minutes of beats at 100 bpm to the beatgrid
@@ -150,7 +145,7 @@ TEST_F(SeratoBeatGridTest, SerializeBeatMap) {
EXPECT_EQ(pBeats->getBpmAroundPosition(framesPerMinute, 1), bpm);
mixxx::SeratoBeatGrid seratoBeatGrid;
- seratoBeatGrid.setBeats(pBeats, streamInfo, 0);
+ seratoBeatGrid.setBeats(pBeats, signalInfo, duration, 0);
EXPECT_EQ(seratoBeatGrid.nonTerminalMarkers().size(), 0);
EXPECT_NE(seratoBeatGrid.terminalMarker(), nullptr);
EXPECT_FLOAT_EQ(seratoBeatGrid.terminalMarker()->bpm(), static_cast<float>(bpm));
@@ -172,7 +167,7 @@ TEST_F(SeratoBeatGridTest, SerializeBeatMap) {
EXPECT_EQ(pBeats->getBpmAroundPosition(framesPerMinute * 4, 1), bpm / 2);
mixxx::SeratoBeatGrid seratoBeatGrid;
- seratoBeatGrid.setBeats(pBeats, streamInfo, 0);
+ seratoBeatGrid.setBeats(pBeats, signalInfo, duration, 0);
EXPECT_EQ(seratoBeatGrid.nonTerminalMarkers().size(), 2);
EXPECT_NE(seratoBeatGrid.terminalMarker(), nullptr);
EXPECT_FLOAT_EQ(seratoBeatGrid.terminalMarker()->bpm(), static_cast<float>(bpm / 2));
diff --git a/src/track/serato/beatgrid.cpp b/src/track/serato/beatgrid.cpp
index 8885637913..52f529a7ad 100644
--- a/src/track/serato/beatgrid.cpp
+++ b/src/track/serato/beatgrid.cpp
@@ -422,7 +422,8 @@ QByteArray SeratoBeatGrid::dumpBase64Encoded() const {
}
void SeratoBeatGrid::setBeats(BeatsPointer pBeats,
- const audio::StreamInfo& streamInfo,
+ const audio::SignalInfo& signalInfo,
+ const Duration& duration,
double timingOffsetMillis) {
if (!pBeats) {
setTerminalMarker(nullptr);
@@ -436,9 +437,9 @@ void SeratoBeatGrid::setBeats(BeatsPointer pBeats,
// in the track, therefore we calculate the track duration in samples and
// round up. This value might be longer than the actual track, but that's
// okay because we want to make sure we get all beats.
- const SINT trackDurationSamples = streamInfo.getSignalInfo().frames2samples(
- static_cast<SINT>(streamInfo.getSignalInfo().secs2frames(
- std::ceil(streamInfo.getDuration().toDoubleSeconds()))));
+ const SINT trackDurationSamples = signalInfo.frames2samples(
+ static_cast<SINT>(signalInfo.secs2frames(
+ std::ceil(duration.toDoubleSeconds()))));
auto pBeatsIterator = pBeats->findBeats(0, trackDurationSamples);
// This might be null if the track doesn't contain any beats
@@ -457,7 +458,7 @@ void SeratoBeatGrid::setBeats(BeatsPointer pBeats,
while (pBeatsIterator->hasNext()) {
previousBeatPositionFrames = currentBeatPositionFrames;
currentBeatPositionFrames =
- streamInfo.getSignalInfo().samples2framesFractional(
+ signalInfo.samples2framesFractional(
pBeatsIterator->next());
// Calculate the delta between the current beat and the previous beat.
@@ -493,7 +494,7 @@ void SeratoBeatGrid::setBeats(BeatsPointer pBeats,
// last beat, this needs to be a terminal marker entry.
if (pBeatsIterator->hasNext()) {
const double positionSecs =
- streamInfo.getSignalInfo().frames2secsFractional(
+ signalInfo.frames2secsFractional(
currentBeatPositionFrames) -
timingOffsetSecs;
nonTerminalMarkers.append(
@@ -532,11 +533,11 @@ void SeratoBeatGrid::setBeats(BeatsPointer pBeats,
// Finally, create the terminal marker.
const double positionSecs =
- streamInfo.getSignalInfo().frames2secsFractional(
+ signalInfo.frames2secsFractional(
currentBeatPositionFrames) -
timingOffsetSecs;
const double bpm = pBeats->getBpmAroundPosition(
- streamInfo.getSignalInfo().frames2samples(
+ signalInfo.frames2samples(
static_cast<SINT>(currentBeatPositionFrames)),
1);
diff --git a/src/track/serato/beatgrid.h b/src/track/serato/beatgrid.h
index cc150ede03..b4d7d96a66 100644
--- a/src/track/serato/beatgrid.h
+++ b/src/track/serato/beatgrid.h
@@ -6,11 +6,12 @@
#include <QList>
#include <memory>
-#include "audio/streaminfo.h"
+#include "audio/signalinfo.h"
#include "track/beats.h"
#include "track/cueinfo.h"
#include "track/taglib/trackmetadata_file.h"
#include "util/assert.h"
+#include "util/duration.h"
#include "util/types.h"
namespace mixxx {
@@ -129,7 +130,8 @@ class SeratoBeatGrid final {
}
void setBeats(BeatsPointer pBeats,
- const audio::StreamInfo& streamInfo,
+ const audio::SignalInfo& signalInfo,
+ const Duration& duration,
double timingOffsetMillis);
quint8 footer() const {
diff --git a/src/track/serato/tags.h b/src/track/serato/tags.h
index 8a31bb1222..5aa480d766 100644
--- a/src/track/serato/tags.h
+++ b/src/track/serato/tags.h
@@ -93,9 +93,10 @@ class SeratoTags final {
void setCueInfos(const QList<CueInfo>& cueInfos, double timingOffset = 0);
void setBeats(BeatsPointer pBeats,
- const audio::StreamInfo& streamInfo,
+ const audio::SignalInfo& signalInfo,
+ const Duration& duration,
double timingOffset) {
- m_seratoBeatGrid.setBeats(pBeats, streamInfo, timingOffset);
+ m_seratoBeatGrid.setBeats(pBeats, signalInfo, duration, timingOffset);
}
RgbColor::optional_t getTrackColor() const;
diff --git a/src/track/track.cpp b/src/track/track.cpp
index 4cbd28fdbb..0a5ad93f93 100644
--- a/src/track/track.cpp
+++ b/src/track/track.cpp
@@ -1365,10 +1365,12 @@ ExportTrackMetadataResult Track::exportMetadata(
if (pConfig->getValue<bool>(kConfigKeySeratoMetadataExport)) {
const auto streamInfo = m_record.getStreamInfoFromSource();
- VERIFY_OR_DEBUG_ASSERT(streamInfo && streamInfo->isValid()) {
- kLogger.warning()
- << "Cannot write Serato metadata because stream info is not available:"
- << getLocation();
+ VERIFY_OR_DEBUG_ASSERT(streamInfo &&
+ streamInfo->getSignalInfo().isValid() &&
+ streamInfo->getDuration() > mixxx::Duration::empty()) {
+ kLogger.warning() << "Cannot write Serato metadata because signal "
+ "info and/or duration is not available:"
+ << getLocation();
return ExportTrackMetadataResult::Skipped;
}
@@ -1395,7 +1397,10 @@ ExportTrackMetadataResult Track::exportMetadata(
getLocation(), streamInfo->getSignalInfo());
seratoTags->setCueInfos(cueInfos, timingOffset);
- seratoTags->setBeats(m_pBeats, *streamInfo, timingOffset);
+ seratoTags->setBeats(m_pBeats,
+ streamInfo->getSignalInfo(),
+ streamInfo->getDuration(),
+ timingOffset);
}
}