Mercurial > hg > sonic-visualiser
diff audioio/AudioCallbackPlaySource.cpp @ 32:e3b32dc5180b
* Make resampler quality configurable
* Fall back to linear resampling when playing very fast
* Switch off transient detection in time stretcher when playing very very fast
author | Chris Cannam |
---|---|
date | Thu, 21 Sep 2006 11:17:19 +0000 |
parents | 37af203dbd15 |
children | fbd7a497fd89 |
line wrap: on
line diff
--- a/audioio/AudioCallbackPlaySource.cpp Thu Sep 21 09:43:41 2006 +0000 +++ b/audioio/AudioCallbackPlaySource.cpp Thu Sep 21 11:17:19 2006 +0000 @@ -20,6 +20,7 @@ #include "data/model/Model.h" #include "view/ViewManager.h" #include "base/PlayParameterRepository.h" +#include "base/Preferences.h" #include "data/model/DenseTimeValueModel.h" #include "data/model/SparseOneDimensionalModel.h" #include "PhaseVocoderTimeStretcher.h" @@ -53,7 +54,9 @@ m_outputRight(0.0), m_timeStretcher(0), m_fillThread(0), - m_converter(0) + m_converter(0), + m_crapConverter(0), + m_resampleQuality(Preferences::getInstance()->getResampleQuality()) { m_viewManager->setAudioPlaySource(this); @@ -67,6 +70,10 @@ connect(PlayParameterRepository::getInstance(), SIGNAL(playParametersChanged(PlayParameters *)), this, SLOT(playParametersChanged(PlayParameters *))); + + connect(Preferences::getInstance(), + SIGNAL(propertyChanged(PropertyContainer::PropertyName)), + this, SLOT(preferenceChanged(PropertyContainer::PropertyName))); } AudioCallbackPlaySource::~AudioCallbackPlaySource() @@ -168,7 +175,9 @@ if (buffersChanged || srChanged) { if (m_converter) { src_delete(m_converter); + src_delete(m_crapConverter); m_converter = 0; + m_crapConverter = 0; } } @@ -202,7 +211,9 @@ if (m_models.empty()) { if (m_converter) { src_delete(m_converter); + src_delete(m_crapConverter); m_converter = 0; + m_crapConverter = 0; } m_sourceSampleRate = 0; } @@ -232,7 +243,9 @@ if (m_converter) { src_delete(m_converter); + src_delete(m_crapConverter); m_converter = 0; + m_crapConverter = 0; } m_lastModelEndFrame = 0; @@ -322,8 +335,10 @@ } } if (m_converter) src_reset(m_converter); + if (m_crapConverter) src_reset(m_crapConverter); } else { if (m_converter) src_reset(m_converter); + if (m_crapConverter) src_reset(m_crapConverter); m_readBufferFill = m_writeBufferFill = startFrame; } m_mutex.unlock(); @@ -374,6 +389,14 @@ } void +AudioCallbackPlaySource::preferenceChanged(PropertyContainer::PropertyName n) +{ + if (n == "Resample Quality") { + setResampleQuality(Preferences::getInstance()->getResampleQuality()); + } +} + +void AudioCallbackPlaySource::setTargetBlockSize(size_t size) { // std::cerr << "AudioCallbackPlaySource::setTargetBlockSize() -> " << size << std::endl; @@ -538,29 +561,84 @@ AudioCallbackPlaySource::setTargetSampleRate(size_t sr) { m_targetSampleRate = sr; + initialiseConverter(); +} + +void +AudioCallbackPlaySource::initialiseConverter() +{ + m_mutex.lock(); + + if (m_converter) { + src_delete(m_converter); + src_delete(m_crapConverter); + m_converter = 0; + m_crapConverter = 0; + } if (getSourceSampleRate() != getTargetSampleRate()) { int err = 0; - m_converter = src_new(SRC_SINC_BEST_QUALITY, + + m_converter = src_new(m_resampleQuality == 2 ? SRC_SINC_BEST_QUALITY : + m_resampleQuality == 1 ? SRC_SINC_MEDIUM_QUALITY : + m_resampleQuality == 0 ? SRC_SINC_FASTEST : + SRC_SINC_MEDIUM_QUALITY, getTargetChannelCount(), &err); - if (!m_converter) { + + if (m_converter) { + m_crapConverter = src_new(SRC_LINEAR, + getTargetChannelCount(), + &err); + } + + if (!m_converter || !m_crapConverter) { std::cerr << "AudioCallbackPlaySource::setModel: ERROR in creating samplerate converter: " << src_strerror(err) << std::endl; + if (m_converter) { + src_delete(m_converter); + m_converter = 0; + } + + if (m_crapConverter) { + src_delete(m_crapConverter); + m_crapConverter = 0; + } + + m_mutex.unlock(); + emit sampleRateMismatch(getSourceSampleRate(), getTargetSampleRate(), false); } else { + m_mutex.unlock(); + emit sampleRateMismatch(getSourceSampleRate(), getTargetSampleRate(), true); } + } else { + m_mutex.unlock(); } } +void +AudioCallbackPlaySource::setResampleQuality(int q) +{ + if (q == m_resampleQuality) return; + m_resampleQuality = q; + +#ifdef DEBUG_AUDIO_PLAY_SOURCE + std::cerr << "AudioCallbackPlaySource::setResampleQuality: setting to " + << m_resampleQuality << std::endl; +#endif + + initialiseConverter(); +} + size_t AudioCallbackPlaySource::getTargetSampleRate() const { @@ -894,8 +972,17 @@ data.src_ratio = ratio; data.end_of_input = 0; - int err = src_process(m_converter, &data); -// size_t toCopy = size_t(work * ratio + 0.1); + int err = 0; + + if (m_timeStretcher && m_timeStretcher->getRatio() < 0.4) { +#ifdef DEBUG_AUDIO_PLAY_SOURCE + std::cerr << "Using crappy converter" << std::endl; +#endif + src_process(m_crapConverter, &data); + } else { + src_process(m_converter, &data); + } + size_t toCopy = size_t(got * ratio + 0.1); if (err) {