comparison audio/AudioCallbackPlaySource.cpp @ 506:39e94df71d24 3.0-integration

Remake SR converter when adding a model, if necessary; remove crap converter to simplify
author Chris Cannam
date Wed, 14 Oct 2015 13:34:46 +0100
parents cd9dec2f47e8
children 7cf6f5501212
comparison
equal deleted inserted replaced
505:ce6917c761a3 506:39e94df71d24
21 #include "base/ViewManagerBase.h" 21 #include "base/ViewManagerBase.h"
22 #include "base/PlayParameterRepository.h" 22 #include "base/PlayParameterRepository.h"
23 #include "base/Preferences.h" 23 #include "base/Preferences.h"
24 #include "data/model/DenseTimeValueModel.h" 24 #include "data/model/DenseTimeValueModel.h"
25 #include "data/model/WaveFileModel.h" 25 #include "data/model/WaveFileModel.h"
26 #include "data/model/ReadOnlyWaveFileModel.h"
26 #include "data/model/SparseOneDimensionalModel.h" 27 #include "data/model/SparseOneDimensionalModel.h"
27 #include "plugin/RealTimePluginInstance.h" 28 #include "plugin/RealTimePluginInstance.h"
28 29
29 #include "bqaudioio/SystemPlaybackTarget.h" 30 #include "bqaudioio/SystemPlaybackTarget.h"
30 31
32 using namespace RubberBand; 33 using namespace RubberBand;
33 34
34 #include <iostream> 35 #include <iostream>
35 #include <cassert> 36 #include <cassert>
36 37
37 //#define DEBUG_AUDIO_PLAY_SOURCE 1 38 #define DEBUG_AUDIO_PLAY_SOURCE 1
38 //#define DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1 39 //#define DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1
39 40
40 static const int DEFAULT_RING_BUFFER_SIZE = 131071; 41 static const int DEFAULT_RING_BUFFER_SIZE = 131071;
41 42
42 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManagerBase *manager, 43 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManagerBase *manager,
76 m_stretcherInputCount(0), 77 m_stretcherInputCount(0),
77 m_stretcherInputs(0), 78 m_stretcherInputs(0),
78 m_stretcherInputSizes(0), 79 m_stretcherInputSizes(0),
79 m_fillThread(0), 80 m_fillThread(0),
80 m_converter(0), 81 m_converter(0),
81 m_crapConverter(0),
82 m_resampleQuality(Preferences::getInstance()->getResampleQuality()) 82 m_resampleQuality(Preferences::getInstance()->getResampleQuality())
83 { 83 {
84 m_viewManager->setAudioPlaySource(this); 84 m_viewManager->setAudioPlaySource(this);
85 85
86 connect(m_viewManager, SIGNAL(selectionChanged()), 86 connect(m_viewManager, SIGNAL(selectionChanged()),
159 } 159 }
160 160
161 bool buffersChanged = false, srChanged = false; 161 bool buffersChanged = false, srChanged = false;
162 162
163 int modelChannels = 1; 163 int modelChannels = 1;
164 DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model); 164 ReadOnlyWaveFileModel *rowfm = qobject_cast<ReadOnlyWaveFileModel *>(model);
165 if (dtvm) modelChannels = dtvm->getChannelCount(); 165 if (rowfm) modelChannels = rowfm->getChannelCount();
166 if (modelChannels > m_sourceChannelCount) { 166 if (modelChannels > m_sourceChannelCount) {
167 m_sourceChannelCount = modelChannels; 167 m_sourceChannelCount = modelChannels;
168 } 168 }
169 169
170 #ifdef DEBUG_AUDIO_PLAY_SOURCE 170 #ifdef DEBUG_AUDIO_PLAY_SOURCE
176 m_sourceSampleRate = model->getSampleRate(); 176 m_sourceSampleRate = model->getSampleRate();
177 srChanged = true; 177 srChanged = true;
178 178
179 } else if (model->getSampleRate() != m_sourceSampleRate) { 179 } else if (model->getSampleRate() != m_sourceSampleRate) {
180 180
181 // If this is a dense time-value model and we have no other, we 181 // If this is a read-only wave file model and we have no
182 // can just switch to this model's sample rate 182 // other, we can just switch to this model's sample rate
183 183
184 if (dtvm) { 184 if (rowfm) {
185 185
186 bool conflicting = false; 186 bool conflicting = false;
187 187
188 for (std::set<Model *>::const_iterator i = m_models.begin(); 188 for (std::set<Model *>::const_iterator i = m_models.begin();
189 i != m_models.end(); ++i) { 189 i != m_models.end(); ++i) {
190 // Only wave file models can be considered conflicting -- 190 // Only read-only wave file models should be
191 // writable wave file models are derived and we shouldn't 191 // considered conflicting -- writable wave file models
192 // take their rates into account. Also, don't give any 192 // are derived and we shouldn't take their rates into
193 // particular weight to a file that's already playing at 193 // account. Also, don't give any particular weight to
194 // the wrong rate anyway 194 // a file that's already playing at the wrong rate
195 WaveFileModel *wfm = dynamic_cast<WaveFileModel *>(*i); 195 // anyway
196 if (wfm && wfm != dtvm && 196 ReadOnlyWaveFileModel *other =
197 wfm->getSampleRate() != model->getSampleRate() && 197 qobject_cast<ReadOnlyWaveFileModel *>(*i);
198 wfm->getSampleRate() == m_sourceSampleRate) { 198 if (other && other != rowfm &&
199 other->getSampleRate() != model->getSampleRate() &&
200 other->getSampleRate() == m_sourceSampleRate) {
199 SVDEBUG << "AudioCallbackPlaySource::addModel: Conflicting wave file model " << *i << " found" << endl; 201 SVDEBUG << "AudioCallbackPlaySource::addModel: Conflicting wave file model " << *i << " found" << endl;
200 conflicting = true; 202 conflicting = true;
201 break; 203 break;
202 } 204 }
203 } 205 }
228 if (willPlay) clearRingBuffers(true); 230 if (willPlay) clearRingBuffers(true);
229 } 231 }
230 232
231 if (buffersChanged || srChanged) { 233 if (buffersChanged || srChanged) {
232 if (m_converter) { 234 if (m_converter) {
235 #ifdef DEBUG_AUDIO_PLAY_SOURCE
236 cerr << "AudioCallbackPlaySource::addModel: Buffers or sample rate changed, deleting existing SR converter" << endl;
237 #endif
233 src_delete(m_converter); 238 src_delete(m_converter);
234 src_delete(m_crapConverter);
235 m_converter = 0; 239 m_converter = 0;
236 m_crapConverter = 0;
237 } 240 }
238 } 241 }
239 242
240 rebuildRangeLists(); 243 rebuildRangeLists();
241 244
242 m_mutex.unlock(); 245 m_mutex.unlock();
243 246
247 initialiseConverter();
248
244 m_audioGenerator->setTargetChannelCount(getTargetChannelCount()); 249 m_audioGenerator->setTargetChannelCount(getTargetChannelCount());
245 250
246 if (!m_fillThread) { 251 if (!m_fillThread) {
247 m_fillThread = new FillThread(*this); 252 m_fillThread = new FillThread(*this);
248 m_fillThread->start(); 253 m_fillThread->start();
296 301
297 m_models.erase(model); 302 m_models.erase(model);
298 303
299 if (m_models.empty()) { 304 if (m_models.empty()) {
300 if (m_converter) { 305 if (m_converter) {
306 #ifdef DEBUG_AUDIO_PLAY_SOURCE
307 cerr << "AudioCallbackPlaySource::removeModel: No models left, deleting SR converter" << endl;
308 #endif
301 src_delete(m_converter); 309 src_delete(m_converter);
302 src_delete(m_crapConverter);
303 m_converter = 0; 310 m_converter = 0;
304 m_crapConverter = 0;
305 } 311 }
306 m_sourceSampleRate = 0; 312 m_sourceSampleRate = 0;
307 } 313 }
308 314
309 sv_frame_t lastEnd = 0; 315 sv_frame_t lastEnd = 0;
338 #endif 344 #endif
339 345
340 m_models.clear(); 346 m_models.clear();
341 347
342 if (m_converter) { 348 if (m_converter) {
349 #ifdef DEBUG_AUDIO_PLAY_SOURCE
350 cerr << "AudioCallbackPlaySource::clearModels: Deleting SR converter" << endl;
351 #endif
343 src_delete(m_converter); 352 src_delete(m_converter);
344 src_delete(m_crapConverter);
345 m_converter = 0; 353 m_converter = 0;
346 m_crapConverter = 0;
347 } 354 }
348 355
349 m_lastModelEndFrame = 0; 356 m_lastModelEndFrame = 0;
350 357
351 m_sourceSampleRate = 0; 358 m_sourceSampleRate = 0;
465 #endif 472 #endif
466 if (rb) rb->reset(); 473 if (rb) rb->reset();
467 } 474 }
468 } 475 }
469 if (m_converter) src_reset(m_converter); 476 if (m_converter) src_reset(m_converter);
470 if (m_crapConverter) src_reset(m_crapConverter);
471 477
472 m_mutex.unlock(); 478 m_mutex.unlock();
473 479
474 m_audioGenerator->reset(); 480 m_audioGenerator->reset();
475 481
957 void 963 void
958 AudioCallbackPlaySource::initialiseConverter() 964 AudioCallbackPlaySource::initialiseConverter()
959 { 965 {
960 m_mutex.lock(); 966 m_mutex.lock();
961 967
968 #ifdef DEBUG_AUDIO_PLAY_SOURCE
969 cerr << "AudioCallbackPlaySource::initialiseConverter(): from "
970 << getSourceSampleRate() << " to " << getTargetSampleRate() << endl;
971 #endif
972
962 if (m_converter) { 973 if (m_converter) {
963 src_delete(m_converter); 974 src_delete(m_converter);
964 src_delete(m_crapConverter);
965 m_converter = 0; 975 m_converter = 0;
966 m_crapConverter = 0;
967 } 976 }
968 977
969 if (getSourceSampleRate() != getTargetSampleRate()) { 978 if (getSourceSampleRate() != getTargetSampleRate()) {
970 979
971 int err = 0; 980 int err = 0;
974 m_resampleQuality == 1 ? SRC_SINC_MEDIUM_QUALITY : 983 m_resampleQuality == 1 ? SRC_SINC_MEDIUM_QUALITY :
975 m_resampleQuality == 0 ? SRC_SINC_FASTEST : 984 m_resampleQuality == 0 ? SRC_SINC_FASTEST :
976 SRC_SINC_MEDIUM_QUALITY, 985 SRC_SINC_MEDIUM_QUALITY,
977 getTargetChannelCount(), &err); 986 getTargetChannelCount(), &err);
978 987
979 if (m_converter) { 988 if (!m_converter) {
980 m_crapConverter = src_new(SRC_LINEAR, 989 cerr << "AudioCallbackPlaySource::setModel: ERROR in creating samplerate converter: "
981 getTargetChannelCount(), 990 << src_strerror(err) << endl;
982 &err);
983 }
984
985 if (!m_converter || !m_crapConverter) {
986 cerr
987 << "AudioCallbackPlaySource::setModel: ERROR in creating samplerate converter: "
988 << src_strerror(err) << endl;
989
990 if (m_converter) {
991 src_delete(m_converter);
992 m_converter = 0;
993 }
994
995 if (m_crapConverter) {
996 src_delete(m_crapConverter);
997 m_crapConverter = 0;
998 }
999 991
1000 m_mutex.unlock(); 992 m_mutex.unlock();
1001 993
1002 emit sampleRateMismatch(getSourceSampleRate(), 994 emit sampleRateMismatch(getSourceSampleRate(),
1003 getTargetSampleRate(), 995 getTargetSampleRate(),
1433 } 1425 }
1434 1426
1435 sv_frame_t generatorBlockSize = m_audioGenerator->getBlockSize(); 1427 sv_frame_t generatorBlockSize = m_audioGenerator->getBlockSize();
1436 1428
1437 if (resample && !m_converter) { 1429 if (resample && !m_converter) {
1438 static bool warned = false; 1430 throw std::logic_error("Sample rates differ, but no converter available!");
1439 if (!warned) {
1440 cerr << "WARNING: sample rates differ, but no converter available!" << endl;
1441 warned = true;
1442 }
1443 } 1431 }
1444 1432
1445 if (resample && m_converter) { 1433 if (resample && m_converter) {
1446 1434
1447 double ratio = 1435 double ratio =
1501 data.input_frames = long(got); 1489 data.input_frames = long(got);
1502 data.output_frames = long(work); 1490 data.output_frames = long(work);
1503 data.src_ratio = ratio; 1491 data.src_ratio = ratio;
1504 data.end_of_input = 0; 1492 data.end_of_input = 0;
1505 1493
1506 int err = 0; 1494 int err = src_process(m_converter, &data);
1507
1508 if (m_timeStretcher && m_timeStretcher->getTimeRatio() < 0.4) {
1509 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1510 cout << "Using crappy converter" << endl;
1511 #endif
1512 err = src_process(m_crapConverter, &data);
1513 } else {
1514 err = src_process(m_converter, &data);
1515 }
1516 1495
1517 sv_frame_t toCopy = sv_frame_t(double(got) * ratio + 0.1); 1496 sv_frame_t toCopy = sv_frame_t(double(got) * ratio + 0.1);
1518 1497
1519 if (err) { 1498 if (err) {
1520 cerr 1499 cerr