diff --git a/src/analyserwaveform.cpp b/src/analyserwaveform.cpp index ae95eb29bb8..6518d2cc04b 100644 --- a/src/analyserwaveform.cpp +++ b/src/analyserwaveform.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include "analyserwaveform.h" @@ -15,10 +14,6 @@ AnalyserWaveform::AnalyserWaveform(ConfigObject* pConfig) : m_skipProcessing(false), - m_waveform(NULL), - m_waveformSummary(NULL), - m_waveformDataSize(0), - m_waveformSummaryDataSize(0), m_waveformData(NULL), m_waveformSummaryData(NULL), m_currentStride(0), @@ -60,10 +55,8 @@ bool AnalyserWaveform::initialise(TrackPointer tio, int sampleRate, int totalSam m_skipProcessing = false; m_timer->start(); - m_waveform = tio->getWaveform(); - m_waveformSummary = tio->getWaveformSummary(); - if (!m_waveform || !m_waveformSummary || totalSamples == 0) { + if (totalSamples == 0) { qWarning() << "AnalyserWaveform::initialise - no waveform/waveform summary"; return false; } @@ -72,10 +65,7 @@ bool AnalyserWaveform::initialise(TrackPointer tio, int sampleRate, int totalSam if (loadStored(tio)) { m_skipProcessing = true; } else { - // Now actually initalise the AnalyserWaveform: - QMutexLocker waveformLocker(m_waveform->getMutex()); - QMutexLocker waveformSummaryLocker(m_waveformSummary->getMutex()); - + // Now actually initialize the AnalyserWaveform: destroyFilters(); resetFilters(tio, sampleRate); @@ -83,17 +73,24 @@ bool AnalyserWaveform::initialise(TrackPointer tio, int sampleRate, int totalSam const int mainWaveformSampleRate = 441; //two visual sample per pixel in full width overview in full hd const int summaryWaveformSamples = 2*1920; - m_waveform->initalise(sampleRate, totalSamples, mainWaveformSampleRate); - m_waveformSummary->initalise(sampleRate, totalSamples, - mainWaveformSampleRate, summaryWaveformSamples); - m_waveformDataSize = m_waveform->getDataSize(); - m_waveformSummaryDataSize = m_waveformSummary->getDataSize(); + m_waveform = WaveformPointer(new Waveform( + sampleRate, totalSamples, mainWaveformSampleRate, -1)); + m_waveformSummary = WaveformPointer(new Waveform( + sampleRate, totalSamples, mainWaveformSampleRate, + summaryWaveformSamples)); + + // Now, that the Waveform memory is initialized, we can set set them to + // the TIO. Be aware that other threads of Mixxx can touch them from + // now. + tio->setWaveform(m_waveform); + tio->setWaveformSummary(m_waveformSummary); - m_waveformData = &m_waveform->at(0); - m_waveformSummaryData = &m_waveformSummary->at(0); + m_waveformData = m_waveform->data(); + m_waveformSummaryData = m_waveformSummary->data(); - m_stride.init(m_waveform->getAudioVisualRatio(), m_waveformSummary->getAudioVisualRatio()); + m_stride.init(m_waveform->getAudioVisualRatio(), + m_waveformSummary->getAudioVisualRatio()); m_currentStride = 0; m_currentSummaryStride = 0; @@ -111,17 +108,14 @@ bool AnalyserWaveform::initialise(TrackPointer tio, int sampleRate, int totalSam } bool AnalyserWaveform::loadStored(TrackPointer tio) const { - Waveform* waveform = tio->getWaveform(); - Waveform* waveformSummary = tio->getWaveformSummary(); - - if (!waveform || !waveformSummary) { - qWarning() << "AnalyserWaveform::loadStored - no waveform/waveform summary"; - return false; - } + ConstWaveformPointer pTrackWaveform = tio->getWaveform(); + ConstWaveformPointer pTrackWaveformSummary = tio->getWaveformSummary(); + ConstWaveformPointer pLoadedTrackWaveform; + ConstWaveformPointer pLoadedTrackWaveformSummary; int trackId = tio->getId(); - bool missingWaveform = waveform->getDataSize() == 0; - bool missingWavesummary = waveformSummary->getDataSize() == 0; + bool missingWaveform = pTrackWaveform.isNull(); + bool missingWavesummary = pTrackWaveformSummary.isNull(); if (trackId != -1 && (missingWaveform || missingWavesummary)) { QList analyses = @@ -135,9 +129,9 @@ bool AnalyserWaveform::loadStored(TrackPointer tio) const { if (analysis.type == AnalysisDao::TYPE_WAVEFORM) { vc = WaveformFactory::waveformVersionToVersionClass(analysis.version); if (missingWaveform && vc == WaveformFactory::VC_USE) { - if (WaveformFactory::updateWaveformFromAnalysis(waveform, analysis)) { - missingWaveform = false; - } + pLoadedTrackWaveform = ConstWaveformPointer( + WaveformFactory::loadWaveformFromAnalysis(analysis)); + missingWaveform = false; } else if (vc != WaveformFactory::VC_KEEP) { // remove all other Analysis except that one we should keep m_analysisDao->deleteAnalysis(analysis.analysisId); @@ -145,10 +139,9 @@ bool AnalyserWaveform::loadStored(TrackPointer tio) const { } if (analysis.type == AnalysisDao::TYPE_WAVESUMMARY) { vc = WaveformFactory::waveformSummaryVersionToVersionClass(analysis.version); if (missingWavesummary && vc == WaveformFactory::VC_USE) { - if (WaveformFactory::updateWaveformFromAnalysis(waveformSummary, analysis)) { - tio->waveformSummaryNew(); - missingWavesummary = false; - } + pLoadedTrackWaveformSummary = ConstWaveformPointer( + WaveformFactory::loadWaveformFromAnalysis(analysis)); + missingWavesummary = false; } else if (vc != WaveformFactory::VC_KEEP) { // remove all other Analysis except that one we should keep m_analysisDao->deleteAnalysis(analysis.analysisId); @@ -160,6 +153,12 @@ bool AnalyserWaveform::loadStored(TrackPointer tio) const { // If we don't need to calculate the waveform/wavesummary, skip. if (!missingWaveform && !missingWavesummary) { qDebug() << "AnalyserWaveform::loadStored - Stored waveform loaded"; + if (pLoadedTrackWaveform) { + tio->setWaveform(pLoadedTrackWaveform); + } + if (pLoadedTrackWaveformSummary) { + tio->setWaveformSummary(pLoadedTrackWaveformSummary); + } return true; } return false; @@ -204,36 +203,36 @@ void AnalyserWaveform::process(const CSAMPLE* buffer, const int bufferLength) { for (int i = 0; i < bufferLength; i+=2) { // Take max value, not average of data - CSAMPLE cover[2] = { fabs(buffer[i]), fabs(buffer[i+1]) }; - CSAMPLE clow[2] = { fabs(m_buffers[ Low][i]), fabs(m_buffers[ Low][i+1]) }; - CSAMPLE cmid[2] = { fabs(m_buffers[ Mid][i]), fabs(m_buffers[ Mid][i+1]) }; - CSAMPLE chigh[2] = { fabs(m_buffers[High][i]), fabs(m_buffers[High][i+1]) }; + CSAMPLE cover[2] = { fabs(buffer[i]), fabs(buffer[i + 1]) }; + CSAMPLE clow[2] = { fabs(m_buffers[Low][i]), fabs(m_buffers[Low][i + 1]) }; + CSAMPLE cmid[2] = { fabs(m_buffers[Mid][i]), fabs(m_buffers[Mid][i + 1]) }; + CSAMPLE chigh[2] = { fabs(m_buffers[High][i]), fabs(m_buffers[High][i + 1]) }; // This is for if you want to experiment with averaging instead of // maxing. // m_stride.m_overallData[Right] += buffer[i]*buffer[i]; - // m_stride.m_overallData[ Left] += buffer[i+1]*buffer[i+1]; - // m_stride.m_filteredData[Right][ Low] += m_buffers[ Low][i ]*m_buffers[ Low][i]; - // m_stride.m_filteredData[ Left][ Low] += m_buffers[ Low][i+1]*m_buffers[ Low][i+1]; - // m_stride.m_filteredData[Right][ Mid] += m_buffers[ Mid][i ]*m_buffers[ Mid][i]; - // m_stride.m_filteredData[ Left][ Mid] += m_buffers[ Mid][i+1]*m_buffers[ Mid][i+1]; - // m_stride.m_filteredData[Right][High] += m_buffers[High][i ]*m_buffers[High][i]; - // m_stride.m_filteredData[ Left][High] += m_buffers[High][i+1]*m_buffers[High][i+1]; + // m_stride.m_overallData[Left] += buffer[i + 1]*buffer[i + 1]; + // m_stride.m_filteredData[Right][Low] += m_buffers[Low][i]*m_buffers[Low][i]; + // m_stride.m_filteredData[Left][Low] += m_buffers[Low][i + 1]*m_buffers[Low][i + 1]; + // m_stride.m_filteredData[Right][Mid] += m_buffers[Mid][i]*m_buffers[Mid][i]; + // m_stride.m_filteredData[Left][Mid] += m_buffers[Mid][i + 1]*m_buffers[Mid][i + 1]; + // m_stride.m_filteredData[Right][High] += m_buffers[High][i]*m_buffers[High][i]; + // m_stride.m_filteredData[Left][High] += m_buffers[High][i + 1]*m_buffers[High][i + 1]; // Record the max across this stride. storeIfGreater(&m_stride.m_overallData[Left], cover[Left]); storeIfGreater(&m_stride.m_overallData[Right], cover[Right]); - storeIfGreater(&m_stride.m_filteredData[ Left][ Low], clow[Left]); - storeIfGreater(&m_stride.m_filteredData[Right][ Low], clow[Right]); - storeIfGreater(&m_stride.m_filteredData[ Left][ Mid], cmid[Left]); - storeIfGreater(&m_stride.m_filteredData[Right][ Mid], cmid[Right]); - storeIfGreater(&m_stride.m_filteredData[ Left][High], chigh[Left]); + storeIfGreater(&m_stride.m_filteredData[Left][Low], clow[Left]); + storeIfGreater(&m_stride.m_filteredData[Right][Low], clow[Right]); + storeIfGreater(&m_stride.m_filteredData[Left][Mid], cmid[Left]); + storeIfGreater(&m_stride.m_filteredData[Right][Mid], cmid[Right]); + storeIfGreater(&m_stride.m_filteredData[Left][High], chigh[Left]); storeIfGreater(&m_stride.m_filteredData[Right][High], chigh[Right]); m_stride.m_position++; if (fmod(m_stride.m_position, m_stride.m_length) < 1) { - if (m_currentStride + ChannelCount > m_waveformDataSize) { + if (m_currentStride + ChannelCount > m_waveform->getDataSize()) { qWarning() << "AnalyserWaveform::process - currentStride >= waveform size"; return; } @@ -243,7 +242,7 @@ void AnalyserWaveform::process(const CSAMPLE* buffer, const int bufferLength) { } if (fmod(m_stride.m_position, m_stride.m_averageLength) < 1) { - if (m_currentSummaryStride + ChannelCount > m_waveformSummaryDataSize) { + if (m_currentSummaryStride + ChannelCount > m_waveformSummary->getDataSize()) { qWarning() << "AnalyserWaveform::process - current summary stride >= waveform summary size"; return; } @@ -252,13 +251,13 @@ void AnalyserWaveform::process(const CSAMPLE* buffer, const int bufferLength) { m_waveformSummary->setCompletion(m_currentSummaryStride); #ifdef TEST_HEAT_MAP - QPointF point(float(m_strideSummary.m_filteredData[Right][High]), - float(m_strideSummary.m_filteredData[Right][ Mid])); + QPointF point(m_stride.m_filteredData[Right][High], + m_stride.m_filteredData[Right][Mid]); float norm = sqrt(point.x()*point.x() + point.y()*point.y()); point /= norm; - point *= m_strideSummary.m_filteredData[Right][ Low]; + point *= m_stride.m_filteredData[Right][Low]; test_heatMap->setPixel(point.toPoint(),0xFF0000FF); #endif } @@ -274,33 +273,45 @@ void AnalyserWaveform::cleanup(TrackPointer tio) { return; } - if (m_waveform) { - m_waveform->reset(); - } - - if (m_waveformSummary) { - m_waveformSummary->reset(); - } + tio->setWaveform(ConstWaveformPointer()); + // Since clear() could delete the waveform, clear our pointer to the + // waveform's vector data first. + m_waveformData = NULL; + m_waveform.clear(); + + tio->setWaveformSummary(ConstWaveformPointer()); + // Since clear() could delete the waveform, clear our pointer to the + // waveform's vector data first. + m_waveformSummaryData = NULL; + m_waveformSummary.clear(); } void AnalyserWaveform::finalise(TrackPointer tio) { - if (m_skipProcessing || m_waveform == NULL || m_waveformSummary == NULL) { + if (m_skipProcessing) { return; } - QMutexLocker waveformLocker(m_waveform->getMutex()); // Force completion to waveform size - m_waveform->setCompletion(m_waveform->getDataSize()); - m_waveform->setVersion(WaveformFactory::currentWaveformVersion()); - m_waveform->setDescription(WaveformFactory::currentWaveformDescription()); - waveformLocker.unlock(); + if (m_waveform) { + m_waveform->setCompletion(m_waveform->getDataSize()); + m_waveform->setVersion(WaveformFactory::currentWaveformVersion()); + m_waveform->setDescription(WaveformFactory::currentWaveformDescription()); + // Since clear() could delete the waveform, clear our pointer to the + // waveform's vector data first. + m_waveformData = NULL; + m_waveform.clear(); + } - QMutexLocker waveformSummaryLocker(m_waveformSummary->getMutex()); // Force completion to waveform size - m_waveformSummary->setCompletion(m_waveformSummary->getDataSize()); - m_waveformSummary->setVersion(WaveformFactory::currentWaveformSummaryVersion()); - m_waveformSummary->setDescription(WaveformFactory::currentWaveformSummaryDescription()); - waveformSummaryLocker.unlock(); + if (m_waveformSummary) { + m_waveformSummary->setCompletion(m_waveformSummary->getDataSize()); + m_waveformSummary->setVersion(WaveformFactory::currentWaveformSummaryVersion()); + m_waveformSummary->setDescription(WaveformFactory::currentWaveformSummaryDescription()); + // Since clear() could delete the waveform, clear our pointer to the + // waveform's vector data first. + m_waveformSummaryData = NULL; + m_waveformSummary.clear(); + } #ifdef TEST_HEAT_MAP test_heatMap->save("heatMap.png"); diff --git a/src/analyserwaveform.h b/src/analyserwaveform.h index 3439b34a456..bc98c4eeb93 100644 --- a/src/analyserwaveform.h +++ b/src/analyserwaveform.h @@ -31,7 +31,7 @@ inline CSAMPLE scaleSignal(CSAMPLE invalue, FilterIndex index = FilterCount) { } } -class WaveformStride { +struct WaveformStride { inline void init(double samples, double averageSamples) { m_length = samples; m_averageLength = averageSamples; @@ -122,7 +122,6 @@ class WaveformStride { } } - private: int m_position; double m_length; double m_averageLength; @@ -136,9 +135,6 @@ class WaveformStride { float m_averageFilteredData[ChannelCount][FilterCount]; float m_postScaleConversion; - - private: - friend class AnalyserWaveform; }; class AnalyserWaveform : public Analyser { @@ -163,10 +159,8 @@ class AnalyserWaveform : public Analyser { private: bool m_skipProcessing; - Waveform* m_waveform; - Waveform* m_waveformSummary; - int m_waveformDataSize; - int m_waveformSummaryDataSize; + WaveformPointer m_waveform; + WaveformPointer m_waveformSummary; WaveformData* m_waveformData; WaveformData* m_waveformSummaryData; diff --git a/src/library/dao/analysisdao.cpp b/src/library/dao/analysisdao.cpp index 48f861e1f8c..a3c8730c777 100644 --- a/src/library/dao/analysisdao.cpp +++ b/src/library/dao/analysisdao.cpp @@ -320,8 +320,8 @@ void AnalysisDao::saveTrackAnalyses(TrackInfoObject* pTrack) { return; } const int trackId = pTrack->getId(); - Waveform* pWaveform = pTrack->getWaveform(); - Waveform* pWaveSummary = pTrack->getWaveformSummary(); + ConstWaveformPointer pWaveform = pTrack->getWaveform(); + ConstWaveformPointer pWaveSummary = pTrack->getWaveformSummary(); // Don't try to save invalid or non-dirty waveforms. if (!pWaveform || pWaveform->getDataSize() == 0 || !pWaveform->isDirty() || diff --git a/src/trackinfoobject.cpp b/src/trackinfoobject.cpp index c5bb1523526..e61877c9aef 100644 --- a/src/trackinfoobject.cpp +++ b/src/trackinfoobject.cpp @@ -48,8 +48,6 @@ TrackInfoObject::TrackInfoObject(const QString& file, m_pSecurityToken(pToken.isNull() ? Sandbox::openSecurityToken( m_fileInfo, true) : pToken), m_qMutex(QMutex::Recursive), - m_waveform(new Waveform()), - m_waveformSummary(new Waveform()), m_analyserProgress(-1) { initialize(parseHeader, parseCoverArt); } @@ -61,16 +59,12 @@ TrackInfoObject::TrackInfoObject(const QFileInfo& fileInfo, m_pSecurityToken(pToken.isNull() ? Sandbox::openSecurityToken( m_fileInfo, true) : pToken), m_qMutex(QMutex::Recursive), - m_waveform(new Waveform()), - m_waveformSummary(new Waveform()), m_analyserProgress(-1) { initialize(parseHeader, parseCoverArt); } TrackInfoObject::TrackInfoObject(const QDomNode &nodeHeader) : m_qMutex(QMutex::Recursive), - m_waveform(new Waveform()), - m_waveformSummary(new Waveform()), m_analyserProgress(-1) { QString filename = XmlParse::selectNodeQString(nodeHeader, "Filename"); QString location = XmlParse::selectNodeQString(nodeHeader, "Filepath") + "/" + filename; @@ -145,9 +139,6 @@ TrackInfoObject::~TrackInfoObject() { // Notifies TrackDAO and other listeners that this track is about to be // deleted and should be saved to the database, removed from caches, etc. emit(deleted(this)); - - delete m_waveform; - delete m_waveformSummary; } void TrackInfoObject::parse(bool parseCoverArt) { @@ -788,16 +779,21 @@ QString TrackInfoObject::getURL() { return m_sURL; } -Waveform* TrackInfoObject::getWaveform() { +ConstWaveformPointer TrackInfoObject::getWaveform() { return m_waveform; } -Waveform* TrackInfoObject::getWaveformSummary() { +void TrackInfoObject::setWaveform(ConstWaveformPointer pWaveform) { + m_waveform = pWaveform; + emit(waveformUpdated()); +} + +ConstWaveformPointer TrackInfoObject::getWaveformSummary() const { return m_waveformSummary; } -// called from the AnalyserQueue Thread -void TrackInfoObject::waveformSummaryNew() { +void TrackInfoObject::setWaveformSummary(ConstWaveformPointer pWaveform) { + m_waveformSummary = pWaveform; emit(waveformSummaryUpdated()); } diff --git a/src/trackinfoobject.h b/src/trackinfoobject.h index 5646fde98ec..02f76e1f125 100644 --- a/src/trackinfoobject.h +++ b/src/trackinfoobject.h @@ -36,9 +36,9 @@ #include "track/beats.h" #include "track/keys.h" #include "util/sandbox.h" +#include "waveform/waveform.h" class Cue; -class Waveform; class TrackInfoObject; typedef QSharedPointer TrackPointer; @@ -223,12 +223,11 @@ class TrackInfoObject : public QObject { // Set URL for track void setURL(const QString& url); - Waveform* getWaveform(); - void waveformNew(); + ConstWaveformPointer getWaveform(); + void setWaveform(ConstWaveformPointer pWaveform); - Waveform* getWaveformSummary(); - const Waveform* getWaveformSummary() const; - void waveformSummaryNew(); + ConstWaveformPointer getWaveformSummary() const; + void setWaveformSummary(ConstWaveformPointer pWaveform); void setAnalyserProgress(int progress); int getAnalyserProgress() const; @@ -396,8 +395,8 @@ class TrackInfoObject : public QObject { BeatsPointer m_pBeats; //Visual waveform data - Waveform* const m_waveform; - Waveform* const m_waveformSummary; + ConstWaveformPointer m_waveform; + ConstWaveformPointer m_waveformSummary; QAtomicInt m_analyserProgress; // in 0.1% diff --git a/src/waveform/renderers/glslwaveformrenderersignal.cpp b/src/waveform/renderers/glslwaveformrenderersignal.cpp index 28d3ba4ce37..d11563091f4 100644 --- a/src/waveform/renderers/glslwaveformrenderersignal.cpp +++ b/src/waveform/renderers/glslwaveformrenderersignal.cpp @@ -79,13 +79,13 @@ bool GLSLWaveformRendererSignal::loadShaders() { bool GLSLWaveformRendererSignal::loadTexture() { TrackPointer trackInfo = m_waveformRenderer->getTrackInfo(); - Waveform* waveform = NULL; + ConstWaveformPointer waveform; int dataSize = 0; - WaveformData* data = NULL; + const WaveformData* data = NULL; if (trackInfo) { waveform = trackInfo->getWaveform(); - if (waveform != NULL) { + if (waveform) { dataSize = waveform->getDataSize(); if (dataSize > 1) { data = waveform->data(); @@ -229,8 +229,8 @@ void GLSLWaveformRendererSignal::draw(QPainter* painter, QPaintEvent* /*event*/) return; } - const Waveform* waveform = trackInfo->getWaveform(); - if (waveform == NULL) { + ConstWaveformPointer waveform = trackInfo->getWaveform(); + if (waveform.isNull()) { return; } diff --git a/src/waveform/renderers/glvsynctestrenderer.cpp b/src/waveform/renderers/glvsynctestrenderer.cpp index aadd8f7cec3..75eab2eabe9 100644 --- a/src/waveform/renderers/glvsynctestrenderer.cpp +++ b/src/waveform/renderers/glvsynctestrenderer.cpp @@ -38,8 +38,8 @@ void GLVSyncTestRenderer::draw(QPainter* painter, QPaintEvent* /*event*/) { return; } - const Waveform* waveform = pTrack->getWaveform(); - if (waveform == NULL) { + ConstWaveformPointer waveform = pTrack->getWaveform(); + if (waveform.isNull()) { return; } diff --git a/src/waveform/renderers/glwaveformrendererfilteredsignal.cpp b/src/waveform/renderers/glwaveformrendererfilteredsignal.cpp index ae129c1adaa..5aa38b7b9fd 100644 --- a/src/waveform/renderers/glwaveformrendererfilteredsignal.cpp +++ b/src/waveform/renderers/glwaveformrendererfilteredsignal.cpp @@ -31,8 +31,8 @@ void GLWaveformRendererFilteredSignal::draw(QPainter* painter, QPaintEvent* /*ev return; } - const Waveform* waveform = pTrack->getWaveform(); - if (waveform == NULL) { + ConstWaveformPointer waveform = pTrack->getWaveform(); + if (waveform.isNull()) { return; } diff --git a/src/waveform/renderers/glwaveformrendererrgb.cpp b/src/waveform/renderers/glwaveformrendererrgb.cpp index d1c56169b27..b361c6c1fa2 100644 --- a/src/waveform/renderers/glwaveformrendererrgb.cpp +++ b/src/waveform/renderers/glwaveformrendererrgb.cpp @@ -57,8 +57,8 @@ void GLWaveformRendererRGB::draw(QPainter* painter, QPaintEvent* /*event*/) { return; } - const Waveform* waveform = pTrack->getWaveform(); - if (waveform == NULL) { + ConstWaveformPointer waveform = pTrack->getWaveform(); + if (waveform.isNull()) { return; } diff --git a/src/waveform/renderers/glwaveformrenderersimplesignal.cpp b/src/waveform/renderers/glwaveformrenderersimplesignal.cpp index 197a124035e..2b39e7842b7 100644 --- a/src/waveform/renderers/glwaveformrenderersimplesignal.cpp +++ b/src/waveform/renderers/glwaveformrenderersimplesignal.cpp @@ -32,8 +32,8 @@ void GLWaveformRendererSimpleSignal::draw(QPainter* painter, QPaintEvent* /*even return; } - const Waveform* waveform = pTrack->getWaveform(); - if (waveform == NULL) { + ConstWaveformPointer waveform = pTrack->getWaveform(); + if (waveform.isNull()) { return; } diff --git a/src/waveform/renderers/qtwaveformrendererfilteredsignal.cpp b/src/waveform/renderers/qtwaveformrendererfilteredsignal.cpp index d12355fea6a..6e154b66ddf 100644 --- a/src/waveform/renderers/qtwaveformrendererfilteredsignal.cpp +++ b/src/waveform/renderers/qtwaveformrendererfilteredsignal.cpp @@ -101,8 +101,8 @@ int QtWaveformRendererFilteredSignal::buildPolygon() { return 0; } - const Waveform* waveform = pTrack->getWaveform(); - if (waveform == NULL) { + ConstWaveformPointer waveform = pTrack->getWaveform(); + if (waveform.isNull()) { return 0; } diff --git a/src/waveform/renderers/qtwaveformrenderersimplesignal.cpp b/src/waveform/renderers/qtwaveformrenderersimplesignal.cpp index 64c7dae1365..3623a36d239 100644 --- a/src/waveform/renderers/qtwaveformrenderersimplesignal.cpp +++ b/src/waveform/renderers/qtwaveformrenderersimplesignal.cpp @@ -43,8 +43,8 @@ void QtWaveformRendererSimpleSignal::draw(QPainter* painter, QPaintEvent* /*even return; } - const Waveform* waveform = pTrack->getWaveform(); - if (waveform == NULL) { + ConstWaveformPointer waveform = pTrack->getWaveform(); + if (waveform.isNull()) { return; } diff --git a/src/waveform/renderers/waveformrendererfilteredsignal.cpp b/src/waveform/renderers/waveformrendererfilteredsignal.cpp index 2cd009a540d..f26e822d9b8 100644 --- a/src/waveform/renderers/waveformrendererfilteredsignal.cpp +++ b/src/waveform/renderers/waveformrendererfilteredsignal.cpp @@ -34,8 +34,8 @@ void WaveformRendererFilteredSignal::draw(QPainter* painter, return; } - const Waveform* waveform = trackInfo->getWaveform(); - if (waveform == NULL) { + ConstWaveformPointer waveform = trackInfo->getWaveform(); + if (waveform.isNull()) { return; } diff --git a/src/waveform/renderers/waveformrendererhsv.cpp b/src/waveform/renderers/waveformrendererhsv.cpp index 108a5ff6dca..6c4f7bbd17e 100644 --- a/src/waveform/renderers/waveformrendererhsv.cpp +++ b/src/waveform/renderers/waveformrendererhsv.cpp @@ -28,8 +28,8 @@ void WaveformRendererHSV::draw(QPainter* painter, return; } - const Waveform* waveform = trackInfo->getWaveform(); - if (waveform == NULL) { + ConstWaveformPointer waveform = trackInfo->getWaveform(); + if (waveform.isNull()) { return; } diff --git a/src/waveform/renderers/waveformrendererrgb.cpp b/src/waveform/renderers/waveformrendererrgb.cpp index 445cf6528ee..92321c5a1fd 100644 --- a/src/waveform/renderers/waveformrendererrgb.cpp +++ b/src/waveform/renderers/waveformrendererrgb.cpp @@ -50,8 +50,8 @@ void WaveformRendererRGB::draw(QPainter* painter, return; } - const Waveform* waveform = trackInfo->getWaveform(); - if (waveform == NULL) { + ConstWaveformPointer waveform = trackInfo->getWaveform(); + if (waveform.isNull()) { return; } diff --git a/src/waveform/renderers/waveformwidgetrenderer.cpp b/src/waveform/renderers/waveformwidgetrenderer.cpp index e9d1cae4355..6c1fc6a392f 100644 --- a/src/waveform/renderers/waveformwidgetrenderer.cpp +++ b/src/waveform/renderers/waveformwidgetrenderer.cpp @@ -14,7 +14,6 @@ const int WaveformWidgetRenderer::s_waveformMaxZoom = 6; WaveformWidgetRenderer::WaveformWidgetRenderer(const char* group) : m_group(group), - m_trackInfoObject(0), m_height(-1), m_width(-1), @@ -121,12 +120,16 @@ void WaveformWidgetRenderer::onPreRender(VSyncThread* vsyncThread) { double visualSamplePerPixel = m_zoomFactor * (1.0 + m_rateAdjust); m_visualSamplePerPixel = math_max(1.0, visualSamplePerPixel); - if (m_trackInfoObject) { - m_audioSamplePerPixel = m_visualSamplePerPixel * m_trackInfoObject->getWaveform()->getAudioVisualRatio(); + TrackPointer pTrack(m_pTrack); + ConstWaveformPointer pWaveform = pTrack ? pTrack->getWaveform() : ConstWaveformPointer(); + int waveformDataSize = pWaveform ? pWaveform->getDataSize() : 0; + if (pWaveform) { + m_audioSamplePerPixel = m_visualSamplePerPixel * pWaveform->getAudioVisualRatio(); } else { m_audioSamplePerPixel = 0.0; } + m_playPos = m_visualPlayPosition->getAtNextVSync(vsyncThread); // m_playPos = -1 happens, when a new track is in buffer but m_visualPlayPosition was not updated @@ -140,7 +143,7 @@ void WaveformWidgetRenderer::onPreRender(VSyncThread* vsyncThread) { // Avoid pixel jitter in play position by rounding to the nearest track // pixel. m_playPos = round(m_playPos * m_trackPixelCount) / m_trackPixelCount; // Avoid pixel jitter in play position - m_playPosVSample = m_playPos * m_trackInfoObject->getWaveform()->getDataSize(); + m_playPosVSample = m_playPos * waveformDataSize; m_firstDisplayedPosition = m_playPos - displayedLengthHalf; m_lastDisplayedPosition = m_playPos + displayedLengthHalf; @@ -249,7 +252,7 @@ void WaveformWidgetRenderer::setZoom(int zoom) { } void WaveformWidgetRenderer::setTrack(TrackPointer track) { - m_trackInfoObject = track; + m_pTrack = track; //used to postpone first display until track sample is actually available m_trackSamples = -1.0; diff --git a/src/waveform/renderers/waveformwidgetrenderer.h b/src/waveform/renderers/waveformwidgetrenderer.h index 6d058a8f80c..fb9953dca43 100644 --- a/src/waveform/renderers/waveformwidgetrenderer.h +++ b/src/waveform/renderers/waveformwidgetrenderer.h @@ -35,7 +35,7 @@ class WaveformWidgetRenderer { void draw(QPainter* painter, QPaintEvent* event); inline const char* getGroup() const { return m_group;} - const TrackPointer getTrackInfo() const { return m_trackInfoObject;} + const TrackPointer getTrackInfo() const { return m_pTrack;} double getFirstDisplayedPosition() const { return m_firstDisplayedPosition;} double getLastDisplayedPosition() const { return m_lastDisplayedPosition;} @@ -85,7 +85,7 @@ class WaveformWidgetRenderer { protected: const char* m_group; - TrackPointer m_trackInfoObject; + TrackPointer m_pTrack; QList m_rendererStack; int m_height; int m_width; diff --git a/src/waveform/waveform.cpp b/src/waveform/waveform.cpp index c74597d080f..86f8e1fd6b5 100644 --- a/src/waveform/waveform.cpp +++ b/src/waveform/waveform.cpp @@ -5,6 +5,8 @@ using namespace mixxx::track; +const int kNumChannels = 2; + // Return the smallest power of 2 which is greater than the desired size when // squared. int computeTextureStride(int size) { @@ -18,18 +20,51 @@ int computeTextureStride(int size) { Waveform::Waveform(const QByteArray data) : m_id(-1), m_bDirty(true), - m_numChannels(2), m_dataSize(0), m_visualSampleRate(0), - m_audioVisualRatio(0.), + m_audioVisualRatio(0), m_textureStride(computeTextureStride(0)), - m_completion(-1), - m_mutex(new QMutex()) { + m_completion(-1) { readByteArray(data); } +Waveform::Waveform(int audioSampleRate, int audioSamples, + int desiredVisualSampleRate, int maxVisualSamples) + : m_id(-1), + m_bDirty(true), + m_dataSize(0), + m_visualSampleRate(0), + m_audioVisualRatio(0), + m_textureStride(1024), + m_completion(-1) { + int numberOfVisualSamples = 0; + if (audioSampleRate > 0) { + if (maxVisualSamples == -1) { + // Waveform + if (desiredVisualSampleRate < audioSampleRate) { + m_visualSampleRate = + static_cast(desiredVisualSampleRate); + } else { + m_visualSampleRate = static_cast(audioSampleRate); + } + } else { + // Waveform Summary (Overview) + if (audioSamples > maxVisualSamples) { + m_visualSampleRate = (double)maxVisualSamples * + (double)audioSampleRate / (double)audioSamples; + } else { + m_visualSampleRate = audioSampleRate; + } + } + m_audioVisualRatio = (double)audioSampleRate / (double)m_visualSampleRate; + numberOfVisualSamples = (audioSamples / m_audioVisualRatio) + 1; + numberOfVisualSamples += numberOfVisualSamples%2; + } + assign(numberOfVisualSamples, 0); + setCompletion(0); +} + Waveform::~Waveform() { - delete m_mutex; } QByteArray Waveform::toByteArray() const { @@ -61,7 +96,7 @@ QByteArray Waveform::toByteArray() const { io::Waveform::Signal* high = filtered->mutable_high(); // TODO(vrince) set max/min for each signal - int numChannels = getNumChannels(); + int numChannels = kNumChannels; all->set_units(io::Waveform::RMS); all->set_channels(numChannels); low->set_units(io::Waveform::RMS); @@ -91,7 +126,7 @@ QByteArray Waveform::toByteArray() const { return QByteArray(output.data(), output.length()); } -void Waveform::readByteArray(const QByteArray data) { +void Waveform::readByteArray(const QByteArray& data) { if (data.isNull()) { return; } @@ -161,48 +196,6 @@ void Waveform::readByteArray(const QByteArray data) { m_bDirty = false; } -void Waveform::reset() { - m_dataSize = 0; - m_textureStride = computeTextureStride(0); - m_completion = -1; - m_visualSampleRate = 0; - m_audioVisualRatio = 0; - m_data.clear(); - m_bDirty = true; -} - -void Waveform::initalise(int audioSampleRate, int audioSamples, - int desiredVisualSampleRate, int maxVisualSamples) { - int numberOfVisualSamples; - - if (audioSampleRate) { - if (maxVisualSamples == -1) { - // Waveform - if (desiredVisualSampleRate < audioSampleRate) { - m_visualSampleRate = (double)desiredVisualSampleRate; - } else { - m_visualSampleRate = (double)audioSampleRate; - } - } else { - // Waveform Summary (Overview) - if (audioSamples > maxVisualSamples) { - m_visualSampleRate = (double)maxVisualSamples * - (double)audioSampleRate / (double)audioSamples; - } else { - m_visualSampleRate = audioSampleRate; - } - } - m_audioVisualRatio = (double)audioSampleRate / (double)m_visualSampleRate; - numberOfVisualSamples = (audioSamples / m_audioVisualRatio) + 1; - numberOfVisualSamples += numberOfVisualSamples%2; - } else { - numberOfVisualSamples = 0; - } - assign(numberOfVisualSamples, 0); - setCompletion(0); - m_bDirty = true; -} - void Waveform::resize(int size) { m_dataSize = size; m_textureStride = computeTextureStride(size); diff --git a/src/waveform/waveform.h b/src/waveform/waveform.h index 5924e55cad7..b9547dff6c0 100644 --- a/src/waveform/waveform.h +++ b/src/waveform/waveform.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include "util.h" @@ -28,54 +30,87 @@ union WaveformData { class Waveform { public: - Waveform(const QByteArray pData = QByteArray()); - virtual ~Waveform(); + explicit Waveform(const QByteArray pData = QByteArray()); + Waveform(int audioSampleRate, int audioSamples, + int desiredVisualSampleRate, int maxVisualSamples); - void readByteArray(const QByteArray data); + virtual ~Waveform(); int getId() const { + QMutexLocker locker(&m_mutex); return m_id; } + void setId(int id) { + QMutexLocker locker(&m_mutex); m_id = id; } + QString getVersion() const { + QMutexLocker locker(&m_mutex); return m_version; } + void setVersion(QString version) { + QMutexLocker locker(&m_mutex); m_version = version; } + QString getDescription() const { + QMutexLocker locker(&m_mutex); return m_description; } + void setDescription(QString description) { + QMutexLocker locker(&m_mutex); m_description = description; } + QByteArray toByteArray() const; - void reset(); + // We do not lock the mutex since m_dataSize and m_visualSampleRate are not + // changed after the constructor runs. + bool isValid() const { + return getDataSize() > 0 && getVisualSampleRate() > 0; + } + + bool isDirty() const { + return m_bDirty; + } - bool isValid() const { return getDataSize() > 0 && getVisualSampleRate() > 0; } - bool isDirty() const { return m_bDirty; } - void setDirty(bool bDirty) { + // AnalysisDAO needs to be able to set the waveform as clean so we mark this + // as const and m_bDirty mutable. + void setDirty(bool bDirty) const { m_bDirty = bDirty; } - double getVisualSampleRate() const { return m_visualSampleRate; } - double getAudioVisualRatio() const { return m_audioVisualRatio; } + // We do not lock the mutex since m_audioVisualRatio is not changed after + // the constructor runs. + double getAudioVisualRatio() const { + return m_audioVisualRatio; + } // Atomically lookup the completion of the waveform. Represents the number // of data elements that have been processed out of dataSize. - int getCompletion() const { return load_atomic(m_completion); } - int getTextureStride() const { return m_textureStride; } - int getTextureSize() const { return m_data.size(); } + int getCompletion() const { + return load_atomic(m_completion); + } + void setCompletion(int completion) { + m_completion = completion; + } - // Atomically get the number of data elements in this Waveform. You do not - // need to lock the Waveform's mutex before calling this method. - int getDataSize() const { return load_atomic(m_dataSize); } - int getNumChannels() const { return load_atomic(m_numChannels); } + // We do not lock the mutex since m_textureStride is not changed after + // the constructor runs. + inline int getTextureStride() const { return m_textureStride; } - const std::vector& getConstData() const { return m_data;} + // We do not lock the mutex since m_data is not resized after the + // constructor runs. + inline int getTextureSize() const { return m_data.size(); } + + // Atomically get the number of data elements in this Waveform. We do not + // lock the mutex since m_dataSize is not changed after the constructor + // runs. + inline int getDataSize() const { return m_dataSize; } inline const WaveformData& get(int i) const { return m_data[i];} inline unsigned char getLow(int i) const { return m_data[i].filtered.low;} @@ -83,55 +118,65 @@ class Waveform { inline unsigned char getHigh(int i) const { return m_data[i].filtered.high;} inline unsigned char getAll(int i) const { return m_data[i].filtered.all;} + // We do not lock the mutex since m_data is not resized after the + // constructor runs. WaveformData* data() { return &m_data[0];} - const WaveformData* data() const { return &m_data[0];} - inline QMutex* getMutex() const { - return m_mutex; - } + // We do not lock the mutex since m_data is not resized after the + // constructor runs. + const WaveformData* data() const { return &m_data[0];} void dump() const; private: + void readByteArray(const QByteArray& data); void resize(int size); void assign(int size, int value = 0); - void initalise(int audioSampleRate, int audioSamples, - int desiredVisualSampleRate, int maxVisualSamples = -1); - inline WaveformData& at(int i) { return m_data[i];} inline unsigned char& low(int i) { return m_data[i].filtered.low;} inline unsigned char& mid(int i) { return m_data[i].filtered.mid;} inline unsigned char& high(int i) { return m_data[i].filtered.high;} inline unsigned char& all(int i) { return m_data[i].filtered.all;} - - int computeTextureSize(int getDataSize); - void setCompletion(int completion) { m_completion = completion;} + double getVisualSampleRate() const { return m_visualSampleRate; } // If stored in the database, the ID of the waveform. int m_id; - bool m_bDirty; + // AnalysisDAO needs to be able to set the waveform as clean. + mutable bool m_bDirty; QString m_version; QString m_description; - const QAtomicInt m_numChannels; - QAtomicInt m_dataSize; //m_data allocated size + // The size of the waveform data stored in m_data. Not allowed to change + // after the constructor runs. + int m_dataSize; + // The vector storing the waveform data. It is potentially larger than + // m_dataSize since it includes padding for uploading the entire waveform as + // a texture in the GLSL renderer. The size is not allowed to change after + // the constructor runs. We use a std::vector to avoid the cost of bounds + // checking when accessing the vector. + // TODO(XXX): In the future we should switch to QVector and use the raw data + // pointer when performance matters. std::vector m_data; + // Not allowed to change after the constructor runs. double m_visualSampleRate; + // Not allowed to change after the constructor runs. double m_audioVisualRatio; - //No need to store the following members they can be recomputed - //on waveform loading - + // We create an NxN texture out of m_data's buffer in the GLSL renderer. The + // stride is N. Not allowed to change after the constructor runs. int m_textureStride; - QAtomicInt m_completion; - mutable QMutex* m_mutex; + // For performance, completion is shared as a QAtomicInt and does not lock + // the mutex. The completion of the waveform calculation. + QAtomicInt m_completion; - friend class AnalyserWaveform; - friend class WaveformStride; + mutable QMutex m_mutex; DISALLOW_COPY_AND_ASSIGN(Waveform); }; +typedef QSharedPointer WaveformPointer; +typedef QSharedPointer ConstWaveformPointer; + #endif // WAVEFORM_H diff --git a/src/waveform/waveformfactory.cpp b/src/waveform/waveformfactory.cpp index 06bd893924b..2c29ae8f678 100644 --- a/src/waveform/waveformfactory.cpp +++ b/src/waveform/waveformfactory.cpp @@ -4,17 +4,13 @@ #include "waveform/waveform.h" // static -bool WaveformFactory::updateWaveformFromAnalysis( - Waveform* pWaveform, const AnalysisDao::AnalysisInfo& analysis) { - if (pWaveform) { - pWaveform->reset(); - pWaveform->readByteArray(analysis.data); - pWaveform->setId(analysis.analysisId); - pWaveform->setVersion(analysis.version); - pWaveform->setDescription(analysis.description); - return true; - } - return false; +Waveform* WaveformFactory::loadWaveformFromAnalysis( + const AnalysisDao::AnalysisInfo& analysis) { + Waveform* pWaveform = new Waveform(analysis.data); + pWaveform->setId(analysis.analysisId); + pWaveform->setVersion(analysis.version); + pWaveform->setDescription(analysis.description); + return pWaveform; } // static diff --git a/src/waveform/waveformfactory.h b/src/waveform/waveformfactory.h index 464c5a16436..45ff7108a80 100644 --- a/src/waveform/waveformfactory.h +++ b/src/waveform/waveformfactory.h @@ -31,8 +31,8 @@ class WaveformFactory { VC_REMOVE }; - static bool updateWaveformFromAnalysis( - Waveform* pWaveform, const AnalysisDao::AnalysisInfo& analysis); + static Waveform* loadWaveformFromAnalysis( + const AnalysisDao::AnalysisInfo& analysis); static VersionClass waveformVersionToVersionClass(const QString& version); static VersionClass waveformSummaryVersionToVersionClass(const QString& version); static QString currentWaveformVersion(); diff --git a/src/widget/woverview.cpp b/src/widget/woverview.cpp index 1eabb61d2dd..186621671a4 100644 --- a/src/widget/woverview.cpp +++ b/src/widget/woverview.cpp @@ -35,7 +35,6 @@ WOverview::WOverview(const char *pGroup, ConfigObject* pConfig, QWidget* parent) : WWidget(parent), - m_pWaveform(NULL), m_pWaveformSourceImage(NULL), m_actualCompletion(0), m_pixmapDone(false), @@ -158,10 +157,11 @@ void WOverview::onConnectedControlChanged(double dParameter, double dValue) { } void WOverview::slotWaveformSummaryUpdated() { - if (!m_pCurrentTrack) { + TrackPointer pTrack(m_pCurrentTrack); + if (!pTrack) { return; } - m_pWaveform = m_pCurrentTrack->getWaveformSummary(); + m_pWaveform = pTrack->getWaveformSummary(); // If the waveform is already complete, just draw it. if (m_pWaveform && m_pWaveform->getCompletion() == m_pWaveform->getDataSize()) { m_actualCompletion = 0; @@ -236,7 +236,7 @@ void WOverview::slotUnloadTrack(TrackPointer /*pTrack*/) { this, SLOT(slotAnalyserProgress(int))); } m_pCurrentTrack.clear(); - m_pWaveform = NULL; + m_pWaveform.clear(); m_actualCompletion = 0; m_waveformPeak = -1.0; m_pixmapDone = false; diff --git a/src/widget/woverview.h b/src/widget/woverview.h index a1db61d7ad1..44b11cdd198 100644 --- a/src/widget/woverview.h +++ b/src/widget/woverview.h @@ -56,7 +56,9 @@ class WOverview : public WWidget { virtual void dragEnterEvent(QDragEnterEvent* event); virtual void dropEvent(QDropEvent* event); - Waveform* m_pWaveform; + ConstWaveformPointer getWaveform() const { + return m_pWaveform; + } QImage* m_pWaveformSourceImage; QImage m_waveformImageScaled; @@ -98,9 +100,9 @@ class WOverview : public WWidget { ControlObjectThread* m_trackSamplesControl; ControlObjectThread* m_playControl; - // Current active track TrackPointer m_pCurrentTrack; + ConstWaveformPointer m_pWaveform; // True if slider is dragged. Only used when m_bEventWhileDrag is false bool m_bDrag; diff --git a/src/widget/woverviewhsv.cpp b/src/widget/woverviewhsv.cpp index 68df3512a8e..179c6bf8b8d 100644 --- a/src/widget/woverviewhsv.cpp +++ b/src/widget/woverviewhsv.cpp @@ -19,11 +19,12 @@ bool WOverviewHSV::drawNextPixmapPart() { int currentCompletion; - if (!m_pWaveform) { + ConstWaveformPointer pWaveform = getWaveform(); + if (!pWaveform) { return false; } - const int dataSize = m_pWaveform->getDataSize(); + const int dataSize = pWaveform->getDataSize(); if (dataSize == 0) { return false; } @@ -38,7 +39,7 @@ bool WOverviewHSV::drawNextPixmapPart() { } // Always multiple of 2 - const int waveformCompletion = m_pWaveform->getCompletion(); + const int waveformCompletion = pWaveform->getCompletion(); // Test if there is some new to draw (at least of pixel width) const int completionIncrement = waveformCompletion - m_actualCompletion; @@ -47,10 +48,6 @@ bool WOverviewHSV::drawNextPixmapPart() { return false; } - if (!m_pWaveform->getMutex()->tryLock()) { - return false; - } - const int nextCompletion = m_actualCompletion + completionIncrement; //qDebug() << "WOverview::drawNextPixmapPart() - nextCompletion:" @@ -79,15 +76,15 @@ bool WOverviewHSV::drawNextPixmapPart() { for (currentCompletion = m_actualCompletion; currentCompletion < nextCompletion; currentCompletion += 2) { - maxAll[0] = m_pWaveform->getAll(currentCompletion); - maxAll[1] = m_pWaveform->getAll(currentCompletion+1); + maxAll[0] = pWaveform->getAll(currentCompletion); + maxAll[1] = pWaveform->getAll(currentCompletion+1); if (maxAll[0] || maxAll[1]) { - maxLow[0] = m_pWaveform->getLow(currentCompletion); - maxLow[1] = m_pWaveform->getLow(currentCompletion+1); - maxMid[0] = m_pWaveform->getMid(currentCompletion); - maxMid[1] = m_pWaveform->getMid(currentCompletion+1); - maxHigh[0] = m_pWaveform->getHigh(currentCompletion); - maxHigh[1] = m_pWaveform->getHigh(currentCompletion+1); + maxLow[0] = pWaveform->getLow(currentCompletion); + maxLow[1] = pWaveform->getLow(currentCompletion+1); + maxMid[0] = pWaveform->getMid(currentCompletion); + maxMid[1] = pWaveform->getMid(currentCompletion+1); + maxHigh[0] = pWaveform->getHigh(currentCompletion); + maxHigh[1] = pWaveform->getHigh(currentCompletion+1); total = (maxLow[0] + maxLow[1] + maxMid[0] + maxMid[1] + maxHigh[0] + maxHigh[1]) * 1.2; @@ -115,10 +112,10 @@ bool WOverviewHSV::drawNextPixmapPart() { for (currentCompletion = m_actualCompletion; currentCompletion < nextCompletion; currentCompletion += 2) { - m_waveformPeak = math_max(m_waveformPeak, - (float)m_pWaveform->getAll(currentCompletion)); - m_waveformPeak = math_max(m_waveformPeak, - (float)m_pWaveform->getAll(currentCompletion+1)); + m_waveformPeak = math_max3( + m_waveformPeak, + static_cast(pWaveform->getAll(currentCompletion)), + static_cast(pWaveform->getAll(currentCompletion + 1))); } m_actualCompletion = nextCompletion; @@ -131,6 +128,5 @@ bool WOverviewHSV::drawNextPixmapPart() { //qDebug() << "m_waveformPeakRatio" << m_waveformPeak; } - m_pWaveform->getMutex()->unlock(); return true; } diff --git a/src/widget/woverviewlmh.cpp b/src/widget/woverviewlmh.cpp index 113944bf0c1..24984d4072d 100644 --- a/src/widget/woverviewlmh.cpp +++ b/src/widget/woverviewlmh.cpp @@ -21,11 +21,12 @@ bool WOverviewLMH::drawNextPixmapPart() { int currentCompletion; - if (!m_pWaveform) { + ConstWaveformPointer pWaveform = getWaveform(); + if (!pWaveform) { return false; } - const int dataSize = m_pWaveform->getDataSize(); + const int dataSize = pWaveform->getDataSize(); if (dataSize == 0) { return false; } @@ -40,7 +41,7 @@ bool WOverviewLMH::drawNextPixmapPart() { } // Always multiple of 2 - const int waveformCompletion = m_pWaveform->getCompletion(); + const int waveformCompletion = pWaveform->getCompletion(); // Test if there is some new to draw (at least of pixel width) const int completionIncrement = waveformCompletion - m_actualCompletion; @@ -49,10 +50,6 @@ bool WOverviewLMH::drawNextPixmapPart() { return false; } - if (!m_pWaveform->getMutex()->tryLock()) { - return false; - } - const int nextCompletion = m_actualCompletion + completionIncrement; //qDebug() << "WOverview::drawNextPixmapPart() - nextCompletion:" @@ -76,8 +73,8 @@ bool WOverviewLMH::drawNextPixmapPart() { for (currentCompletion = m_actualCompletion; currentCompletion < nextCompletion; currentCompletion += 2) { - unsigned char lowNeg = m_pWaveform->getLow(currentCompletion); - unsigned char lowPos = m_pWaveform->getLow(currentCompletion+1); + unsigned char lowNeg = pWaveform->getLow(currentCompletion); + unsigned char lowPos = pWaveform->getLow(currentCompletion+1); if (lowPos || lowNeg) { painter.setPen(lowColorPen); painter.drawLine(QPoint(currentCompletion / 2, -lowNeg), @@ -89,28 +86,28 @@ bool WOverviewLMH::drawNextPixmapPart() { currentCompletion < nextCompletion; currentCompletion += 2) { painter.setPen(midColorPen); painter.drawLine(QPoint(currentCompletion / 2, - -m_pWaveform->getMid(currentCompletion)), + -pWaveform->getMid(currentCompletion)), QPoint(currentCompletion / 2, - m_pWaveform->getMid(currentCompletion+1))); + pWaveform->getMid(currentCompletion+1))); } for (currentCompletion = m_actualCompletion; currentCompletion < nextCompletion; currentCompletion += 2) { painter.setPen(highColorPen); painter.drawLine(QPoint(currentCompletion / 2, - -m_pWaveform->getHigh(currentCompletion)), + -pWaveform->getHigh(currentCompletion)), QPoint(currentCompletion / 2, - m_pWaveform->getHigh(currentCompletion+1))); + pWaveform->getHigh(currentCompletion+1))); } // Evaluate waveform ratio peak for (currentCompletion = m_actualCompletion; currentCompletion < nextCompletion; currentCompletion += 2) { - m_waveformPeak = math_max(m_waveformPeak, - (float)m_pWaveform->getAll(currentCompletion)); - m_waveformPeak = math_max(m_waveformPeak, - (float)m_pWaveform->getAll(currentCompletion+1)); + m_waveformPeak = math_max3( + m_waveformPeak, + static_cast(pWaveform->getAll(currentCompletion)), + static_cast(pWaveform->getAll(currentCompletion + 1))); } m_actualCompletion = nextCompletion; @@ -123,6 +120,5 @@ bool WOverviewLMH::drawNextPixmapPart() { //qDebug() << "m_waveformPeakRatio" << m_waveformPeak; } - m_pWaveform->getMutex()->unlock(); return true; } diff --git a/src/widget/woverviewrgb.cpp b/src/widget/woverviewrgb.cpp index 4c95f5d1d25..cf38b93903e 100644 --- a/src/widget/woverviewrgb.cpp +++ b/src/widget/woverviewrgb.cpp @@ -18,11 +18,12 @@ bool WOverviewRGB::drawNextPixmapPart() { int currentCompletion; - if (!m_pWaveform) { + ConstWaveformPointer pWaveform = getWaveform(); + if (!pWaveform) { return false; } - const int dataSize = m_pWaveform->getDataSize(); + const int dataSize = pWaveform->getDataSize(); if (dataSize == 0) { return false; } @@ -37,7 +38,7 @@ bool WOverviewRGB::drawNextPixmapPart() { } // Always multiple of 2 - const int waveformCompletion = m_pWaveform->getCompletion(); + const int waveformCompletion = pWaveform->getCompletion(); // Test if there is some new to draw (at least of pixel width) const int completionIncrement = waveformCompletion - m_actualCompletion; @@ -46,10 +47,6 @@ bool WOverviewRGB::drawNextPixmapPart() { return false; } - if (!m_pWaveform->getMutex()->tryLock()) { - return false; - } - const int nextCompletion = m_actualCompletion + completionIncrement; //qDebug() << "WOverview::drawNextPixmapPart() - nextCompletion:" @@ -71,12 +68,12 @@ bool WOverviewRGB::drawNextPixmapPart() { for (currentCompletion = m_actualCompletion; currentCompletion < nextCompletion; currentCompletion += 2) { - unsigned char left = m_pWaveform->getAll(currentCompletion); - unsigned char right = m_pWaveform->getAll(currentCompletion + 1); + unsigned char left = pWaveform->getAll(currentCompletion); + unsigned char right = pWaveform->getAll(currentCompletion + 1); - low = m_pWaveform->getLow(currentCompletion); - mid = m_pWaveform->getMid(currentCompletion); - high = m_pWaveform->getHigh(currentCompletion); + low = pWaveform->getLow(currentCompletion); + mid = pWaveform->getMid(currentCompletion); + high = pWaveform->getHigh(currentCompletion); max = (float) math_max3(low, mid, high); if (max > 0.0f) { @@ -85,9 +82,9 @@ bool WOverviewRGB::drawNextPixmapPart() { painter.drawLine(currentCompletion / 2, -left, currentCompletion / 2, 0); } - low = m_pWaveform->getLow(currentCompletion + 1); - mid = m_pWaveform->getMid(currentCompletion + 1); - high = m_pWaveform->getHigh(currentCompletion + 1); + low = pWaveform->getLow(currentCompletion + 1); + mid = pWaveform->getMid(currentCompletion + 1); + high = pWaveform->getHigh(currentCompletion + 1); max = (float) math_max3(low, mid, high); if (max > 0.0f) { @@ -100,10 +97,10 @@ bool WOverviewRGB::drawNextPixmapPart() { // Evaluate waveform ratio peak for (currentCompletion = m_actualCompletion; currentCompletion < nextCompletion; currentCompletion += 2) { - m_waveformPeak = math_max(m_waveformPeak, - (float)m_pWaveform->getAll(currentCompletion)); - m_waveformPeak = math_max(m_waveformPeak, - (float)m_pWaveform->getAll(currentCompletion+1)); + m_waveformPeak = math_max3( + m_waveformPeak, + static_cast(pWaveform->getAll(currentCompletion)), + static_cast(pWaveform->getAll(currentCompletion + 1))); } m_actualCompletion = nextCompletion; @@ -116,6 +113,5 @@ bool WOverviewRGB::drawNextPixmapPart() { //qDebug() << "m_waveformPeakRatio" << m_waveformPeak; } - m_pWaveform->getMutex()->unlock(); return true; }