comparison 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
comparison
equal deleted inserted replaced
31:37af203dbd15 32:e3b32dc5180b
18 #include "AudioGenerator.h" 18 #include "AudioGenerator.h"
19 19
20 #include "data/model/Model.h" 20 #include "data/model/Model.h"
21 #include "view/ViewManager.h" 21 #include "view/ViewManager.h"
22 #include "base/PlayParameterRepository.h" 22 #include "base/PlayParameterRepository.h"
23 #include "base/Preferences.h"
23 #include "data/model/DenseTimeValueModel.h" 24 #include "data/model/DenseTimeValueModel.h"
24 #include "data/model/SparseOneDimensionalModel.h" 25 #include "data/model/SparseOneDimensionalModel.h"
25 #include "PhaseVocoderTimeStretcher.h" 26 #include "PhaseVocoderTimeStretcher.h"
26 27
27 #include <iostream> 28 #include <iostream>
51 m_lastModelEndFrame(0), 52 m_lastModelEndFrame(0),
52 m_outputLeft(0.0), 53 m_outputLeft(0.0),
53 m_outputRight(0.0), 54 m_outputRight(0.0),
54 m_timeStretcher(0), 55 m_timeStretcher(0),
55 m_fillThread(0), 56 m_fillThread(0),
56 m_converter(0) 57 m_converter(0),
58 m_crapConverter(0),
59 m_resampleQuality(Preferences::getInstance()->getResampleQuality())
57 { 60 {
58 m_viewManager->setAudioPlaySource(this); 61 m_viewManager->setAudioPlaySource(this);
59 62
60 connect(m_viewManager, SIGNAL(selectionChanged()), 63 connect(m_viewManager, SIGNAL(selectionChanged()),
61 this, SLOT(selectionChanged())); 64 this, SLOT(selectionChanged()));
65 this, SLOT(playSelectionModeChanged())); 68 this, SLOT(playSelectionModeChanged()));
66 69
67 connect(PlayParameterRepository::getInstance(), 70 connect(PlayParameterRepository::getInstance(),
68 SIGNAL(playParametersChanged(PlayParameters *)), 71 SIGNAL(playParametersChanged(PlayParameters *)),
69 this, SLOT(playParametersChanged(PlayParameters *))); 72 this, SLOT(playParametersChanged(PlayParameters *)));
73
74 connect(Preferences::getInstance(),
75 SIGNAL(propertyChanged(PropertyContainer::PropertyName)),
76 this, SLOT(preferenceChanged(PropertyContainer::PropertyName)));
70 } 77 }
71 78
72 AudioCallbackPlaySource::~AudioCallbackPlaySource() 79 AudioCallbackPlaySource::~AudioCallbackPlaySource()
73 { 80 {
74 m_exiting = true; 81 m_exiting = true;
166 } 173 }
167 174
168 if (buffersChanged || srChanged) { 175 if (buffersChanged || srChanged) {
169 if (m_converter) { 176 if (m_converter) {
170 src_delete(m_converter); 177 src_delete(m_converter);
178 src_delete(m_crapConverter);
171 m_converter = 0; 179 m_converter = 0;
180 m_crapConverter = 0;
172 } 181 }
173 } 182 }
174 183
175 m_mutex.unlock(); 184 m_mutex.unlock();
176 185
200 m_models.erase(model); 209 m_models.erase(model);
201 210
202 if (m_models.empty()) { 211 if (m_models.empty()) {
203 if (m_converter) { 212 if (m_converter) {
204 src_delete(m_converter); 213 src_delete(m_converter);
214 src_delete(m_crapConverter);
205 m_converter = 0; 215 m_converter = 0;
216 m_crapConverter = 0;
206 } 217 }
207 m_sourceSampleRate = 0; 218 m_sourceSampleRate = 0;
208 } 219 }
209 220
210 size_t lastEnd = 0; 221 size_t lastEnd = 0;
230 241
231 m_models.clear(); 242 m_models.clear();
232 243
233 if (m_converter) { 244 if (m_converter) {
234 src_delete(m_converter); 245 src_delete(m_converter);
246 src_delete(m_crapConverter);
235 m_converter = 0; 247 m_converter = 0;
248 m_crapConverter = 0;
236 } 249 }
237 250
238 m_lastModelEndFrame = 0; 251 m_lastModelEndFrame = 0;
239 252
240 m_sourceSampleRate = 0; 253 m_sourceSampleRate = 0;
320 RingBuffer<float> *rb = getReadRingBuffer(c); 333 RingBuffer<float> *rb = getReadRingBuffer(c);
321 if (rb) rb->reset(); 334 if (rb) rb->reset();
322 } 335 }
323 } 336 }
324 if (m_converter) src_reset(m_converter); 337 if (m_converter) src_reset(m_converter);
338 if (m_crapConverter) src_reset(m_crapConverter);
325 } else { 339 } else {
326 if (m_converter) src_reset(m_converter); 340 if (m_converter) src_reset(m_converter);
341 if (m_crapConverter) src_reset(m_crapConverter);
327 m_readBufferFill = m_writeBufferFill = startFrame; 342 m_readBufferFill = m_writeBufferFill = startFrame;
328 } 343 }
329 m_mutex.unlock(); 344 m_mutex.unlock();
330 345
331 m_audioGenerator->reset(); 346 m_audioGenerator->reset();
369 384
370 void 385 void
371 AudioCallbackPlaySource::playParametersChanged(PlayParameters *params) 386 AudioCallbackPlaySource::playParametersChanged(PlayParameters *params)
372 { 387 {
373 clearRingBuffers(); 388 clearRingBuffers();
389 }
390
391 void
392 AudioCallbackPlaySource::preferenceChanged(PropertyContainer::PropertyName n)
393 {
394 if (n == "Resample Quality") {
395 setResampleQuality(Preferences::getInstance()->getResampleQuality());
396 }
374 } 397 }
375 398
376 void 399 void
377 AudioCallbackPlaySource::setTargetBlockSize(size_t size) 400 AudioCallbackPlaySource::setTargetBlockSize(size_t size)
378 { 401 {
536 559
537 void 560 void
538 AudioCallbackPlaySource::setTargetSampleRate(size_t sr) 561 AudioCallbackPlaySource::setTargetSampleRate(size_t sr)
539 { 562 {
540 m_targetSampleRate = sr; 563 m_targetSampleRate = sr;
564 initialiseConverter();
565 }
566
567 void
568 AudioCallbackPlaySource::initialiseConverter()
569 {
570 m_mutex.lock();
571
572 if (m_converter) {
573 src_delete(m_converter);
574 src_delete(m_crapConverter);
575 m_converter = 0;
576 m_crapConverter = 0;
577 }
541 578
542 if (getSourceSampleRate() != getTargetSampleRate()) { 579 if (getSourceSampleRate() != getTargetSampleRate()) {
543 580
544 int err = 0; 581 int err = 0;
545 m_converter = src_new(SRC_SINC_BEST_QUALITY, 582
583 m_converter = src_new(m_resampleQuality == 2 ? SRC_SINC_BEST_QUALITY :
584 m_resampleQuality == 1 ? SRC_SINC_MEDIUM_QUALITY :
585 m_resampleQuality == 0 ? SRC_SINC_FASTEST :
586 SRC_SINC_MEDIUM_QUALITY,
546 getTargetChannelCount(), &err); 587 getTargetChannelCount(), &err);
547 if (!m_converter) { 588
589 if (m_converter) {
590 m_crapConverter = src_new(SRC_LINEAR,
591 getTargetChannelCount(),
592 &err);
593 }
594
595 if (!m_converter || !m_crapConverter) {
548 std::cerr 596 std::cerr
549 << "AudioCallbackPlaySource::setModel: ERROR in creating samplerate converter: " 597 << "AudioCallbackPlaySource::setModel: ERROR in creating samplerate converter: "
550 << src_strerror(err) << std::endl; 598 << src_strerror(err) << std::endl;
599
600 if (m_converter) {
601 src_delete(m_converter);
602 m_converter = 0;
603 }
604
605 if (m_crapConverter) {
606 src_delete(m_crapConverter);
607 m_crapConverter = 0;
608 }
609
610 m_mutex.unlock();
551 611
552 emit sampleRateMismatch(getSourceSampleRate(), 612 emit sampleRateMismatch(getSourceSampleRate(),
553 getTargetSampleRate(), 613 getTargetSampleRate(),
554 false); 614 false);
555 } else { 615 } else {
556 616
617 m_mutex.unlock();
618
557 emit sampleRateMismatch(getSourceSampleRate(), 619 emit sampleRateMismatch(getSourceSampleRate(),
558 getTargetSampleRate(), 620 getTargetSampleRate(),
559 true); 621 true);
560 } 622 }
561 } 623 } else {
624 m_mutex.unlock();
625 }
626 }
627
628 void
629 AudioCallbackPlaySource::setResampleQuality(int q)
630 {
631 if (q == m_resampleQuality) return;
632 m_resampleQuality = q;
633
634 #ifdef DEBUG_AUDIO_PLAY_SOURCE
635 std::cerr << "AudioCallbackPlaySource::setResampleQuality: setting to "
636 << m_resampleQuality << std::endl;
637 #endif
638
639 initialiseConverter();
562 } 640 }
563 641
564 size_t 642 size_t
565 AudioCallbackPlaySource::getTargetSampleRate() const 643 AudioCallbackPlaySource::getTargetSampleRate() const
566 { 644 {
892 data.input_frames = got; 970 data.input_frames = got;
893 data.output_frames = work; 971 data.output_frames = work;
894 data.src_ratio = ratio; 972 data.src_ratio = ratio;
895 data.end_of_input = 0; 973 data.end_of_input = 0;
896 974
897 int err = src_process(m_converter, &data); 975 int err = 0;
898 // size_t toCopy = size_t(work * ratio + 0.1); 976
977 if (m_timeStretcher && m_timeStretcher->getRatio() < 0.4) {
978 #ifdef DEBUG_AUDIO_PLAY_SOURCE
979 std::cerr << "Using crappy converter" << std::endl;
980 #endif
981 src_process(m_crapConverter, &data);
982 } else {
983 src_process(m_converter, &data);
984 }
985
899 size_t toCopy = size_t(got * ratio + 0.1); 986 size_t toCopy = size_t(got * ratio + 0.1);
900 987
901 if (err) { 988 if (err) {
902 std::cerr 989 std::cerr
903 << "AudioCallbackPlaySourceFillThread: ERROR in samplerate conversion: " 990 << "AudioCallbackPlaySourceFillThread: ERROR in samplerate conversion: "