Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance precision of track duration #970

Merged
merged 10 commits into from
Jun 25, 2016
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
8 changes: 8 additions & 0 deletions res/schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -416,4 +416,12 @@ METADATA
ALTER TABLE library ADD COLUMN tracktotal TEXT DEFAULT '//';
</sql>
</revision>
<revision version="27" min_compatible="3">
<description>
Store track durations with subsecond precision in new column 'duration_real'.
</description>
<sql>
ALTER TABLE library ADD COLUMN duration_real REAL DEFAULT duration;
</sql>
</revision>
</schema>
30 changes: 14 additions & 16 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,
fromTrackDuration / 2);
m_nextTransitionTime = math_min(m_transitionTime,
fromTrackDuration / 2.0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A Pentium is able to divide a float by an integer. No need for .0 here.


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);
toTrackDuration / 2.0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same here

}
}

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
12 changes: 7 additions & 5 deletions src/library/dao/trackdao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,15 +390,15 @@ void TrackDAO::addTracksPrepare() {
m_pQueryLibraryInsert->prepare("INSERT INTO library "
"("
"artist,title,album,album_artist,year,genre,tracknumber,tracktotal,composer,"
"grouping,filetype,location,comment,url,duration,rating,key,key_id,"
"grouping,filetype,location,comment,url,duration,duration_real,rating,key,key_id,"
"bitrate,samplerate,cuepoint,bpm,replaygain,replaygain_peak,wavesummaryhex,"
"timesplayed,channels,mixxx_deleted,header_parsed,"
"beats_version,beats_sub_version,beats,bpm_lock,"
"keys_version,keys_sub_version,keys,"
"coverart_source,coverart_type,coverart_location,coverart_hash"
") VALUES ("
":artist,:title,:album,:album_artist,:year,:genre,:tracknumber,:tracktotal,:composer,"
":grouping,:filetype,:location,:comment,:url,:duration,:rating,:key,:key_id,"
":grouping,:filetype,:location,:comment,:url,:duration,:duration_real,:rating,:key,:key_id,"
":bitrate,:samplerate,:cuepoint,:bpm,:replaygain,:replaygain_peak,:wavesummaryhex,"
":timesplayed,:channels,:mixxx_deleted,:header_parsed,"
":beats_version,:beats_sub_version,:beats,:bpm_lock,"
Expand Down Expand Up @@ -465,7 +465,8 @@ namespace {
pTrackLibraryQuery->bindValue(":filetype", track.getType());
pTrackLibraryQuery->bindValue(":comment", track.getComment());
pTrackLibraryQuery->bindValue(":url", track.getURL());
pTrackLibraryQuery->bindValue(":duration", track.getDuration());
pTrackLibraryQuery->bindValue(":duration", track.getDurationInt());
pTrackLibraryQuery->bindValue(":duration_real", track.getDuration());
pTrackLibraryQuery->bindValue(":rating", track.getRating());
pTrackLibraryQuery->bindValue(":bitrate", track.getBitrate());
pTrackLibraryQuery->bindValue(":samplerate", track.getSampleRate());
Expand Down Expand Up @@ -1088,7 +1089,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 Expand Up @@ -1279,7 +1280,7 @@ TrackPointer TrackDAO::getTrackFromDB(TrackId trackId) const {
{ "rating", setTrackRating },
{ "comment", setTrackComment },
{ "url", setTrackUrl },
{ "duration", setTrackDuration },
{ "duration_real", setTrackDuration },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leftover

{ "bitrate", setTrackBitrate },
{ "samplerate", setTrackSampleRate },
{ "cuepoint", setTrackCuePoint },
Expand Down Expand Up @@ -1542,6 +1543,7 @@ bool TrackDAO::updateTrack(Track* pTrack) {
"comment=:comment,"
"url=:url,"
"duration=:duration,"
"duration_real=:duration_real,"
"rating=:rating,"
"key=:key,"
"key_id=:key_id,"
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/library/trackcollection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include "util/assert.h"

// static
const int TrackCollection::kRequiredSchemaVersion = 26;
const int TrackCollection::kRequiredSchemaVersion = 27;

TrackCollection::TrackCollection(UserSettingsPointer pConfig)
: m_pConfig(pConfig),
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
2 changes: 1 addition & 1 deletion src/sources/soundsourceopus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Result SoundSourceOpus::parseTrackMetadataAndCoverArt(
pTrackMetadata->setSampleRate(kSamplingRate);
pTrackMetadata->setBitrate(op_bitrate(l_ptrOpusFile, -1) / 1000);
pTrackMetadata->setDuration(
op_pcm_total(l_ptrOpusFile, -1) / pTrackMetadata->getSampleRate());
double(op_pcm_total(l_ptrOpusFile, -1)) / double(pTrackMetadata->getSampleRate()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second cast is not required. I think we use static_cast() elsewhere


bool hasDate = false;
for (i = 0; i < l_ptrOpusTags->comments; ++i) {
Expand Down