comparison 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
comparison
equal deleted inserted replaced
547:82d7e5cf7517 548:baa11365ebdd
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
75 m_stretchMono(false), 76 m_stretchMono(false),
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_resampler(0)
81 m_crapConverter(0),
82 m_resampleQuality(Preferences::getInstance()->getResampleQuality())
83 { 82 {
84 m_viewManager->setAudioPlaySource(this); 83 m_viewManager->setAudioPlaySource(this);
85 84
86 connect(m_viewManager, SIGNAL(selectionChanged()), 85 connect(m_viewManager, SIGNAL(selectionChanged()),
87 this, SLOT(selectionChanged())); 86 this, SLOT(selectionChanged()));
159 } 158 }
160 159
161 bool buffersChanged = false, srChanged = false; 160 bool buffersChanged = false, srChanged = false;
162 161
163 int modelChannels = 1; 162 int modelChannels = 1;
164 DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model); 163 ReadOnlyWaveFileModel *rowfm = qobject_cast<ReadOnlyWaveFileModel *>(model);
165 if (dtvm) modelChannels = dtvm->getChannelCount(); 164 if (rowfm) modelChannels = rowfm->getChannelCount();
166 if (modelChannels > m_sourceChannelCount) { 165 if (modelChannels > m_sourceChannelCount) {
167 m_sourceChannelCount = modelChannels; 166 m_sourceChannelCount = modelChannels;
168 } 167 }
169 168
170 #ifdef DEBUG_AUDIO_PLAY_SOURCE 169 #ifdef DEBUG_AUDIO_PLAY_SOURCE
176 m_sourceSampleRate = model->getSampleRate(); 175 m_sourceSampleRate = model->getSampleRate();
177 srChanged = true; 176 srChanged = true;
178 177
179 } else if (model->getSampleRate() != m_sourceSampleRate) { 178 } else if (model->getSampleRate() != m_sourceSampleRate) {
180 179
181 // If this is a dense time-value model and we have no other, we 180 // If this is a read-only wave file model and we have no
182 // can just switch to this model's sample rate 181 // other, we can just switch to this model's sample rate
183 182
184 if (dtvm) { 183 if (rowfm) {
185 184
186 bool conflicting = false; 185 bool conflicting = false;
187 186
188 for (std::set<Model *>::const_iterator i = m_models.begin(); 187 for (std::set<Model *>::const_iterator i = m_models.begin();
189 i != m_models.end(); ++i) { 188 i != m_models.end(); ++i) {
190 // Only wave file models can be considered conflicting -- 189 // Only read-only wave file models should be
191 // writable wave file models are derived and we shouldn't 190 // considered conflicting -- writable wave file models
192 // take their rates into account. Also, don't give any 191 // are derived and we shouldn't take their rates into
193 // particular weight to a file that's already playing at 192 // account. Also, don't give any particular weight to
194 // the wrong rate anyway 193 // a file that's already playing at the wrong rate
195 WaveFileModel *wfm = dynamic_cast<WaveFileModel *>(*i); 194 // anyway
196 if (wfm && wfm != dtvm && 195 ReadOnlyWaveFileModel *other =
197 wfm->getSampleRate() != model->getSampleRate() && 196 qobject_cast<ReadOnlyWaveFileModel *>(*i);
198 wfm->getSampleRate() == m_sourceSampleRate) { 197 if (other && other != rowfm &&
198 other->getSampleRate() != model->getSampleRate() &&
199 other->getSampleRate() == m_sourceSampleRate) {
199 SVDEBUG << "AudioCallbackPlaySource::addModel: Conflicting wave file model " << *i << " found" << endl; 200 SVDEBUG << "AudioCallbackPlaySource::addModel: Conflicting wave file model " << *i << " found" << endl;
200 conflicting = true; 201 conflicting = true;
201 break; 202 break;
202 } 203 }
203 } 204 }
227 } else { 228 } else {
228 if (willPlay) clearRingBuffers(true); 229 if (willPlay) clearRingBuffers(true);
229 } 230 }
230 231
231 if (buffersChanged || srChanged) { 232 if (buffersChanged || srChanged) {
232 if (m_converter) { 233 if (m_resampler) {
233 src_delete(m_converter); 234 #ifdef DEBUG_AUDIO_PLAY_SOURCE
234 src_delete(m_crapConverter); 235 cerr << "AudioCallbackPlaySource::addModel: Buffers or sample rate changed, deleting existing resampler" << endl;
235 m_converter = 0; 236 #endif
236 m_crapConverter = 0; 237 delete m_resampler;
238 m_resampler = 0;
237 } 239 }
238 } 240 }
239 241
240 rebuildRangeLists(); 242 rebuildRangeLists();
241 243
242 m_mutex.unlock(); 244 m_mutex.unlock();
243 245
246 initialiseResampler();
247
244 m_audioGenerator->setTargetChannelCount(getTargetChannelCount()); 248 m_audioGenerator->setTargetChannelCount(getTargetChannelCount());
245 249
246 if (!m_fillThread) { 250 if (!m_fillThread) {
247 m_fillThread = new FillThread(*this); 251 m_fillThread = new FillThread(*this);
248 m_fillThread->start(); 252 m_fillThread->start();
295 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); 299 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t)));
296 300
297 m_models.erase(model); 301 m_models.erase(model);
298 302
299 if (m_models.empty()) { 303 if (m_models.empty()) {
300 if (m_converter) { 304 if (m_resampler) {
301 src_delete(m_converter); 305 #ifdef DEBUG_AUDIO_PLAY_SOURCE
302 src_delete(m_crapConverter); 306 cerr << "AudioCallbackPlaySource::removeModel: No models left, deleting resampler" << endl;
303 m_converter = 0; 307 #endif
304 m_crapConverter = 0; 308 delete m_resampler;
309 m_resampler = 0;
305 } 310 }
306 m_sourceSampleRate = 0; 311 m_sourceSampleRate = 0;
307 } 312 }
308 313
309 sv_frame_t lastEnd = 0; 314 sv_frame_t lastEnd = 0;
337 cout << "AudioCallbackPlaySource::clearModels()" << endl; 342 cout << "AudioCallbackPlaySource::clearModels()" << endl;
338 #endif 343 #endif
339 344
340 m_models.clear(); 345 m_models.clear();
341 346
342 if (m_converter) { 347 if (m_resampler) {
343 src_delete(m_converter); 348 #ifdef DEBUG_AUDIO_PLAY_SOURCE
344 src_delete(m_crapConverter); 349 cerr << "AudioCallbackPlaySource::clearModels: Deleting resampler" << endl;
345 m_converter = 0; 350 #endif
346 m_crapConverter = 0; 351 delete m_resampler;
352 m_resampler = 0;
347 } 353 }
348 354
349 m_lastModelEndFrame = 0; 355 m_lastModelEndFrame = 0;
350 356
351 m_sourceSampleRate = 0; 357 m_sourceSampleRate = 0;
405 } 411 }
406 412
407 void 413 void
408 AudioCallbackPlaySource::play(sv_frame_t startFrame) 414 AudioCallbackPlaySource::play(sv_frame_t startFrame)
409 { 415 {
416 if (!m_target) return;
417
410 if (!m_sourceSampleRate) { 418 if (!m_sourceSampleRate) {
411 cerr << "AudioCallbackPlaySource::play: No source sample rate available, not playing" << endl; 419 cerr << "AudioCallbackPlaySource::play: No source sample rate available, not playing" << endl;
412 return; 420 return;
413 } 421 }
414 422
462 cerr << "reset ring buffer for channel " << c << endl; 470 cerr << "reset ring buffer for channel " << c << endl;
463 #endif 471 #endif
464 if (rb) rb->reset(); 472 if (rb) rb->reset();
465 } 473 }
466 } 474 }
467 if (m_converter) src_reset(m_converter); 475 if (m_resampler) {
468 if (m_crapConverter) src_reset(m_crapConverter); 476 m_resampler->reset();
477 }
469 478
470 m_mutex.unlock(); 479 m_mutex.unlock();
471 480
472 m_audioGenerator->reset(); 481 m_audioGenerator->reset();
473 482
549 } 558 }
550 559
551 void 560 void
552 AudioCallbackPlaySource::preferenceChanged(PropertyContainer::PropertyName n) 561 AudioCallbackPlaySource::preferenceChanged(PropertyContainer::PropertyName n)
553 { 562 {
554 if (n == "Resample Quality") {
555 setResampleQuality(Preferences::getInstance()->getResampleQuality());
556 }
557 } 563 }
558 564
559 void 565 void
560 AudioCallbackPlaySource::audioProcessingOverload() 566 AudioCallbackPlaySource::audioProcessingOverload()
561 { 567 {
939 AudioCallbackPlaySource::setSystemPlaybackSampleRate(int sr) 945 AudioCallbackPlaySource::setSystemPlaybackSampleRate(int sr)
940 { 946 {
941 bool first = (m_targetSampleRate == 0); 947 bool first = (m_targetSampleRate == 0);
942 948
943 m_targetSampleRate = sr; 949 m_targetSampleRate = sr;
944 initialiseConverter(); 950 initialiseResampler();
945 951
946 if (first && (m_stretchRatio != 1.f)) { 952 if (first && (m_stretchRatio != 1.f)) {
947 // couldn't create a stretcher before because we had no sample 953 // couldn't create a stretcher before because we had no sample
948 // rate: make one now 954 // rate: make one now
949 setTimeStretch(m_stretchRatio); 955 setTimeStretch(m_stretchRatio);
950 } 956 }
951 } 957 }
952 958
953 void 959 void
954 AudioCallbackPlaySource::initialiseConverter() 960 AudioCallbackPlaySource::initialiseResampler()
955 { 961 {
956 m_mutex.lock(); 962 m_mutex.lock();
957 963
958 if (m_converter) { 964 #ifdef DEBUG_AUDIO_PLAY_SOURCE
959 src_delete(m_converter); 965 cerr << "AudioCallbackPlaySource::initialiseResampler(): from "
960 src_delete(m_crapConverter); 966 << getSourceSampleRate() << " to " << getTargetSampleRate() << endl;
961 m_converter = 0; 967 #endif
962 m_crapConverter = 0; 968
969 if (m_resampler) {
970 delete m_resampler;
971 m_resampler = 0;
963 } 972 }
964 973
965 if (getSourceSampleRate() != getTargetSampleRate()) { 974 if (getSourceSampleRate() != getTargetSampleRate()) {
966 975
967 int err = 0; 976 m_resampler = new breakfastquay::Resampler
968 977 (breakfastquay::Resampler::FastestTolerable,
969 m_converter = src_new(m_resampleQuality == 2 ? SRC_SINC_BEST_QUALITY : 978 getTargetChannelCount());
970 m_resampleQuality == 1 ? SRC_SINC_MEDIUM_QUALITY : 979
971 m_resampleQuality == 0 ? SRC_SINC_FASTEST : 980 m_mutex.unlock();
972 SRC_SINC_MEDIUM_QUALITY, 981
973 getTargetChannelCount(), &err); 982 emit sampleRateMismatch(getSourceSampleRate(),
974 983 getTargetSampleRate(),
975 if (m_converter) { 984 true);
976 m_crapConverter = src_new(SRC_LINEAR,
977 getTargetChannelCount(),
978 &err);
979 }
980
981 if (!m_converter || !m_crapConverter) {
982 cerr
983 << "AudioCallbackPlaySource::setModel: ERROR in creating samplerate converter: "
984 << src_strerror(err) << endl;
985
986 if (m_converter) {
987 src_delete(m_converter);
988 m_converter = 0;
989 }
990
991 if (m_crapConverter) {
992 src_delete(m_crapConverter);
993 m_crapConverter = 0;
994 }
995
996 m_mutex.unlock();
997
998 emit sampleRateMismatch(getSourceSampleRate(),
999 getTargetSampleRate(),
1000 false);
1001 } else {
1002
1003 m_mutex.unlock();
1004
1005 emit sampleRateMismatch(getSourceSampleRate(),
1006 getTargetSampleRate(),
1007 true);
1008 }
1009 } else { 985 } else {
1010 m_mutex.unlock(); 986 m_mutex.unlock();
1011 } 987 }
1012 }
1013
1014 void
1015 AudioCallbackPlaySource::setResampleQuality(int q)
1016 {
1017 if (q == m_resampleQuality) return;
1018 m_resampleQuality = q;
1019
1020 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1021 SVDEBUG << "AudioCallbackPlaySource::setResampleQuality: setting to "
1022 << m_resampleQuality << endl;
1023 #endif
1024
1025 initialiseConverter();
1026 } 988 }
1027 989
1028 void 990 void
1029 AudioCallbackPlaySource::setAuditioningEffect(Auditionable *a) 991 AudioCallbackPlaySource::setAuditioningEffect(Auditionable *a)
1030 { 992 {
1391 cout << "AudioCallbackPlaySourceFillThread: no space to fill" << endl; 1353 cout << "AudioCallbackPlaySourceFillThread: no space to fill" << endl;
1392 #endif 1354 #endif
1393 return false; 1355 return false;
1394 } 1356 }
1395 1357
1358 // space is now the number of samples that can be written on each
1359 // channel's write ringbuffer
1360
1396 sv_frame_t f = m_writeBufferFill; 1361 sv_frame_t f = m_writeBufferFill;
1397 1362
1398 bool readWriteEqual = (m_readBuffers == m_writeBuffers); 1363 bool readWriteEqual = (m_readBuffers == m_writeBuffers);
1399 1364
1400 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1365 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1428 bufferPtrCount = channels; 1393 bufferPtrCount = channels;
1429 } 1394 }
1430 1395
1431 sv_frame_t generatorBlockSize = m_audioGenerator->getBlockSize(); 1396 sv_frame_t generatorBlockSize = m_audioGenerator->getBlockSize();
1432 1397
1433 if (resample && !m_converter) { 1398 if (resample && !m_resampler) {
1434 static bool warned = false; 1399 throw std::logic_error("Sample rates differ, but no resampler available!");
1435 if (!warned) { 1400 }
1436 cerr << "WARNING: sample rates differ, but no converter available!" << endl; 1401
1437 warned = true; 1402 if (resample && m_resampler) {
1438 }
1439 }
1440
1441 if (resample && m_converter) {
1442 1403
1443 double ratio = 1404 double ratio =
1444 double(getTargetSampleRate()) / double(getSourceSampleRate()); 1405 double(getTargetSampleRate()) / double(getSourceSampleRate());
1445 orig = sv_frame_t(double(orig) / ratio + 0.1); 1406 orig = sv_frame_t(double(orig) / ratio + 0.1);
1446 1407
1488 for (int i = 0; i < got; ++i) { 1449 for (int i = 0; i < got; ++i) {
1489 float sample = nonintlv[c * got + i]; 1450 float sample = nonintlv[c * got + i];
1490 intlv[channels * i + c] = sample; 1451 intlv[channels * i + c] = sample;
1491 } 1452 }
1492 } 1453 }
1493 1454
1455 sv_frame_t toCopy = m_resampler->resampleInterleaved
1456 (intlv, srcout, got, ratio, false);
1457
1494 SRC_DATA data; 1458 SRC_DATA data;
1495 data.data_in = intlv; 1459 data.data_in = intlv;
1496 data.data_out = srcout; 1460 data.data_out = srcout;
1497 data.input_frames = long(got); 1461 data.input_frames = long(got);
1498 data.output_frames = long(work); 1462 data.output_frames = long(work);
1499 data.src_ratio = ratio; 1463 data.src_ratio = ratio;
1500 data.end_of_input = 0; 1464 data.end_of_input = 0;
1501 1465
1502 int err = 0; 1466 int err = src_process(m_converter, &data);
1503
1504 if (m_timeStretcher && m_timeStretcher->getTimeRatio() < 0.4) {
1505 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1506 cout << "Using crappy converter" << endl;
1507 #endif
1508 err = src_process(m_crapConverter, &data);
1509 } else {
1510 err = src_process(m_converter, &data);
1511 }
1512 1467
1513 sv_frame_t toCopy = sv_frame_t(double(got) * ratio + 0.1); 1468 sv_frame_t toCopy = sv_frame_t(double(got) * ratio + 0.1);
1514 1469
1515 if (err) { 1470 if (err) {
1516 cerr 1471 cerr