Mercurial > hg > svapp
diff audio/AudioCallbackPlaySource.cpp @ 548:baa11365ebdd bqaudioio
Merge from branch bqresample
author | Chris Cannam |
---|---|
date | Wed, 07 Dec 2016 11:51:42 +0000 |
parents | c4391f6c7484 |
children | c732251237b1 |
line wrap: on
line diff
--- a/audio/AudioCallbackPlaySource.cpp Wed Dec 07 11:50:54 2016 +0000 +++ b/audio/AudioCallbackPlaySource.cpp Wed Dec 07 11:51:42 2016 +0000 @@ -23,6 +23,7 @@ #include "base/Preferences.h" #include "data/model/DenseTimeValueModel.h" #include "data/model/WaveFileModel.h" +#include "data/model/ReadOnlyWaveFileModel.h" #include "data/model/SparseOneDimensionalModel.h" #include "plugin/RealTimePluginInstance.h" @@ -77,9 +78,7 @@ m_stretcherInputs(0), m_stretcherInputSizes(0), m_fillThread(0), - m_converter(0), - m_crapConverter(0), - m_resampleQuality(Preferences::getInstance()->getResampleQuality()) + m_resampler(0) { m_viewManager->setAudioPlaySource(this); @@ -161,8 +160,8 @@ bool buffersChanged = false, srChanged = false; int modelChannels = 1; - DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model); - if (dtvm) modelChannels = dtvm->getChannelCount(); + ReadOnlyWaveFileModel *rowfm = qobject_cast<ReadOnlyWaveFileModel *>(model); + if (rowfm) modelChannels = rowfm->getChannelCount(); if (modelChannels > m_sourceChannelCount) { m_sourceChannelCount = modelChannels; } @@ -178,24 +177,26 @@ } else if (model->getSampleRate() != m_sourceSampleRate) { - // If this is a dense time-value model and we have no other, we - // can just switch to this model's sample rate + // If this is a read-only wave file model and we have no + // other, we can just switch to this model's sample rate - if (dtvm) { + if (rowfm) { bool conflicting = false; for (std::set<Model *>::const_iterator i = m_models.begin(); i != m_models.end(); ++i) { - // Only wave file models can be considered conflicting -- - // writable wave file models are derived and we shouldn't - // take their rates into account. Also, don't give any - // particular weight to a file that's already playing at - // the wrong rate anyway - WaveFileModel *wfm = dynamic_cast<WaveFileModel *>(*i); - if (wfm && wfm != dtvm && - wfm->getSampleRate() != model->getSampleRate() && - wfm->getSampleRate() == m_sourceSampleRate) { + // Only read-only wave file models should be + // considered conflicting -- writable wave file models + // are derived and we shouldn't take their rates into + // account. Also, don't give any particular weight to + // a file that's already playing at the wrong rate + // anyway + ReadOnlyWaveFileModel *other = + qobject_cast<ReadOnlyWaveFileModel *>(*i); + if (other && other != rowfm && + other->getSampleRate() != model->getSampleRate() && + other->getSampleRate() == m_sourceSampleRate) { SVDEBUG << "AudioCallbackPlaySource::addModel: Conflicting wave file model " << *i << " found" << endl; conflicting = true; break; @@ -229,11 +230,12 @@ } if (buffersChanged || srChanged) { - if (m_converter) { - src_delete(m_converter); - src_delete(m_crapConverter); - m_converter = 0; - m_crapConverter = 0; + if (m_resampler) { +#ifdef DEBUG_AUDIO_PLAY_SOURCE + cerr << "AudioCallbackPlaySource::addModel: Buffers or sample rate changed, deleting existing resampler" << endl; +#endif + delete m_resampler; + m_resampler = 0; } } @@ -241,6 +243,8 @@ m_mutex.unlock(); + initialiseResampler(); + m_audioGenerator->setTargetChannelCount(getTargetChannelCount()); if (!m_fillThread) { @@ -297,11 +301,12 @@ m_models.erase(model); if (m_models.empty()) { - if (m_converter) { - src_delete(m_converter); - src_delete(m_crapConverter); - m_converter = 0; - m_crapConverter = 0; + if (m_resampler) { +#ifdef DEBUG_AUDIO_PLAY_SOURCE + cerr << "AudioCallbackPlaySource::removeModel: No models left, deleting resampler" << endl; +#endif + delete m_resampler; + m_resampler = 0; } m_sourceSampleRate = 0; } @@ -339,11 +344,12 @@ m_models.clear(); - if (m_converter) { - src_delete(m_converter); - src_delete(m_crapConverter); - m_converter = 0; - m_crapConverter = 0; + if (m_resampler) { +#ifdef DEBUG_AUDIO_PLAY_SOURCE + cerr << "AudioCallbackPlaySource::clearModels: Deleting resampler" << endl; +#endif + delete m_resampler; + m_resampler = 0; } m_lastModelEndFrame = 0; @@ -407,6 +413,8 @@ void AudioCallbackPlaySource::play(sv_frame_t startFrame) { + if (!m_target) return; + if (!m_sourceSampleRate) { cerr << "AudioCallbackPlaySource::play: No source sample rate available, not playing" << endl; return; @@ -464,8 +472,9 @@ if (rb) rb->reset(); } } - if (m_converter) src_reset(m_converter); - if (m_crapConverter) src_reset(m_crapConverter); + if (m_resampler) { + m_resampler->reset(); + } m_mutex.unlock(); @@ -551,9 +560,6 @@ void AudioCallbackPlaySource::preferenceChanged(PropertyContainer::PropertyName n) { - if (n == "Resample Quality") { - setResampleQuality(Preferences::getInstance()->getResampleQuality()); - } } void @@ -941,7 +947,7 @@ bool first = (m_targetSampleRate == 0); m_targetSampleRate = sr; - initialiseConverter(); + initialiseResampler(); if (first && (m_stretchRatio != 1.f)) { // couldn't create a stretcher before because we had no sample @@ -951,81 +957,37 @@ } void -AudioCallbackPlaySource::initialiseConverter() +AudioCallbackPlaySource::initialiseResampler() { m_mutex.lock(); - if (m_converter) { - src_delete(m_converter); - src_delete(m_crapConverter); - m_converter = 0; - m_crapConverter = 0; +#ifdef DEBUG_AUDIO_PLAY_SOURCE + cerr << "AudioCallbackPlaySource::initialiseResampler(): from " + << getSourceSampleRate() << " to " << getTargetSampleRate() << endl; +#endif + + if (m_resampler) { + delete m_resampler; + m_resampler = 0; } if (getSourceSampleRate() != getTargetSampleRate()) { - int err = 0; + m_resampler = new breakfastquay::Resampler + (breakfastquay::Resampler::FastestTolerable, + getTargetChannelCount()); - 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); + m_mutex.unlock(); - if (m_converter) { - m_crapConverter = src_new(SRC_LINEAR, - getTargetChannelCount(), - &err); - } - - if (!m_converter || !m_crapConverter) { - cerr - << "AudioCallbackPlaySource::setModel: ERROR in creating samplerate converter: " - << src_strerror(err) << 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); - } + 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 - SVDEBUG << "AudioCallbackPlaySource::setResampleQuality: setting to " - << m_resampleQuality << endl; -#endif - - initialiseConverter(); -} - -void AudioCallbackPlaySource::setAuditioningEffect(Auditionable *a) { RealTimePluginInstance *plugin = dynamic_cast<RealTimePluginInstance *>(a); @@ -1393,6 +1355,9 @@ return false; } + // space is now the number of samples that can be written on each + // channel's write ringbuffer + sv_frame_t f = m_writeBufferFill; bool readWriteEqual = (m_readBuffers == m_writeBuffers); @@ -1430,15 +1395,11 @@ sv_frame_t generatorBlockSize = m_audioGenerator->getBlockSize(); - if (resample && !m_converter) { - static bool warned = false; - if (!warned) { - cerr << "WARNING: sample rates differ, but no converter available!" << endl; - warned = true; - } + if (resample && !m_resampler) { + throw std::logic_error("Sample rates differ, but no resampler available!"); } - if (resample && m_converter) { + if (resample && m_resampler) { double ratio = double(getTargetSampleRate()) / double(getSourceSampleRate()); @@ -1490,7 +1451,10 @@ intlv[channels * i + c] = sample; } } - + + sv_frame_t toCopy = m_resampler->resampleInterleaved + (intlv, srcout, got, ratio, false); + SRC_DATA data; data.data_in = intlv; data.data_out = srcout; @@ -1499,16 +1463,7 @@ data.src_ratio = ratio; data.end_of_input = 0; - int err = 0; - - if (m_timeStretcher && m_timeStretcher->getTimeRatio() < 0.4) { -#ifdef DEBUG_AUDIO_PLAY_SOURCE - cout << "Using crappy converter" << endl; -#endif - err = src_process(m_crapConverter, &data); - } else { - err = src_process(m_converter, &data); - } + int err = src_process(m_converter, &data); sv_frame_t toCopy = sv_frame_t(double(got) * ratio + 0.1);