diff options
author | Jan Holthuis <jan.holthuis@ruhr-uni-bochum.de> | 2021-03-18 21:08:50 +0100 |
---|---|---|
committer | Jan Holthuis <jan.holthuis@ruhr-uni-bochum.de> | 2021-03-18 21:17:59 +0100 |
commit | 7f0718585a1e491d42eea30da5163ba5672f890c (patch) | |
tree | d64b92d6d989c59763ff015bdfc80610b57cca23 | |
parent | 3b8507081084a39f026f1fd38f61a7d6efbdc94e (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.cpp | 17 | ||||
-rw-r--r-- | src/track/serato/beatgrid.cpp | 17 | ||||
-rw-r--r-- | src/track/serato/beatgrid.h | 6 | ||||
-rw-r--r-- | src/track/serato/tags.h | 5 | ||||
-rw-r--r-- | src/track/track.cpp | 15 |
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); } } |