Skip to content

Commit

Permalink
Merge pull request #970 from uklotzde/duration_real
Browse files Browse the repository at this point in the history
Enhance precision of track duration
  • Loading branch information
daschuer committed Jun 25, 2016
2 parents 32b223b + 1070a48 commit 89612ff
Show file tree
Hide file tree
Showing 27 changed files with 232 additions and 163 deletions.
1 change: 1 addition & 0 deletions build/depends.py
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,7 @@ def sources(self, build):
"util/statsmanager.cpp",
"util/stat.cpp",
"util/statmodel.cpp",
"util/duration.cpp",
"util/time.cpp",
"util/timer.cpp",
"util/performancetimer.cpp",
Expand Down
4 changes: 2 additions & 2 deletions res/schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ METADATA
genre varchar(32), tracknumber varchar(3),
location varchar(512) REFERENCES track_locations(location),
comment varchar(20), url varchar(256),
duration integer,
duration float,
bitrate integer, samplerate integer,
cuepoint integer, bpm float,
wavesummaryhex blob,
Expand Down Expand Up @@ -113,7 +113,7 @@ METADATA
location integer REFERENCES track_locations(location),
comment varchar(256),
url varchar(256),
duration integer,
duration float,
bitrate integer,
samplerate integer,
cuepoint integer,
Expand Down
26 changes: 12 additions & 14 deletions src/library/autodj/autodjprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#define kConfigKey "[Auto DJ]"
const char* kTransitionPreferenceName = "Transition";
const int kTransitionPreferenceDefault = 10;
const double kTransitionPreferenceDefault = 10.0;

static const bool sDebug = false;

Expand Down Expand Up @@ -73,7 +73,7 @@ AutoDJProcessor::AutoDJProcessor(QObject* pParent,
m_pPlayerManager(pPlayerManager),
m_pAutoDJTableModel(NULL),
m_eState(ADJ_DISABLED),
m_iTransitionTime(kTransitionPreferenceDefault),
m_transitionTime(kTransitionPreferenceDefault),
m_nextTransitionTime(kTransitionPreferenceDefault) {
m_pAutoDJTableModel = new PlaylistTableModel(this, pTrackCollection,
"mixxx.db.model.autodj");
Expand Down Expand Up @@ -123,8 +123,8 @@ AutoDJProcessor::AutoDJProcessor(QObject* pParent,
QString str_autoDjTransition = m_pConfig->getValueString(
ConfigKey(kConfigKey, kTransitionPreferenceName));
if (!str_autoDjTransition.isEmpty()) {
m_iTransitionTime = str_autoDjTransition.toInt();
m_nextTransitionTime = m_iTransitionTime;
m_transitionTime = str_autoDjTransition.toDouble();
m_nextTransitionTime = m_transitionTime;
}
}

Expand Down Expand Up @@ -707,37 +707,35 @@ void AutoDJProcessor::calculateTransition(DeckAttributes* pFromDeck,
if (fromTrack) {
// TODO(rryan): Duration is super inaccurate! We should be using
// track_samples / track_samplerate instead.
int fromTrackDuration = fromTrack->getDuration();
double fromTrackDuration = fromTrack->getDuration();
qDebug() << fromTrack->getLocation()
<< "fromTrackDuration =" << fromTrackDuration;

// The track might be shorter than the transition period. Use a
// sensible cap.
m_nextTransitionTime = math_min(m_iTransitionTime,
m_nextTransitionTime = math_min(m_transitionTime,
fromTrackDuration / 2);

if (pToDeck) {
TrackPointer toTrack = pToDeck->getLoadedTrack();
if (toTrack) {
// TODO(rryan): Duration is super inaccurate! We should be using
// track_samples / track_samplerate instead.
int toTrackDuration = toTrack->getDuration();
double toTrackDuration = toTrack->getDuration();
qDebug() << toTrack->getLocation()
<< "toTrackDuration = " << toTrackDuration;
m_nextTransitionTime = math_min(m_nextTransitionTime,
toTrackDuration / 2);
}
}

if (fromTrackDuration > 0) {
pFromDeck->fadeDuration =
static_cast<double>(m_nextTransitionTime) /
static_cast<double>(fromTrackDuration);
if (fromTrackDuration > 0.0) {
pFromDeck->fadeDuration = m_nextTransitionTime / fromTrackDuration;
} else {
pFromDeck->fadeDuration = 0;
pFromDeck->fadeDuration = 0.0;
}

if (m_nextTransitionTime > 0) {
if (m_nextTransitionTime > 0.0) {
pFromDeck->posThreshold = 1.0 - pFromDeck->fadeDuration;
} else {
// in case of pause transition
Expand Down Expand Up @@ -826,7 +824,7 @@ void AutoDJProcessor::setTransitionTime(int time) {
// Update the transition time first.
m_pConfig->set(ConfigKey(kConfigKey, kTransitionPreferenceName),
ConfigValue(time));
m_iTransitionTime = time;
m_transitionTime = time;

// Then re-calculate fade thresholds for the decks.
if (m_eState == ADJ_IDLE) {
Expand Down
8 changes: 4 additions & 4 deletions src/library/autodj/autodjprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ class AutoDJProcessor : public QObject {
return m_eState;
}

int getTransitionTime() const {
return m_iTransitionTime;
double getTransitionTime() const {
return m_transitionTime;
}

PlaylistTableModel* getTableModel() const {
Expand Down Expand Up @@ -197,8 +197,8 @@ class AutoDJProcessor : public QObject {
PlaylistTableModel* m_pAutoDJTableModel;

AutoDJState m_eState;
int m_iTransitionTime; // the desired value set by the user
int m_nextTransitionTime; // the tweaked value actually used
double m_transitionTime; // the desired value set by the user
double m_nextTransitionTime; // the tweaked value actually used

QList<DeckAttributes*> m_decks;

Expand Down
6 changes: 3 additions & 3 deletions src/library/autodj/dlgautodj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "library/playlisttablemodel.h"
#include "widget/wtracktableview.h"
#include "util/assert.h"
#include "util/time.h"
#include "util/duration.h"

DlgAutoDJ::DlgAutoDJ(QWidget* parent,
UserSettingsPointer pConfig,
Expand Down Expand Up @@ -200,7 +200,7 @@ void DlgAutoDJ::setTrackTableRowHeight(int rowHeight) {
}

void DlgAutoDJ::updateSelectionInfo() {
int duration = 0;
double duration = 0.0;

QModelIndexList indices = m_pTrackTableView->selectionModel()->selectedRows();

Expand All @@ -214,7 +214,7 @@ void DlgAutoDJ::updateSelectionInfo() {
QString label;

if (!indices.isEmpty()) {
label.append(Time::formatSeconds(duration));
label.append(mixxx::Duration::formatSeconds(duration));
label.append(QString(" (%1)").arg(indices.size()));
labelSelectionInfo->setText(label);
labelSelectionInfo->setEnabled(true);
Expand Down
2 changes: 1 addition & 1 deletion src/library/banshee/bansheeplaylistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ TrackPointer BansheePlaylistModel::getTrack(const QModelIndex& index) const {
if (pTrack && !track_already_in_library) {
pTrack->setArtist(getFieldString(index, CLM_ARTIST));
pTrack->setTitle(getFieldString(index, CLM_TITLE));
pTrack->setDuration(getFieldString(index, CLM_DURATION).toInt());
pTrack->setDuration(getFieldString(index, CLM_DURATION).toDouble());
pTrack->setAlbum(getFieldString(index, CLM_ALBUM));
pTrack->setAlbumArtist(getFieldString(index, CLM_ALBUM_ARTIST));
pTrack->setYear(getFieldString(index, CLM_YEAR));
Expand Down
4 changes: 2 additions & 2 deletions src/library/basesqltablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include "mixer/playerinfo.h"
#include "track/keyutils.h"
#include "track/trackmetadata.h"
#include "util/time.h"
#include "util/duration.h"
#include "util/dnd.h"
#include "util/assert.h"
#include "util/performancetimer.h"
Expand Down Expand Up @@ -615,7 +615,7 @@ QVariant BaseSqlTableModel::data(const QModelIndex& index, int role) const {
if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_DURATION)) {
int duration = value.toInt();
if (duration > 0) {
value = Time::formatSeconds(duration);
value = mixxx::Duration::formatSeconds(duration);
} else {
value = QString();
}
Expand Down
3 changes: 1 addition & 2 deletions src/library/browse/browsethread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "library/browse/browsetablemodel.h"
#include "sources/soundsourceproxy.h"
#include "track/trackmetadata.h"
#include "util/time.h"
#include "util/trace.h"


Expand Down Expand Up @@ -213,7 +212,7 @@ void BrowseThread::populateModel() {
item->setData(item->text(), Qt::UserRole);
row_data.insert(COLUMN_COMMENT, item);

QString duration = Time::formatSeconds(pTrack->getDuration());
QString duration = pTrack->getDurationText(mixxx::Duration::Precision::SECONDS);
item = new QStandardItem(duration);
item->setToolTip(item->text());
item->setData(item->text(), Qt::UserRole);
Expand Down
4 changes: 2 additions & 2 deletions src/library/cratefeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include "treeitem.h"
#include "sources/soundsourceproxy.h"
#include "util/dnd.h"
#include "util/time.h"
#include "util/duration.h"

CrateFeature::CrateFeature(Library* pLibrary,
TrackCollection* pTrackCollection,
Expand Down Expand Up @@ -498,7 +498,7 @@ void CrateFeature::buildCrateList() {
crateListTableModel.index(row, durationColumn)).toInt();
m_crateList.append(qMakePair(id, QString("%1 (%2) %3")
.arg(name, QString::number(count),
Time::formatSeconds(duration))));
mixxx::Duration::formatSeconds(duration))));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/library/dao/trackdao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ bool setTrackUrl(const QSqlRecord& record, const int column,

bool setTrackDuration(const QSqlRecord& record, const int column,
TrackPointer pTrack) {
pTrack->setDuration(record.value(column).toInt());
pTrack->setDuration(record.value(column).toDouble());
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion src/library/dlgtrackinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ void DlgTrackInfo::populateFields(const Track& track) {
txtComment->setPlainText(track.getComment());

// Non-editable fields
txtDuration->setText(track.getDurationText());
txtDuration->setText(track.getDurationText(mixxx::Duration::Precision::SECONDS));
txtLocation->setPlainText(track.getLocation());
txtType->setText(track.getType());
txtBitrate->setText(QString(track.getBitrateText()) + (" ") + tr("kbps"));
Expand Down
4 changes: 2 additions & 2 deletions src/library/playlistfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include "controllers/keyboard/keyboardeventfilter.h"
#include "sources/soundsourceproxy.h"
#include "util/dnd.h"
#include "util/time.h"
#include "util/duration.h"

PlaylistFeature::PlaylistFeature(QObject* parent,
TrackCollection* pTrackCollection,
Expand Down Expand Up @@ -170,7 +170,7 @@ void PlaylistFeature::buildPlaylistList() {
playlistTableModel.index(row, durationColumn)).toInt();
m_playlistList.append(qMakePair(id, QString("%1 (%2) %3")
.arg(name, QString::number(count),
Time::formatSeconds(duration))));
mixxx::Duration::formatSeconds(duration))));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/musicbrainz/tagfetcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ void TagFetcher::fingerprintFound(int index) {

emit(fetchProgress(tr("Identifying track")));
// qDebug() << "start to look up the MBID";
m_AcoustidClient.start(index, fingerprint, ptrack->getDuration());
m_AcoustidClient.start(index, fingerprint, ptrack->getDurationInt());
}

void TagFetcher::mbidFound(int index, const QString& mbid) {
Expand Down
4 changes: 2 additions & 2 deletions src/sources/audiosource.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ class AudioSource: public UrlResource, public AudioSignal {
inline bool hasDuration() const {
return isValid();
}
inline SINT getDuration() const {
inline double getDuration() const {
DEBUG_ASSERT(hasDuration()); // prevents division by zero
return getFrameCount() / getSamplingRate();
return double(getFrameCount()) / double(getSamplingRate());
}

// The bitrate is measured in kbit/s (kbps).
Expand Down
2 changes: 1 addition & 1 deletion src/sources/soundsourcemodplug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Result SoundSourceModPlug::parseTrackMetadataAndCoverArt(
if (nullptr != pModFile) {
pTrackMetadata->setComment(QString(ModPlug::ModPlug_GetMessage(pModFile)));
pTrackMetadata->setTitle(QString(ModPlug::ModPlug_GetName(pModFile)));
pTrackMetadata->setDuration(ModPlug::ModPlug_GetLength(pModFile) / 1000);
pTrackMetadata->setDuration(ModPlug::ModPlug_GetLength(pModFile) / 1000.0);
pTrackMetadata->setBitrate(8); // not really, but fill in something...
ModPlug::ModPlug_Unload(pModFile);
}
Expand Down
5 changes: 3 additions & 2 deletions src/sources/soundsourceopus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ Result SoundSourceOpus::parseTrackMetadataAndCoverArt(
pTrackMetadata->setChannels(op_channel_count(l_ptrOpusFile, -1));
pTrackMetadata->setSampleRate(kSamplingRate);
pTrackMetadata->setBitrate(op_bitrate(l_ptrOpusFile, -1) / 1000);
pTrackMetadata->setDuration(
op_pcm_total(l_ptrOpusFile, -1) / pTrackMetadata->getSampleRate());
// Cast to double is required for duration with sub-second precision
const double dTotalFrames = op_pcm_total(l_ptrOpusFile, -1);
pTrackMetadata->setDuration(dTotalFrames / pTrackMetadata->getSampleRate());

bool hasDate = false;
for (i = 0; i < l_ptrOpusTags->comments; ++i) {
Expand Down
32 changes: 16 additions & 16 deletions src/test/timeutiltest.cpp → src/test/durationutiltest.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#include <gtest/gtest.h>

#include "util/time.h"
#include "util/duration.h"

#include <QtDebug>

namespace {

class TimeUtilTest : public testing::Test {
class DurationUtilTest : public testing::Test {
protected:

TimeUtilTest() {
DurationUtilTest() {
}

virtual void SetUp() {
Expand All @@ -20,13 +20,13 @@ class TimeUtilTest : public testing::Test {

static QString adjustPrecision(
QString withMilliseconds,
Time::Precision precision) {
mixxx::Duration::Precision precision) {
switch (precision) {
case Time::Precision::SECONDS:
case mixxx::Duration::Precision::SECONDS:
{
return withMilliseconds.left(withMilliseconds.length() - 4);
}
case Time::Precision::CENTISECONDS:
case mixxx::Duration::Precision::CENTISECONDS:
{
return withMilliseconds.left(withMilliseconds.length() - 1);
}
Expand All @@ -38,28 +38,28 @@ class TimeUtilTest : public testing::Test {
void formatSeconds(QString expectedMilliseconds, double dSeconds) {
ASSERT_LE(4, expectedMilliseconds.length()); // 3 digits + 1 decimal point
const QString actualSeconds =
Time::formatSeconds(dSeconds, Time::Precision::SECONDS);
mixxx::Duration::formatSeconds(dSeconds, mixxx::Duration::Precision::SECONDS);
const QString expectedSeconds =
adjustPrecision(expectedMilliseconds, Time::Precision::SECONDS);
adjustPrecision(expectedMilliseconds, mixxx::Duration::Precision::SECONDS);
EXPECT_EQ(expectedSeconds, actualSeconds);
const QString expectedCentiseconds =
adjustPrecision(expectedMilliseconds, Time::Precision::CENTISECONDS);
adjustPrecision(expectedMilliseconds, mixxx::Duration::Precision::CENTISECONDS);
const QString actualCentiseconds =
Time::formatSeconds(dSeconds, Time::Precision::CENTISECONDS);
mixxx::Duration::formatSeconds(dSeconds, mixxx::Duration::Precision::CENTISECONDS);
EXPECT_EQ(expectedCentiseconds, actualCentiseconds);
const QString actualMilliseconds =
Time::formatSeconds(dSeconds, Time::Precision::MILLISECONDS);
mixxx::Duration::formatSeconds(dSeconds, mixxx::Duration::Precision::MILLISECONDS);
EXPECT_EQ(actualMilliseconds, actualMilliseconds);
}
};

TEST_F(TimeUtilTest, FormatSecondsNegative) {
EXPECT_EQ("?", Time::formatSeconds(-1, Time::Precision::SECONDS));
EXPECT_EQ("?", Time::formatSeconds(-1, Time::Precision::CENTISECONDS));
EXPECT_EQ("?", Time::formatSeconds(-1, Time::Precision::MILLISECONDS));
TEST_F(DurationUtilTest, FormatSecondsNegative) {
EXPECT_EQ("?", mixxx::Duration::formatSeconds(-1, mixxx::Duration::Precision::SECONDS));
EXPECT_EQ("?", mixxx::Duration::formatSeconds(-1, mixxx::Duration::Precision::CENTISECONDS));
EXPECT_EQ("?", mixxx::Duration::formatSeconds(-1, mixxx::Duration::Precision::MILLISECONDS));
}

TEST_F(TimeUtilTest, FormatSeconds) {
TEST_F(DurationUtilTest, FormatSeconds) {
formatSeconds("00:00.000", 0);
formatSeconds("00:01.000", 1);
formatSeconds("00:59.000", 59);
Expand Down

0 comments on commit 89612ff

Please sign in to comment.