diff options
author | Ferran Pujol Camins <ferranpujolcamins@gmail.com> | 2019-11-11 13:19:43 +0100 |
---|---|---|
committer | Ferran Pujol Camins <ferranpujolcamins@gmail.com> | 2019-11-11 13:19:43 +0100 |
commit | a16a2905296c938803196bdf729ab090587f0663 (patch) | |
tree | 82f4dcb737744d20ace4d86ac5dd906324b60a4c /src | |
parent | 03b4f06557d6c25301af69cb96b033b1b825a15d (diff) | |
parent | b23d56e2df37db12fb7860306bd878b2a968f118 (diff) |
Merge branch 'master' into new_colors_impl
Diffstat (limited to 'src')
71 files changed, 2584 insertions, 1704 deletions
diff --git a/src/analyzer/analyzersilence.cpp b/src/analyzer/analyzersilence.cpp index 9d5c814f1e..bde8445bef 100644 --- a/src/analyzer/analyzersilence.cpp +++ b/src/analyzer/analyzersilence.cpp @@ -9,40 +9,15 @@ constexpr float kSilenceThreshold = 0.001; // TODO: Change the above line to: //constexpr float kSilenceThreshold = db2ratio(-60.0f); -bool shouldUpdateMainCue(CuePosition mainCue) { - return mainCue.getSource() != Cue::MANUAL || - mainCue.getPosition() == -1.0 || - mainCue.getPosition() == 0.0; -} - -bool hasIntroCueStart(const Cue& introCue) { - return introCue.getPosition() != -1.0; -} - -bool hasOutroCueEnd(const Cue& outroCue) { - return outroCue.getEndPosition() > 0.0; -} - -bool needsIntroCueStart(const Cue& introCue) { - return introCue.getSource() != Cue::MANUAL && - !hasIntroCueStart(introCue); -} +bool shouldAnalyze(TrackPointer pTrack) { + CuePointer pIntroCue = pTrack->findCueByType(Cue::Type::Intro); + CuePointer pOutroCue = pTrack->findCueByType(Cue::Type::Outro); + CuePointer pAudibleSound = pTrack->findCueByType(Cue::Type::AudibleSound); -bool needsOutroCueEnd(const Cue& outroCue) { - return outroCue.getSource() != Cue::MANUAL && - !hasOutroCueEnd(outroCue); -} - -bool shouldAnalyze(TrackPointer tio) { - CuePointer pIntroCue = tio->findCueByType(Cue::INTRO); - if (!pIntroCue) { - return true; - } - CuePointer pOutroCue = tio->findCueByType(Cue::OUTRO); - if (!pOutroCue) { + if (!pIntroCue || !pOutroCue || !pAudibleSound || pAudibleSound->getLength() <= 0) { return true; } - return needsIntroCueStart(*pIntroCue) || needsOutroCueEnd(*pOutroCue); + return false; } } // anonymous namespace @@ -56,11 +31,11 @@ AnalyzerSilence::AnalyzerSilence(UserSettingsPointer pConfig) m_iSignalEnd(-1) { } -bool AnalyzerSilence::initialize(TrackPointer tio, int sampleRate, int totalSamples) { +bool AnalyzerSilence::initialize(TrackPointer pTrack, int sampleRate, int totalSamples) { Q_UNUSED(sampleRate); Q_UNUSED(totalSamples); - if (!shouldAnalyze(tio)) { + if (!shouldAnalyze(pTrack)) { return false; } @@ -100,7 +75,7 @@ bool AnalyzerSilence::processSamples(const CSAMPLE* pIn, const int iLen) { void AnalyzerSilence::cleanup() { } -void AnalyzerSilence::storeResults(TrackPointer tio) { +void AnalyzerSilence::storeResults(TrackPointer pTrack) { if (m_iSignalStart < 0) { m_iSignalStart = 0; } @@ -114,32 +89,53 @@ void AnalyzerSilence::storeResults(TrackPointer tio) { m_iSignalEnd = m_iFramesProcessed; } - double introStart = mixxx::kAnalysisChannels * m_iSignalStart; - double outroEnd = mixxx::kAnalysisChannels * m_iSignalEnd; + double firstSound = mixxx::kAnalysisChannels * m_iSignalStart; + double lastSound = mixxx::kAnalysisChannels * m_iSignalEnd; - if (shouldUpdateMainCue(tio->getCuePoint())) { - tio->setCuePoint(CuePosition(introStart, Cue::AUTOMATIC)); + CuePointer pAudibleSound = pTrack->findCueByType(Cue::Type::AudibleSound); + if (pAudibleSound == nullptr) { + pAudibleSound = pTrack->createAndAddCue(); + pAudibleSound->setType(Cue::Type::AudibleSound); } - - CuePointer pIntroCue = tio->findCueByType(Cue::INTRO); - if (!pIntroCue) { - pIntroCue = tio->createAndAddCue(); - pIntroCue->setType(Cue::INTRO); - pIntroCue->setSource(Cue::AUTOMATIC); - } - if (pIntroCue->getSource() != Cue::MANUAL) { - pIntroCue->setPosition(introStart); - pIntroCue->setLength(0.0); + // The user has no way to directly edit the AudibleSound cue. If the user + // has deleted the Intro or Outro Cue, this analysis will be rerun when + // the track is loaded again. In this case, adjust the AudibleSound Cue's + // positions. This could be helpful, for example, when the track length + // is changed in a different program, or the silence detection threshold + // is changed. + pAudibleSound->setStartPosition(firstSound); + pAudibleSound->setEndPosition(lastSound); + + CuePointer pIntroCue = pTrack->findCueByType(Cue::Type::Intro); + + double mainCue = pTrack->getCuePoint().getPosition(); + double introStart = firstSound; + // Before Mixxx 2.3, the default position for the main cue was 0.0. In this + // case, move the main cue point to the first sound. This case can be + // distinguished from a user intentionally setting the main cue position + // to 0.0 at a later time after analysis because in that case the intro cue + // would have already been created by this analyzer. + bool upgradingWithMainCueAtDefault = (mainCue == 0.0 && pIntroCue == nullptr); + if (mainCue == Cue::kNoPosition || upgradingWithMainCueAtDefault) { + pTrack->setCuePoint(CuePosition(firstSound)); + // NOTE: the actual default for this ConfigValue is set in DlgPrefDeck. + } else if (m_pConfig->getValue(ConfigKey("[Controls]", "SetIntroStartAtMainCue"), false) && + pIntroCue == nullptr) { + introStart = mainCue; } - CuePointer pOutroCue = tio->findCueByType(Cue::OUTRO); - if (!pOutroCue) { - pOutroCue = tio->createAndAddCue(); - pOutroCue->setType(Cue::OUTRO); - pOutroCue->setSource(Cue::AUTOMATIC); + if (pIntroCue == nullptr) { + pIntroCue = pTrack->createAndAddCue(); + pIntroCue->setType(Cue::Type::Intro); + pIntroCue->setStartPosition(introStart); + pIntroCue->setEndPosition(Cue::kNoPosition); } - if (pOutroCue->getSource() != Cue::MANUAL) { - pOutroCue->setPosition(-1.0); - pOutroCue->setLength(outroEnd); + + CuePointer pOutroCue = pTrack->findCueByType(Cue::Type::Outro); + if (pOutroCue == nullptr) { + pOutroCue = pTrack->createAndAddCue(); + pOutroCue->setType(Cue::Type::Outro); + pOutroCue->setStartPosition(Cue::kNoPosition); + pOutroCue->setEndPosition(lastSound); } } diff --git a/src/analyzer/analyzersilence.h b/src/analyzer/analyzersilence.h index b0b94f9c79..9c27b5c1e6 100644 --- a/src/analyzer/analyzersilence.h +++ b/src/analyzer/analyzersilence.h @@ -11,9 +11,9 @@ class AnalyzerSilence : public Analyzer { explicit AnalyzerSilence(UserSettingsPointer pConfig); ~AnalyzerSilence() override = default; - bool initialize(TrackPointer tio, int sampleRate, int totalSamples) override; + bool initialize(TrackPointer pTrack, int sampleRate, int totalSamples) override; bool processSamples(const CSAMPLE* pIn, const int iLen) override; - void storeResults(TrackPointer tio) override; + void storeResults(TrackPointer pTrack) override; void cleanup() override; private: diff --git a/src/engine/cachingreader/cachingreader.cpp b/src/engine/cachingreader/cachingreader.cpp index edaf66b42b..abdd1329cc 100644 --- a/src/engine/cachingreader/cachingreader.cpp +++ b/src/engine/cachingreader/cachingreader.cpp @@ -40,9 +40,8 @@ const SINT kNumberOfCachedChunksInMemory = 80; } // anonymous namespace - CachingReader::CachingReader(QString group, - UserSettingsPointer config) + UserSettingsPointer config) : m_pConfig(config), // Limit the number of in-flight requests to the worker. This should // prevent to overload the worker when it is not able to fetch those @@ -63,7 +62,6 @@ CachingReader::CachingReader(QString group, m_lruCachingReaderChunk(nullptr), m_sampleBuffer(CachingReaderChunk::kSamples * kNumberOfCachedChunksInMemory), m_worker(group, &m_chunkReadRequestFIFO, &m_readerStatusUpdateFIFO) { - m_allocatedCachingReaderChunks.reserve(kNumberOfCachedChunksInMemory); // Divide up the allocated raw memory buffer into total_chunks // chunks. Initialize each chunk to hold nothing and add it to the free @@ -265,7 +263,7 @@ void CachingReader::process() { // TRACK_LOADED without a chunk in between, assert this here. DEBUG_ASSERT(m_state.load() == STATE_TRACK_LOADING || (m_state.load() == STATE_TRACK_LOADED && - !m_mruCachingReaderChunk && !m_lruCachingReaderChunk)); + !m_mruCachingReaderChunk && !m_lruCachingReaderChunk)); // now purge also the recently used chunk list from the old track. if (m_mruCachingReaderChunk || m_lruCachingReaderChunk) { DEBUG_ASSERT(m_state.load() == STATE_TRACK_LOADING); @@ -349,11 +347,14 @@ CachingReader::ReadResult CachingReader::read(SINT startSample, SINT numSamples, remainingFrameIndexRange.start(), m_readableFrameIndexRange.start()); DEBUG_ASSERT(prerollFrameIndexRange.length() <= remainingFrameIndexRange.length()); - if (kLogger.traceEnabled()) { - kLogger.trace() - << "Prepending" + if (kLogger.debugEnabled()) { + kLogger.debug() + << "Preroll: Filling the first" << prerollFrameIndexRange.length() - << "frames of silence"; + << "sample frames in" + << remainingFrameIndexRange + << "with silence. Audio signal starts at" + << m_readableFrameIndexRange.start(); } const SINT prerollFrames = prerollFrameIndexRange.length(); const SINT prerollSamples = CachingReaderChunk::frames2samples(prerollFrames); diff --git a/src/engine/cachingreader/cachingreader.h b/src/engine/cachingreader/cachingreader.h index ca0df4d7d2..acec6c0ec5 100644 --- a/src/engine/cachingreader/cachingreader.h +++ b/src/engine/cachingreader/cachingreader.h @@ -5,11 +5,11 @@ #define ENGINE_CACHINGREADER_H #include <QAtomicInt> -#include <QList> -#include <QVector> -#include <QLinkedList> #include <QHash> +#include <QLinkedList> +#include <QList> #include <QVarLengthArray> +#include <QVector> #include "util/types.h" #include "preferences/usersettings.h" diff --git a/src/engine/cachingreader/cachingreaderworker.cpp b/src/engine/cachingreader/cachingreaderworker.cpp index ddfe9f3dbc..070a9993a2 100644 --- a/src/engine/cachingreader/cachingreaderworker.cpp +++ b/src/engine/cachingreader/cachingreaderworker.cpp @@ -42,8 +42,7 @@ ReaderStatusUpdate CachingReaderWorker::processReadRequest( chunkFrameIndexRange <= m_pAudioSource->frameIndexRange()); if (chunkFrameIndexRange.empty()) { ReaderStatusUpdate result; - result.init(CHUNK_READ_INVALID, pChunk, - m_pAudioSource ? m_pAudioSource->frameIndexRange() : mixxx::IndexRange()); + result.init(CHUNK_READ_INVALID, pChunk, m_pAudioSource ? m_pAudioSource->frameIndexRange() : mixxx::IndexRange()); return result; } @@ -71,8 +70,7 @@ ReaderStatusUpdate CachingReaderWorker::processReadRequest( } ReaderStatusUpdate result; - result.init(status, pChunk, - m_pAudioSource ? m_pAudioSource->frameIndexRange() : mixxx::IndexRange()); + result.init(status, pChunk, m_pAudioSource ? m_pAudioSource->frameIndexRange() : mixxx::IndexRange()); return result; } @@ -139,14 +137,13 @@ void CachingReaderWorker::loadTrack(const TrackPointer& pTrack) { QString filename = pTrack->getLocation(); if (filename.isEmpty() || !pTrack->checkFileExists()) { kLogger.warning() - << m_group - << "File not found" - << filename; + << m_group + << "File not found" + << filename; const auto update = ReaderStatusUpdate::trackUnloaded(); m_pReaderStatusFIFO->writeBlocking(&update, 1); emit trackLoadFailed( - pTrack, QString("The file '%1' could not be found.") - .arg(QDir::toNativeSeparators(filename))); + pTrack, QString("The file '%1' could not be found.").arg(QDir::toNativeSeparators(filename))); return; } @@ -161,7 +158,7 @@ void CachingReaderWorker::loadTrack(const TrackPointer& pTrack) { const auto update = ReaderStatusUpdate::trackUnloaded(); m_pReaderStatusFIFO->writeBlocking(&update, 1); emit trackLoadFailed( - pTrack, QString("The file '%1' could not be loaded").arg(filename)); + pTrack, QString("The file '%1' could not be loaded").arg(filename)); return; } @@ -177,7 +174,7 @@ void CachingReaderWorker::loadTrack(const TrackPointer& pTrack) { const auto update = ReaderStatusUpdate::trackUnloaded(); m_pReaderStatusFIFO->writeBlocking(&update, 1); emit trackLoadFailed( - pTrack, QString("The file '%1' is empty and could not be loaded").arg(filename)); + pTrack, QString("The file '%1' is empty and could not be loaded").arg(filename)); return; } @@ -190,7 +187,7 @@ void CachingReaderWorker::loadTrack(const TrackPointer& pTrack) { const auto update = ReaderStatusUpdate::trackLoaded( - m_pAudioSource->frameIndexRange()); + m_pAudioSource->frameIndexRange()); m_pReaderStatusFIFO->writeBlocking(&update, 1); // Emit that the track is loaded. diff --git a/src/engine/controls/bpmcontrol.cpp b/src/engine/controls/bpmcontrol.cpp index 301a2fd8fd..cd0725d1dd 100644 --- a/src/engine/controls/bpmcontrol.cpp +++ b/src/engine/controls/bpmcontrol.cpp @@ -37,7 +37,7 @@ constexpr SINT kSamplesPerFrame = 2; } BpmControl::BpmControl(QString group, - UserSettingsPointer pConfig) + UserSettingsPointer pConfig) : EngineControl(group, pConfig), m_tapFilter(this, kBpmTapFilterLength, kBpmTapMaxInterval), m_dSyncInstantaneousBpm(0.0), @@ -96,8 +96,10 @@ BpmControl::BpmControl(QString group, // bpm_up_small / bpm_down_small steps by kBpmRangeSmallStep m_pEngineBpm = new ControlLinPotmeter( ConfigKey(group, "bpm"), - kBpmRangeMin, kBpmRangeMax, - kBpmRangeStep, kBpmRangeSmallStep, + kBpmRangeMin, + kBpmRangeMax, + kBpmRangeStep, + kBpmRangeSmallStep, true); connect(m_pEngineBpm, &ControlObject::valueChanged, this, &BpmControl::slotUpdateRateSlider, diff --git a/src/engine/controls/cuecontrol.cpp b/src/engine/controls/cuecontrol.cpp index 589f4494bf..f607e932fa 100644 --- a/src/engine/controls/cuecontrol.cpp +++ b/src/engine/controls/cuecontrol.cpp @@ -53,12 +53,10 @@ CueControl::CueControl(QString group, UserSettingsPointer pConfig) m_pClosestBeat = ControlObject::getControl(ConfigKey(group, "beat_closest")); m_pCuePoint = new ControlObject(ConfigKey(group, "cue_point")); - m_pCuePoint->set(-1.0); + m_pCuePoint->set(Cue::kNoPosition); m_pCueMode = new ControlObject(ConfigKey(group, "cue_mode")); - m_pSeekOnLoadMode = new ControlObject(ConfigKey(group, "seekonload_mode")); - m_pCueSet = new ControlPushButton(ConfigKey(group, "cue_set")); m_pCueSet->setButtonMode(ControlPushButton::TRIGGER); connect(m_pCueSet, &ControlObject::valueChanged, @@ -118,7 +116,7 @@ CueControl::CueControl(QString group, UserSettingsPointer pConfig) m_pPlayIndicator = new ControlIndicator(ConfigKey(group, "play_indicator")); m_pIntroStartPosition = new ControlObject(ConfigKey(group, "intro_start_position")); - m_pIntroStartPosition->set(-1.0); + m_pIntroStartPosition->set(Cue::kNoPosition); m_pIntroStartEnabled = new ControlObject(ConfigKey(group, "intro_start_enabled")); m_pIntroStartEnabled->setReadOnly(); @@ -139,7 +137,7 @@ CueControl::CueControl(QString group, UserSettingsPointer pConfig) Qt::DirectConnection); m_pIntroEndPosition = new ControlObject(ConfigKey(group, "intro_end_position")); - m_pIntroEndPosition->set(-1.0); + m_pIntroEndPosition->set(Cue::kNoPosition); m_pIntroEndEnabled = new ControlObject(ConfigKey(group, "intro_end_enabled")); m_pIntroEndEnabled->setReadOnly(); @@ -160,7 +158,7 @@ CueControl::CueControl(QString group, UserSettingsPointer pConfig) Qt::DirectConnection); m_pOutroStartPosition = new ControlObject(ConfigKey(group, "outro_start_position")); - m_pOutroStartPosition->set(-1.0); + m_pOutroStartPosition->set(Cue::kNoPosition); m_pOutroStartEnabled = new ControlObject(ConfigKey(group, "outro_start_enabled")); m_pOutroStartEnabled->setReadOnly(); @@ -181,7 +179,7 @@ CueControl::CueControl(QString group, UserSettingsPointer pConfig) Qt::DirectConnection); m_pOutroEndPosition = new ControlObject(ConfigKey(group, "outro_end_position")); - m_pOutroEndPosition->set(-1.0); + m_pOutroEndPosition->set(Cue::kNoPosition); m_pOutroEndEnabled = new ControlObject(ConfigKey(group, "outro_end_enabled")); m_pOutroEndEnabled->setReadOnly(); @@ -208,7 +206,6 @@ CueControl::CueControl(QString group, UserSettingsPointer pConfig) CueControl::~CueControl() { delete m_pCuePoint; delete m_pCueMode; - delete m_pSeekOnLoadMode; delete m_pCueSet; delete m_pCueClear; delete m_pCueGoto; @@ -307,19 +304,19 @@ void CueControl::trackLoaded(TrackPointer pNewTrack) { QMutexLocker lock(&m_mutex); if (m_pLoadedTrack) { disconnect(m_pLoadedTrack.get(), 0, this, 0); - for (const auto& pControl: m_hotcueControls) { + for (const auto& pControl : m_hotcueControls) { detachCue(pControl); } m_pCueIndicator->setBlinkValue(ControlIndicator::OFF); - m_pCuePoint->set(-1.0); - m_pIntroStartPosition->set(-1.0); + m_pCuePoint->set(Cue::kNoPosition); + m_pIntroStartPosition->set(Cue::kNoPosition); m_pIntroStartEnabled->forceSet(0.0); - m_pIntroEndPosition->set(-1.0); |