comparison audioio/AudioCallbackPlaySource.cpp @ 371:dfcc5b355f33

Merge from branch warnfix_no_size_t
author Chris Cannam
date Wed, 18 Jun 2014 13:51:38 +0100
parents 1e4fa2007e61
children f747be6743ab
comparison
equal deleted inserted replaced
355:e7a3fa8f4eec 371:dfcc5b355f33
35 #include <cassert> 35 #include <cassert>
36 36
37 //#define DEBUG_AUDIO_PLAY_SOURCE 1 37 //#define DEBUG_AUDIO_PLAY_SOURCE 1
38 //#define DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1 38 //#define DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1
39 39
40 static const size_t DEFAULT_RING_BUFFER_SIZE = 131071; 40 static const int DEFAULT_RING_BUFFER_SIZE = 131071;
41 41
42 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManagerBase *manager, 42 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManagerBase *manager,
43 QString clientName) : 43 QString clientName) :
44 m_viewManager(manager), 44 m_viewManager(manager),
45 m_audioGenerator(new AudioGenerator()), 45 m_audioGenerator(new AudioGenerator()),
125 125
126 delete m_writeBuffers; 126 delete m_writeBuffers;
127 127
128 delete m_audioGenerator; 128 delete m_audioGenerator;
129 129
130 for (size_t i = 0; i < m_stretcherInputCount; ++i) { 130 for (int i = 0; i < m_stretcherInputCount; ++i) {
131 delete[] m_stretcherInputs[i]; 131 delete[] m_stretcherInputs[i];
132 } 132 }
133 delete[] m_stretcherInputSizes; 133 delete[] m_stretcherInputSizes;
134 delete[] m_stretcherInputs; 134 delete[] m_stretcherInputs;
135 135
157 m_lastModelEndFrame = model->getEndFrame(); 157 m_lastModelEndFrame = model->getEndFrame();
158 } 158 }
159 159
160 bool buffersChanged = false, srChanged = false; 160 bool buffersChanged = false, srChanged = false;
161 161
162 size_t modelChannels = 1; 162 int modelChannels = 1;
163 DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model); 163 DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model);
164 if (dtvm) modelChannels = dtvm->getChannelCount(); 164 if (dtvm) modelChannels = dtvm->getChannelCount();
165 if (modelChannels > m_sourceChannelCount) { 165 if (modelChannels > m_sourceChannelCount) {
166 m_sourceChannelCount = modelChannels; 166 m_sourceChannelCount = modelChannels;
167 } 167 }
218 srChanged = true; 218 srChanged = true;
219 } 219 }
220 } 220 }
221 } 221 }
222 222
223 if (!m_writeBuffers || (m_writeBuffers->size() < getTargetChannelCount())) { 223 if (!m_writeBuffers || (int)m_writeBuffers->size() < getTargetChannelCount()) {
224 clearRingBuffers(true, getTargetChannelCount()); 224 clearRingBuffers(true, getTargetChannelCount());
225 buffersChanged = true; 225 buffersChanged = true;
226 } else { 226 } else {
227 if (canPlay) clearRingBuffers(true); 227 if (canPlay) clearRingBuffers(true);
228 } 228 }
253 253
254 if (buffersChanged || srChanged) { 254 if (buffersChanged || srChanged) {
255 emit modelReplaced(); 255 emit modelReplaced();
256 } 256 }
257 257
258 connect(model, SIGNAL(modelChanged(size_t, size_t)), 258 connect(model, SIGNAL(modelChangedWithin(int, int)),
259 this, SLOT(modelChanged(size_t, size_t))); 259 this, SLOT(modelChangedWithin(int, int)));
260 260
261 #ifdef DEBUG_AUDIO_PLAY_SOURCE 261 #ifdef DEBUG_AUDIO_PLAY_SOURCE
262 cout << "AudioCallbackPlaySource::addModel: awakening thread" << endl; 262 cout << "AudioCallbackPlaySource::addModel: awakening thread" << endl;
263 #endif 263 #endif
264 264
265 m_condition.wakeAll(); 265 m_condition.wakeAll();
266 } 266 }
267 267
268 void 268 void
269 AudioCallbackPlaySource::modelChanged(size_t startFrame, size_t endFrame) 269 AudioCallbackPlaySource::modelChangedWithin(int
270 { 270 #ifdef DEBUG_AUDIO_PLAY_SOURCE
271 #ifdef DEBUG_AUDIO_PLAY_SOURCE 271 startFrame
272 SVDEBUG << "AudioCallbackPlaySource::modelChanged(" << startFrame << "," << endFrame << ")" << endl; 272 #endif
273 , int endFrame)
274 {
275 #ifdef DEBUG_AUDIO_PLAY_SOURCE
276 SVDEBUG << "AudioCallbackPlaySource::modelChangedWithin(" << startFrame << "," << endFrame << ")" << endl;
273 #endif 277 #endif
274 if (endFrame > m_lastModelEndFrame) { 278 if (endFrame > m_lastModelEndFrame) {
275 m_lastModelEndFrame = endFrame; 279 m_lastModelEndFrame = endFrame;
276 rebuildRangeLists(); 280 rebuildRangeLists();
277 } 281 }
284 288
285 #ifdef DEBUG_AUDIO_PLAY_SOURCE 289 #ifdef DEBUG_AUDIO_PLAY_SOURCE
286 cout << "AudioCallbackPlaySource::removeModel(" << model << ")" << endl; 290 cout << "AudioCallbackPlaySource::removeModel(" << model << ")" << endl;
287 #endif 291 #endif
288 292
289 disconnect(model, SIGNAL(modelChanged(size_t, size_t)), 293 disconnect(model, SIGNAL(modelChangedWithin(int, int)),
290 this, SLOT(modelChanged(size_t, size_t))); 294 this, SLOT(modelChangedWithin(int, int)));
291 295
292 m_models.erase(model); 296 m_models.erase(model);
293 297
294 if (m_models.empty()) { 298 if (m_models.empty()) {
295 if (m_converter) { 299 if (m_converter) {
299 m_crapConverter = 0; 303 m_crapConverter = 0;
300 } 304 }
301 m_sourceSampleRate = 0; 305 m_sourceSampleRate = 0;
302 } 306 }
303 307
304 size_t lastEnd = 0; 308 int lastEnd = 0;
305 for (std::set<Model *>::const_iterator i = m_models.begin(); 309 for (std::set<Model *>::const_iterator i = m_models.begin();
306 i != m_models.end(); ++i) { 310 i != m_models.end(); ++i) {
307 #ifdef DEBUG_AUDIO_PLAY_SOURCE 311 #ifdef DEBUG_AUDIO_PLAY_SOURCE
308 cout << "AudioCallbackPlaySource::removeModel(" << model << "): checking end frame on model " << *i << endl; 312 cout << "AudioCallbackPlaySource::removeModel(" << model << "): checking end frame on model " << *i << endl;
309 #endif 313 #endif
310 if ((*i)->getEndFrame() > lastEnd) lastEnd = (*i)->getEndFrame(); 314 if ((*i)->getEndFrame() > lastEnd) {
315 lastEnd = (*i)->getEndFrame();
316 }
311 #ifdef DEBUG_AUDIO_PLAY_SOURCE 317 #ifdef DEBUG_AUDIO_PLAY_SOURCE
312 cout << "(done, lastEnd now " << lastEnd << ")" << endl; 318 cout << "(done, lastEnd now " << lastEnd << ")" << endl;
313 #endif 319 #endif
314 } 320 }
315 m_lastModelEndFrame = lastEnd; 321 m_lastModelEndFrame = lastEnd;
349 355
350 clearRingBuffers(); 356 clearRingBuffers();
351 } 357 }
352 358
353 void 359 void
354 AudioCallbackPlaySource::clearRingBuffers(bool haveLock, size_t count) 360 AudioCallbackPlaySource::clearRingBuffers(bool haveLock, int count)
355 { 361 {
356 if (!haveLock) m_mutex.lock(); 362 if (!haveLock) m_mutex.lock();
357 363
358 rebuildRangeLists(); 364 rebuildRangeLists();
359 365
367 delete m_writeBuffers; 373 delete m_writeBuffers;
368 } 374 }
369 375
370 m_writeBuffers = new RingBufferVector; 376 m_writeBuffers = new RingBufferVector;
371 377
372 for (size_t i = 0; i < count; ++i) { 378 for (int i = 0; i < count; ++i) {
373 m_writeBuffers->push_back(new RingBuffer<float>(m_ringBufferSize)); 379 m_writeBuffers->push_back(new RingBuffer<float>(m_ringBufferSize));
374 } 380 }
375 381
376 // cout << "AudioCallbackPlaySource::clearRingBuffers: Created " 382 // cout << "AudioCallbackPlaySource::clearRingBuffers: Created "
377 // << count << " write buffers" << endl; 383 // << count << " write buffers" << endl;
380 m_mutex.unlock(); 386 m_mutex.unlock();
381 } 387 }
382 } 388 }
383 389
384 void 390 void
385 AudioCallbackPlaySource::play(size_t startFrame) 391 AudioCallbackPlaySource::play(int startFrame)
386 { 392 {
387 if (m_viewManager->getPlaySelectionMode() && 393 if (m_viewManager->getPlaySelectionMode() &&
388 !m_viewManager->getSelections().empty()) { 394 !m_viewManager->getSelections().empty()) {
389 395
390 SVDEBUG << "AudioCallbackPlaySource::play: constraining frame " << startFrame << " to selection = "; 396 SVDEBUG << "AudioCallbackPlaySource::play: constraining frame " << startFrame << " to selection = ";
423 m_monoStretcher->reset(); 429 m_monoStretcher->reset();
424 } 430 }
425 431
426 m_readBufferFill = m_writeBufferFill = startFrame; 432 m_readBufferFill = m_writeBufferFill = startFrame;
427 if (m_readBuffers) { 433 if (m_readBuffers) {
428 for (size_t c = 0; c < getTargetChannelCount(); ++c) { 434 for (int c = 0; c < getTargetChannelCount(); ++c) {
429 RingBuffer<float> *rb = getReadRingBuffer(c); 435 RingBuffer<float> *rb = getReadRingBuffer(c);
430 #ifdef DEBUG_AUDIO_PLAY_SOURCE 436 #ifdef DEBUG_AUDIO_PLAY_SOURCE
431 cerr << "reset ring buffer for channel " << c << endl; 437 cerr << "reset ring buffer for channel " << c << endl;
432 #endif 438 #endif
433 if (rb) rb->reset(); 439 if (rb) rb->reset();
548 return; 554 return;
549 } 555 }
550 } 556 }
551 557
552 void 558 void
553 AudioCallbackPlaySource::setTarget(AudioCallbackPlayTarget *target, size_t size) 559 AudioCallbackPlaySource::setTarget(AudioCallbackPlayTarget *target, int size)
554 { 560 {
555 m_target = target; 561 m_target = target;
556 cout << "AudioCallbackPlaySource::setTarget: Block size -> " << size << endl; 562 cout << "AudioCallbackPlaySource::setTarget: Block size -> " << size << endl;
557 if (size != 0) { 563 if (size != 0) {
558 m_blockSize = size; 564 m_blockSize = size;
567 clearRingBuffers(); 573 clearRingBuffers();
568 } 574 }
569 } 575 }
570 } 576 }
571 577
572 size_t 578 int
573 AudioCallbackPlaySource::getTargetBlockSize() const 579 AudioCallbackPlaySource::getTargetBlockSize() const
574 { 580 {
575 // cout << "AudioCallbackPlaySource::getTargetBlockSize() -> " << m_blockSize << endl; 581 // cout << "AudioCallbackPlaySource::getTargetBlockSize() -> " << m_blockSize << endl;
576 return m_blockSize; 582 return m_blockSize;
577 } 583 }
578 584
579 void 585 void
580 AudioCallbackPlaySource::setTargetPlayLatency(size_t latency) 586 AudioCallbackPlaySource::setTargetPlayLatency(int latency)
581 { 587 {
582 m_playLatency = latency; 588 m_playLatency = latency;
583 } 589 }
584 590
585 size_t 591 int
586 AudioCallbackPlaySource::getTargetPlayLatency() const 592 AudioCallbackPlaySource::getTargetPlayLatency() const
587 { 593 {
588 return m_playLatency; 594 return m_playLatency;
589 } 595 }
590 596
591 size_t 597 int
592 AudioCallbackPlaySource::getCurrentPlayingFrame() 598 AudioCallbackPlaySource::getCurrentPlayingFrame()
593 { 599 {
594 // This method attempts to estimate which audio sample frame is 600 // This method attempts to estimate which audio sample frame is
595 // "currently coming through the speakers". 601 // "currently coming through the speakers".
596 602
597 size_t targetRate = getTargetSampleRate(); 603 int targetRate = getTargetSampleRate();
598 size_t latency = m_playLatency; // at target rate 604 int latency = m_playLatency; // at target rate
599 RealTime latency_t = RealTime::frame2RealTime(latency, targetRate); 605 RealTime latency_t = RealTime::frame2RealTime(latency, targetRate);
600 606
601 return getCurrentFrame(latency_t); 607 return getCurrentFrame(latency_t);
602 } 608 }
603 609
604 size_t 610 int
605 AudioCallbackPlaySource::getCurrentBufferedFrame() 611 AudioCallbackPlaySource::getCurrentBufferedFrame()
606 { 612 {
607 return getCurrentFrame(RealTime::zeroTime); 613 return getCurrentFrame(RealTime::zeroTime);
608 } 614 }
609 615
610 size_t 616 int
611 AudioCallbackPlaySource::getCurrentFrame(RealTime latency_t) 617 AudioCallbackPlaySource::getCurrentFrame(RealTime latency_t)
612 { 618 {
613 bool resample = false;
614 double resampleRatio = 1.0;
615
616 // We resample when filling the ring buffer, and time-stretch when 619 // We resample when filling the ring buffer, and time-stretch when
617 // draining it. The buffer contains data at the "target rate" and 620 // draining it. The buffer contains data at the "target rate" and
618 // the latency provided by the target is also at the target rate. 621 // the latency provided by the target is also at the target rate.
619 // Because of the multiple rates involved, we do the actual 622 // Because of the multiple rates involved, we do the actual
620 // calculation using RealTime instead. 623 // calculation using RealTime instead.
621 624
622 size_t sourceRate = getSourceSampleRate(); 625 int sourceRate = getSourceSampleRate();
623 size_t targetRate = getTargetSampleRate(); 626 int targetRate = getTargetSampleRate();
624 627
625 if (sourceRate == 0 || targetRate == 0) return 0; 628 if (sourceRate == 0 || targetRate == 0) return 0;
626 629
627 size_t inbuffer = 0; // at target rate 630 int inbuffer = 0; // at target rate
628 631
629 for (size_t c = 0; c < getTargetChannelCount(); ++c) { 632 for (int c = 0; c < getTargetChannelCount(); ++c) {
630 RingBuffer<float> *rb = getReadRingBuffer(c); 633 RingBuffer<float> *rb = getReadRingBuffer(c);
631 if (rb) { 634 if (rb) {
632 size_t here = rb->getReadSpace(); 635 int here = rb->getReadSpace();
633 if (c == 0 || here < inbuffer) inbuffer = here; 636 if (c == 0 || here < inbuffer) inbuffer = here;
634 } 637 }
635 } 638 }
636 639
637 size_t readBufferFill = m_readBufferFill; 640 int readBufferFill = m_readBufferFill;
638 size_t lastRetrievedBlockSize = m_lastRetrievedBlockSize; 641 int lastRetrievedBlockSize = m_lastRetrievedBlockSize;
639 double lastRetrievalTimestamp = m_lastRetrievalTimestamp; 642 double lastRetrievalTimestamp = m_lastRetrievalTimestamp;
640 double currentTime = 0.0; 643 double currentTime = 0.0;
641 if (m_target) currentTime = m_target->getCurrentTime(); 644 if (m_target) currentTime = m_target->getCurrentTime();
642 645
643 bool looping = m_viewManager->getPlayLoopMode(); 646 bool looping = m_viewManager->getPlayLoopMode();
644 647
645 RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, targetRate); 648 RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, targetRate);
646 649
647 size_t stretchlat = 0; 650 int stretchlat = 0;
648 double timeRatio = 1.0; 651 double timeRatio = 1.0;
649 652
650 if (m_timeStretcher) { 653 if (m_timeStretcher) {
651 stretchlat = m_timeStretcher->getLatency(); 654 stretchlat = m_timeStretcher->getLatency();
652 timeRatio = m_timeStretcher->getTimeRatio(); 655 timeRatio = m_timeStretcher->getTimeRatio();
702 705
703 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 706 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
704 cerr << "\nbuffered to: " << bufferedto_t << ", in buffer: " << inbuffer_t << ", time ratio " << timeRatio << "\n stretcher latency: " << stretchlat_t << ", device latency: " << latency_t << "\n since request: " << sincerequest_t << ", last retrieved quantity: " << lastretrieved_t << endl; 707 cerr << "\nbuffered to: " << bufferedto_t << ", in buffer: " << inbuffer_t << ", time ratio " << timeRatio << "\n stretcher latency: " << stretchlat_t << ", device latency: " << latency_t << "\n since request: " << sincerequest_t << ", last retrieved quantity: " << lastretrieved_t << endl;
705 #endif 708 #endif
706 709
707 RealTime end = RealTime::frame2RealTime(m_lastModelEndFrame, sourceRate);
708
709 // Normally the range lists should contain at least one item each 710 // Normally the range lists should contain at least one item each
710 // -- if playback is unconstrained, that item should report the 711 // -- if playback is unconstrained, that item should report the
711 // entire source audio duration. 712 // entire source audio duration.
712 713
713 if (m_rangeStarts.empty()) { 714 if (m_rangeStarts.empty()) {
718 // this code is only used in case of error in rebuildRangeLists 719 // this code is only used in case of error in rebuildRangeLists
719 RealTime playing_t = bufferedto_t 720 RealTime playing_t = bufferedto_t
720 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t 721 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
721 + sincerequest_t; 722 + sincerequest_t;
722 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime; 723 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
723 size_t frame = RealTime::realTime2Frame(playing_t, sourceRate); 724 int frame = RealTime::realTime2Frame(playing_t, sourceRate);
724 return m_viewManager->alignPlaybackFrameToReference(frame); 725 return m_viewManager->alignPlaybackFrameToReference(frame);
725 } 726 }
726 727
727 int inRange = 0; 728 int inRange = 0;
728 int index = 0; 729 int index = 0;
729 730
730 for (size_t i = 0; i < m_rangeStarts.size(); ++i) { 731 for (int i = 0; i < (int)m_rangeStarts.size(); ++i) {
731 if (bufferedto_t >= m_rangeStarts[i]) { 732 if (bufferedto_t >= m_rangeStarts[i]) {
732 inRange = index; 733 inRange = index;
733 } else { 734 } else {
734 break; 735 break;
735 } 736 }
736 ++index; 737 ++index;
737 } 738 }
738 739
739 if (inRange >= m_rangeStarts.size()) inRange = m_rangeStarts.size()-1; 740 if (inRange >= (int)m_rangeStarts.size()) inRange = m_rangeStarts.size()-1;
740 741
741 RealTime playing_t = bufferedto_t; 742 RealTime playing_t = bufferedto_t;
742 743
743 playing_t = playing_t 744 playing_t = playing_t
744 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t 745 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
803 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 804 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
804 cerr << " playing time: " << playing_t << endl; 805 cerr << " playing time: " << playing_t << endl;
805 #endif 806 #endif
806 807
807 if (!looping) { 808 if (!looping) {
808 if (inRange == m_rangeStarts.size()-1 && 809 if (inRange == (int)m_rangeStarts.size()-1 &&
809 playing_t >= m_rangeStarts[inRange] + m_rangeDurations[inRange]) { 810 playing_t >= m_rangeStarts[inRange] + m_rangeDurations[inRange]) {
810 cerr << "Not looping, inRange " << inRange << " == rangeStarts.size()-1, playing_t " << playing_t << " >= m_rangeStarts[inRange] " << m_rangeStarts[inRange] << " + m_rangeDurations[inRange] " << m_rangeDurations[inRange] << " -- stopping" << endl; 811 cerr << "Not looping, inRange " << inRange << " == rangeStarts.size()-1, playing_t " << playing_t << " >= m_rangeStarts[inRange] " << m_rangeStarts[inRange] << " + m_rangeDurations[inRange] " << m_rangeDurations[inRange] << " -- stopping" << endl;
811 stop(); 812 stop();
812 } 813 }
813 } 814 }
814 815
815 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime; 816 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
816 817
817 size_t frame = RealTime::realTime2Frame(playing_t, sourceRate); 818 int frame = RealTime::realTime2Frame(playing_t, sourceRate);
818 819
819 if (m_lastCurrentFrame > 0 && !looping) { 820 if (m_lastCurrentFrame > 0 && !looping) {
820 if (frame < m_lastCurrentFrame) { 821 if (frame < m_lastCurrentFrame) {
821 frame = m_lastCurrentFrame; 822 frame = m_lastCurrentFrame;
822 } 823 }
833 bool constrained = (m_viewManager->getPlaySelectionMode()); 834 bool constrained = (m_viewManager->getPlaySelectionMode());
834 835
835 m_rangeStarts.clear(); 836 m_rangeStarts.clear();
836 m_rangeDurations.clear(); 837 m_rangeDurations.clear();
837 838
838 size_t sourceRate = getSourceSampleRate(); 839 int sourceRate = getSourceSampleRate();
839 if (sourceRate == 0) return; 840 if (sourceRate == 0) return;
840 841
841 RealTime end = RealTime::frame2RealTime(m_lastModelEndFrame, sourceRate); 842 RealTime end = RealTime::frame2RealTime(m_lastModelEndFrame, sourceRate);
842 if (end == RealTime::zeroTime) return; 843 if (end == RealTime::zeroTime) return;
843 844
895 right = m_outputRight; 896 right = m_outputRight;
896 return true; 897 return true;
897 } 898 }
898 899
899 void 900 void
900 AudioCallbackPlaySource::setTargetSampleRate(size_t sr) 901 AudioCallbackPlaySource::setTargetSampleRate(int sr)
901 { 902 {
902 bool first = (m_targetSampleRate == 0); 903 bool first = (m_targetSampleRate == 0);
903 904
904 m_targetSampleRate = sr; 905 m_targetSampleRate = sr;
905 initialiseConverter(); 906 initialiseConverter();
1012 { 1013 {
1013 m_audioGenerator->clearSoloModelSet(); 1014 m_audioGenerator->clearSoloModelSet();
1014 clearRingBuffers(); 1015 clearRingBuffers();
1015 } 1016 }
1016 1017
1017 size_t 1018 int
1018 AudioCallbackPlaySource::getTargetSampleRate() const 1019 AudioCallbackPlaySource::getTargetSampleRate() const
1019 { 1020 {
1020 if (m_targetSampleRate) return m_targetSampleRate; 1021 if (m_targetSampleRate) return m_targetSampleRate;
1021 else return getSourceSampleRate(); 1022 else return getSourceSampleRate();
1022 } 1023 }
1023 1024
1024 size_t 1025 int
1025 AudioCallbackPlaySource::getSourceChannelCount() const 1026 AudioCallbackPlaySource::getSourceChannelCount() const
1026 { 1027 {
1027 return m_sourceChannelCount; 1028 return m_sourceChannelCount;
1028 } 1029 }
1029 1030
1030 size_t 1031 int
1031 AudioCallbackPlaySource::getTargetChannelCount() const 1032 AudioCallbackPlaySource::getTargetChannelCount() const
1032 { 1033 {
1033 if (m_sourceChannelCount < 2) return 2; 1034 if (m_sourceChannelCount < 2) return 2;
1034 return m_sourceChannelCount; 1035 return m_sourceChannelCount;
1035 } 1036 }
1036 1037
1037 size_t 1038 int
1038 AudioCallbackPlaySource::getSourceSampleRate() const 1039 AudioCallbackPlaySource::getSourceSampleRate() const
1039 { 1040 {
1040 return m_sourceSampleRate; 1041 return m_sourceSampleRate;
1041 } 1042 }
1042 1043
1060 (getTargetSampleRate(), 1061 (getTargetSampleRate(),
1061 1, 1062 1,
1062 RubberBandStretcher::OptionProcessRealTime, 1063 RubberBandStretcher::OptionProcessRealTime,
1063 factor); 1064 factor);
1064 m_stretcherInputs = new float *[m_stretcherInputCount]; 1065 m_stretcherInputs = new float *[m_stretcherInputCount];
1065 m_stretcherInputSizes = new size_t[m_stretcherInputCount]; 1066 m_stretcherInputSizes = new int[m_stretcherInputCount];
1066 for (size_t c = 0; c < m_stretcherInputCount; ++c) { 1067 for (int c = 0; c < m_stretcherInputCount; ++c) {
1067 m_stretcherInputSizes[c] = 16384; 1068 m_stretcherInputSizes[c] = 16384;
1068 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]]; 1069 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]];
1069 } 1070 }
1070 m_monoStretcher = monoStretcher; 1071 m_monoStretcher = monoStretcher;
1071 m_timeStretcher = stretcher; 1072 m_timeStretcher = stretcher;
1072 } 1073 }
1073 1074
1074 emit activity(tr("Change time-stretch factor to %1").arg(factor)); 1075 emit activity(tr("Change time-stretch factor to %1").arg(factor));
1075 } 1076 }
1076 1077
1077 size_t 1078 int
1078 AudioCallbackPlaySource::getSourceSamples(size_t ucount, float **buffer) 1079 AudioCallbackPlaySource::getSourceSamples(int ucount, float **buffer)
1079 { 1080 {
1080 int count = ucount; 1081 int count = ucount;
1081 1082
1082 if (!m_playing) { 1083 if (!m_playing) {
1083 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1084 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1084 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not playing" << endl; 1085 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not playing" << endl;
1085 #endif 1086 #endif
1086 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { 1087 for (int ch = 0; ch < getTargetChannelCount(); ++ch) {
1087 for (int i = 0; i < count; ++i) { 1088 for (int i = 0; i < count; ++i) {
1088 buffer[ch][i] = 0.0; 1089 buffer[ch][i] = 0.0;
1089 } 1090 }
1090 } 1091 }
1091 return 0; 1092 return 0;
1096 #endif 1097 #endif
1097 1098
1098 // Ensure that all buffers have at least the amount of data we 1099 // Ensure that all buffers have at least the amount of data we
1099 // need -- else reduce the size of our requests correspondingly 1100 // need -- else reduce the size of our requests correspondingly
1100 1101
1101 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { 1102 for (int ch = 0; ch < getTargetChannelCount(); ++ch) {
1102 1103
1103 RingBuffer<float> *rb = getReadRingBuffer(ch); 1104 RingBuffer<float> *rb = getReadRingBuffer(ch);
1104 1105
1105 if (!rb) { 1106 if (!rb) {
1106 cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: " 1107 cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: "
1108 << ", returning no data here" << endl; 1109 << ", returning no data here" << endl;
1109 count = 0; 1110 count = 0;
1110 break; 1111 break;
1111 } 1112 }
1112 1113
1113 size_t rs = rb->getReadSpace(); 1114 int rs = rb->getReadSpace();
1114 if (rs < count) { 1115 if (rs < count) {
1115 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1116 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1116 cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: " 1117 cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: "
1117 << "Ring buffer for channel " << ch << " has only " 1118 << "Ring buffer for channel " << ch << " has only "
1118 << rs << " (of " << count << ") samples available (" 1119 << rs << " (of " << count << ") samples available ("
1159 1160
1160 if (!ts || ratio == 1.f) { 1161 if (!ts || ratio == 1.f) {
1161 1162
1162 int got = 0; 1163 int got = 0;
1163 1164
1164 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { 1165 for (int ch = 0; ch < getTargetChannelCount(); ++ch) {
1165 1166
1166 RingBuffer<float> *rb = getReadRingBuffer(ch); 1167 RingBuffer<float> *rb = getReadRingBuffer(ch);
1167 1168
1168 if (rb) { 1169 if (rb) {
1169 1170
1170 // this is marginally more likely to leave our channels in 1171 // this is marginally more likely to leave our channels in
1171 // sync after a processing failure than just passing "count": 1172 // sync after a processing failure than just passing "count":
1172 size_t request = count; 1173 int request = count;
1173 if (ch > 0) request = got; 1174 if (ch > 0) request = got;
1174 1175
1175 got = rb->read(buffer[ch], request); 1176 got = rb->read(buffer[ch], request);
1176 1177
1177 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1178 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1178 cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << endl; 1179 cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << endl;
1179 #endif 1180 #endif
1180 } 1181 }
1181 1182
1182 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { 1183 for (int ch = 0; ch < getTargetChannelCount(); ++ch) {
1183 for (int i = got; i < count; ++i) { 1184 for (int i = got; i < count; ++i) {
1184 buffer[ch][i] = 0.0; 1185 buffer[ch][i] = 0.0;
1185 } 1186 }
1186 } 1187 }
1187 } 1188 }
1195 m_condition.wakeAll(); 1196 m_condition.wakeAll();
1196 1197
1197 return got; 1198 return got;
1198 } 1199 }
1199 1200
1200 size_t channels = getTargetChannelCount(); 1201 int channels = getTargetChannelCount();
1201 size_t available; 1202 int available;
1202 int warned = 0; 1203 int warned = 0;
1203 size_t fedToStretcher = 0; 1204 int fedToStretcher = 0;
1204 1205
1205 // The input block for a given output is approx output / ratio, 1206 // The input block for a given output is approx output / ratio,
1206 // but we can't predict it exactly, for an adaptive timestretcher. 1207 // but we can't predict it exactly, for an adaptive timestretcher.
1207 1208
1208 while ((available = ts->available()) < count) { 1209 while ((available = ts->available()) < count) {
1209 1210
1210 size_t reqd = lrintf((count - available) / ratio); 1211 int reqd = lrintf((count - available) / ratio);
1211 reqd = std::max(reqd, ts->getSamplesRequired()); 1212 reqd = std::max(reqd, (int)ts->getSamplesRequired());
1212 if (reqd == 0) reqd = 1; 1213 if (reqd == 0) reqd = 1;
1213 1214
1214 size_t got = reqd; 1215 int got = reqd;
1215 1216
1216 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1217 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1217 cerr << "reqd = " <<reqd << ", channels = " << channels << ", ic = " << m_stretcherInputCount << endl; 1218 cerr << "reqd = " <<reqd << ", channels = " << channels << ", ic = " << m_stretcherInputCount << endl;
1218 #endif 1219 #endif
1219 1220
1220 for (size_t c = 0; c < channels; ++c) { 1221 for (int c = 0; c < channels; ++c) {
1221 if (c >= m_stretcherInputCount) continue; 1222 if (c >= m_stretcherInputCount) continue;
1222 if (reqd > m_stretcherInputSizes[c]) { 1223 if (reqd > m_stretcherInputSizes[c]) {
1223 if (c == 0) { 1224 if (c == 0) {
1224 cerr << "WARNING: resizing stretcher input buffer from " << m_stretcherInputSizes[c] << " to " << (reqd * 2) << endl; 1225 cerr << "WARNING: resizing stretcher input buffer from " << m_stretcherInputSizes[c] << " to " << (reqd * 2) << endl;
1225 } 1226 }
1227 m_stretcherInputSizes[c] = reqd * 2; 1228 m_stretcherInputSizes[c] = reqd * 2;
1228 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]]; 1229 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]];
1229 } 1230 }
1230 } 1231 }
1231 1232
1232 for (size_t c = 0; c < channels; ++c) { 1233 for (int c = 0; c < channels; ++c) {
1233 if (c >= m_stretcherInputCount) continue; 1234 if (c >= m_stretcherInputCount) continue;
1234 RingBuffer<float> *rb = getReadRingBuffer(c); 1235 RingBuffer<float> *rb = getReadRingBuffer(c);
1235 if (rb) { 1236 if (rb) {
1236 size_t gotHere; 1237 int gotHere;
1237 if (stretchChannels == 1 && c > 0) { 1238 if (stretchChannels == 1 && c > 0) {
1238 gotHere = rb->readAdding(m_stretcherInputs[0], got); 1239 gotHere = rb->readAdding(m_stretcherInputs[0], got);
1239 } else { 1240 } else {
1240 gotHere = rb->read(m_stretcherInputs[c], got); 1241 gotHere = rb->read(m_stretcherInputs[c], got);
1241 } 1242 }
1288 1289
1289 return count; 1290 return count;
1290 } 1291 }
1291 1292
1292 void 1293 void
1293 AudioCallbackPlaySource::applyAuditioningEffect(size_t count, float **buffers) 1294 AudioCallbackPlaySource::applyAuditioningEffect(int count, float **buffers)
1294 { 1295 {
1295 if (m_auditioningPluginBypassed) return; 1296 if (m_auditioningPluginBypassed) return;
1296 RealTimePluginInstance *plugin = m_auditioningPlugin; 1297 RealTimePluginInstance *plugin = m_auditioningPlugin;
1297 if (!plugin) return; 1298 if (!plugin) return;
1298 1299
1299 if (plugin->getAudioInputCount() != getTargetChannelCount()) { 1300 if ((int)plugin->getAudioInputCount() != getTargetChannelCount()) {
1300 // cerr << "plugin input count " << plugin->getAudioInputCount() 1301 // cerr << "plugin input count " << plugin->getAudioInputCount()
1301 // << " != our channel count " << getTargetChannelCount() 1302 // << " != our channel count " << getTargetChannelCount()
1302 // << endl; 1303 // << endl;
1303 return; 1304 return;
1304 } 1305 }
1305 if (plugin->getAudioOutputCount() != getTargetChannelCount()) { 1306 if ((int)plugin->getAudioOutputCount() != getTargetChannelCount()) {
1306 // cerr << "plugin output count " << plugin->getAudioOutputCount() 1307 // cerr << "plugin output count " << plugin->getAudioOutputCount()
1307 // << " != our channel count " << getTargetChannelCount() 1308 // << " != our channel count " << getTargetChannelCount()
1308 // << endl; 1309 // << endl;
1309 return; 1310 return;
1310 } 1311 }
1311 if (plugin->getBufferSize() < count) { 1312 if ((int)plugin->getBufferSize() < count) {
1312 // cerr << "plugin buffer size " << plugin->getBufferSize() 1313 // cerr << "plugin buffer size " << plugin->getBufferSize()
1313 // << " < our block size " << count 1314 // << " < our block size " << count
1314 // << endl; 1315 // << endl;
1315 return; 1316 return;
1316 } 1317 }
1317 1318
1318 float **ib = plugin->getAudioInputBuffers(); 1319 float **ib = plugin->getAudioInputBuffers();
1319 float **ob = plugin->getAudioOutputBuffers(); 1320 float **ob = plugin->getAudioOutputBuffers();
1320 1321
1321 for (size_t c = 0; c < getTargetChannelCount(); ++c) { 1322 for (int c = 0; c < getTargetChannelCount(); ++c) {
1322 for (size_t i = 0; i < count; ++i) { 1323 for (int i = 0; i < count; ++i) {
1323 ib[c][i] = buffers[c][i]; 1324 ib[c][i] = buffers[c][i];
1324 } 1325 }
1325 } 1326 }
1326 1327
1327 plugin->run(Vamp::RealTime::zeroTime, count); 1328 plugin->run(Vamp::RealTime::zeroTime, count);
1328 1329
1329 for (size_t c = 0; c < getTargetChannelCount(); ++c) { 1330 for (int c = 0; c < getTargetChannelCount(); ++c) {
1330 for (size_t i = 0; i < count; ++i) { 1331 for (int i = 0; i < count; ++i) {
1331 buffers[c][i] = ob[c][i]; 1332 buffers[c][i] = ob[c][i];
1332 } 1333 }
1333 } 1334 }
1334 } 1335 }
1335 1336
1336 // Called from fill thread, m_playing true, mutex held 1337 // Called from fill thread, m_playing true, mutex held
1337 bool 1338 bool
1338 AudioCallbackPlaySource::fillBuffers() 1339 AudioCallbackPlaySource::fillBuffers()
1339 { 1340 {
1340 static float *tmp = 0; 1341 static float *tmp = 0;
1341 static size_t tmpSize = 0; 1342 static int tmpSize = 0;
1342 1343
1343 size_t space = 0; 1344 int space = 0;
1344 for (size_t c = 0; c < getTargetChannelCount(); ++c) { 1345 for (int c = 0; c < getTargetChannelCount(); ++c) {
1345 RingBuffer<float> *wb = getWriteRingBuffer(c); 1346 RingBuffer<float> *wb = getWriteRingBuffer(c);
1346 if (wb) { 1347 if (wb) {
1347 size_t spaceHere = wb->getWriteSpace(); 1348 int spaceHere = wb->getWriteSpace();
1348 if (c == 0 || spaceHere < space) space = spaceHere; 1349 if (c == 0 || spaceHere < space) space = spaceHere;
1349 } 1350 }
1350 } 1351 }
1351 1352
1352 if (space == 0) { 1353 if (space == 0) {
1354 cout << "AudioCallbackPlaySourceFillThread: no space to fill" << endl; 1355 cout << "AudioCallbackPlaySourceFillThread: no space to fill" << endl;
1355 #endif 1356 #endif
1356 return false; 1357 return false;
1357 } 1358 }
1358 1359
1359 size_t f = m_writeBufferFill; 1360 int f = m_writeBufferFill;
1360 1361
1361 bool readWriteEqual = (m_readBuffers == m_writeBuffers); 1362 bool readWriteEqual = (m_readBuffers == m_writeBuffers);
1362 1363
1363 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1364 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1364 if (!readWriteEqual) { 1365 if (!readWriteEqual) {
1375 1376
1376 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1377 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1377 cout << (resample ? "" : "not ") << "resampling (source " << getSourceSampleRate() << ", target " << getTargetSampleRate() << ")" << endl; 1378 cout << (resample ? "" : "not ") << "resampling (source " << getSourceSampleRate() << ", target " << getTargetSampleRate() << ")" << endl;
1378 #endif 1379 #endif
1379 1380
1380 size_t channels = getTargetChannelCount(); 1381 int channels = getTargetChannelCount();
1381 1382
1382 size_t orig = space; 1383 int orig = space;
1383 size_t got = 0; 1384 int got = 0;
1384 1385
1385 static float **bufferPtrs = 0; 1386 static float **bufferPtrs = 0;
1386 static size_t bufferPtrCount = 0; 1387 static int bufferPtrCount = 0;
1387 1388
1388 if (bufferPtrCount < channels) { 1389 if (bufferPtrCount < channels) {
1389 if (bufferPtrs) delete[] bufferPtrs; 1390 if (bufferPtrs) delete[] bufferPtrs;
1390 bufferPtrs = new float *[channels]; 1391 bufferPtrs = new float *[channels];
1391 bufferPtrCount = channels; 1392 bufferPtrCount = channels;
1392 } 1393 }
1393 1394
1394 size_t generatorBlockSize = m_audioGenerator->getBlockSize(); 1395 int generatorBlockSize = m_audioGenerator->getBlockSize();
1395 1396
1396 if (resample && !m_converter) { 1397 if (resample && !m_converter) {
1397 static bool warned = false; 1398 static bool warned = false;
1398 if (!warned) { 1399 if (!warned) {
1399 cerr << "WARNING: sample rates differ, but no converter available!" << endl; 1400 cerr << "WARNING: sample rates differ, but no converter available!" << endl;
1403 1404
1404 if (resample && m_converter) { 1405 if (resample && m_converter) {
1405 1406
1406 double ratio = 1407 double ratio =
1407 double(getTargetSampleRate()) / double(getSourceSampleRate()); 1408 double(getTargetSampleRate()) / double(getSourceSampleRate());
1408 orig = size_t(orig / ratio + 0.1); 1409 orig = int(orig / ratio + 0.1);
1409 1410
1410 // orig must be a multiple of generatorBlockSize 1411 // orig must be a multiple of generatorBlockSize
1411 orig = (orig / generatorBlockSize) * generatorBlockSize; 1412 orig = (orig / generatorBlockSize) * generatorBlockSize;
1412 if (orig == 0) return false; 1413 if (orig == 0) return false;
1413 1414
1414 size_t work = std::max(orig, space); 1415 int work = std::max(orig, space);
1415 1416
1416 // We only allocate one buffer, but we use it in two halves. 1417 // We only allocate one buffer, but we use it in two halves.
1417 // We place the non-interleaved values in the second half of 1418 // We place the non-interleaved values in the second half of
1418 // the buffer (orig samples for channel 0, orig samples for 1419 // the buffer (orig samples for channel 0, orig samples for
1419 // channel 1 etc), and then interleave them into the first 1420 // channel 1 etc), and then interleave them into the first
1432 1433
1433 float *nonintlv = tmp + channels * work; 1434 float *nonintlv = tmp + channels * work;
1434 float *intlv = tmp; 1435 float *intlv = tmp;
1435 float *srcout = tmp + channels * work; 1436 float *srcout = tmp + channels * work;
1436 1437
1437 for (size_t c = 0; c < channels; ++c) { 1438 for (int c = 0; c < channels; ++c) {
1438 for (size_t i = 0; i < orig; ++i) { 1439 for (int i = 0; i < orig; ++i) {
1439 nonintlv[channels * i + c] = 0.0f; 1440 nonintlv[channels * i + c] = 0.0f;
1440 } 1441 }
1441 } 1442 }
1442 1443
1443 for (size_t c = 0; c < channels; ++c) { 1444 for (int c = 0; c < channels; ++c) {
1444 bufferPtrs[c] = nonintlv + c * orig; 1445 bufferPtrs[c] = nonintlv + c * orig;
1445 } 1446 }
1446 1447
1447 got = mixModels(f, orig, bufferPtrs); // also modifies f 1448 got = mixModels(f, orig, bufferPtrs); // also modifies f
1448 1449
1449 // and interleave into first half 1450 // and interleave into first half
1450 for (size_t c = 0; c < channels; ++c) { 1451 for (int c = 0; c < channels; ++c) {
1451 for (size_t i = 0; i < got; ++i) { 1452 for (int i = 0; i < got; ++i) {
1452 float sample = nonintlv[c * got + i]; 1453 float sample = nonintlv[c * got + i];
1453 intlv[channels * i + c] = sample; 1454 intlv[channels * i + c] = sample;
1454 } 1455 }
1455 } 1456 }
1456 1457
1471 err = src_process(m_crapConverter, &data); 1472 err = src_process(m_crapConverter, &data);
1472 } else { 1473 } else {
1473 err = src_process(m_converter, &data); 1474 err = src_process(m_converter, &data);
1474 } 1475 }
1475 1476
1476 size_t toCopy = size_t(got * ratio + 0.1); 1477 int toCopy = int(got * ratio + 0.1);
1477 1478
1478 if (err) { 1479 if (err) {
1479 cerr 1480 cerr
1480 << "AudioCallbackPlaySourceFillThread: ERROR in samplerate conversion: " 1481 << "AudioCallbackPlaySourceFillThread: ERROR in samplerate conversion: "
1481 << src_strerror(err) << endl; 1482 << src_strerror(err) << endl;
1486 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1487 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1487 cout << "Resampled " << got << " frames to " << toCopy << " frames" << endl; 1488 cout << "Resampled " << got << " frames to " << toCopy << " frames" << endl;
1488 #endif 1489 #endif
1489 } 1490 }
1490 1491
1491 for (size_t c = 0; c < channels; ++c) { 1492 for (int c = 0; c < channels; ++c) {
1492 for (size_t i = 0; i < toCopy; ++i) { 1493 for (int i = 0; i < toCopy; ++i) {
1493 tmp[i] = srcout[channels * i + c]; 1494 tmp[i] = srcout[channels * i + c];
1494 } 1495 }
1495 RingBuffer<float> *wb = getWriteRingBuffer(c); 1496 RingBuffer<float> *wb = getWriteRingBuffer(c);
1496 if (wb) wb->write(tmp, toCopy); 1497 if (wb) wb->write(tmp, toCopy);
1497 } 1498 }
1500 if (readWriteEqual) m_readBufferFill = f; 1501 if (readWriteEqual) m_readBufferFill = f;
1501 1502
1502 } else { 1503 } else {
1503 1504
1504 // space must be a multiple of generatorBlockSize 1505 // space must be a multiple of generatorBlockSize
1505 size_t reqSpace = space; 1506 int reqSpace = space;
1506 space = (reqSpace / generatorBlockSize) * generatorBlockSize; 1507 space = (reqSpace / generatorBlockSize) * generatorBlockSize;
1507 if (space == 0) { 1508 if (space == 0) {
1508 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1509 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1509 cout << "requested fill of " << reqSpace 1510 cout << "requested fill of " << reqSpace
1510 << " is less than generator block size of " 1511 << " is less than generator block size of "
1517 delete[] tmp; 1518 delete[] tmp;
1518 tmp = new float[channels * space]; 1519 tmp = new float[channels * space];
1519 tmpSize = channels * space; 1520 tmpSize = channels * space;
1520 } 1521 }
1521 1522
1522 for (size_t c = 0; c < channels; ++c) { 1523 for (int c = 0; c < channels; ++c) {
1523 1524
1524 bufferPtrs[c] = tmp + c * space; 1525 bufferPtrs[c] = tmp + c * space;
1525 1526
1526 for (size_t i = 0; i < space; ++i) { 1527 for (int i = 0; i < space; ++i) {
1527 tmp[c * space + i] = 0.0f; 1528 tmp[c * space + i] = 0.0f;
1528 } 1529 }
1529 } 1530 }
1530 1531
1531 size_t got = mixModels(f, space, bufferPtrs); // also modifies f 1532 int got = mixModels(f, space, bufferPtrs); // also modifies f
1532 1533
1533 for (size_t c = 0; c < channels; ++c) { 1534 for (int c = 0; c < channels; ++c) {
1534 1535
1535 RingBuffer<float> *wb = getWriteRingBuffer(c); 1536 RingBuffer<float> *wb = getWriteRingBuffer(c);
1536 if (wb) { 1537 if (wb) {
1537 size_t actual = wb->write(bufferPtrs[c], got); 1538 int actual = wb->write(bufferPtrs[c], got);
1538 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1539 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1539 cout << "Wrote " << actual << " samples for ch " << c << ", now " 1540 cout << "Wrote " << actual << " samples for ch " << c << ", now "
1540 << wb->getReadSpace() << " to read" 1541 << wb->getReadSpace() << " to read"
1541 << endl; 1542 << endl;
1542 #endif 1543 #endif
1559 } 1560 }
1560 1561
1561 return true; 1562 return true;
1562 } 1563 }
1563 1564
1564 size_t 1565 int
1565 AudioCallbackPlaySource::mixModels(size_t &frame, size_t count, float **buffers) 1566 AudioCallbackPlaySource::mixModels(int &frame, int count, float **buffers)
1566 { 1567 {
1567 size_t processed = 0; 1568 int processed = 0;
1568 size_t chunkStart = frame; 1569 int chunkStart = frame;
1569 size_t chunkSize = count; 1570 int chunkSize = count;
1570 size_t selectionSize = 0; 1571 int selectionSize = 0;
1571 size_t nextChunkStart = chunkStart + chunkSize; 1572 int nextChunkStart = chunkStart + chunkSize;
1572 1573
1573 bool looping = m_viewManager->getPlayLoopMode(); 1574 bool looping = m_viewManager->getPlayLoopMode();
1574 bool constrained = (m_viewManager->getPlaySelectionMode() && 1575 bool constrained = (m_viewManager->getPlaySelectionMode() &&
1575 !m_viewManager->getSelections().empty()); 1576 !m_viewManager->getSelections().empty());
1576 1577
1577 static float **chunkBufferPtrs = 0; 1578 static float **chunkBufferPtrs = 0;
1578 static size_t chunkBufferPtrCount = 0; 1579 static int chunkBufferPtrCount = 0;
1579 size_t channels = getTargetChannelCount(); 1580 int channels = getTargetChannelCount();
1580 1581
1581 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1582 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1582 cout << "Selection playback: start " << frame << ", size " << count <<", channels " << channels << endl; 1583 cout << "Selection playback: start " << frame << ", size " << count <<", channels " << channels << endl;
1583 #endif 1584 #endif
1584 1585
1586 if (chunkBufferPtrs) delete[] chunkBufferPtrs; 1587 if (chunkBufferPtrs) delete[] chunkBufferPtrs;
1587 chunkBufferPtrs = new float *[channels]; 1588 chunkBufferPtrs = new float *[channels];
1588 chunkBufferPtrCount = channels; 1589 chunkBufferPtrCount = channels;
1589 } 1590 }
1590 1591
1591 for (size_t c = 0; c < channels; ++c) { 1592 for (int c = 0; c < channels; ++c) {
1592 chunkBufferPtrs[c] = buffers[c]; 1593 chunkBufferPtrs[c] = buffers[c];
1593 } 1594 }
1594 1595
1595 while (processed < count) { 1596 while (processed < count) {
1596 1597
1597 chunkSize = count - processed; 1598 chunkSize = count - processed;
1598 nextChunkStart = chunkStart + chunkSize; 1599 nextChunkStart = chunkStart + chunkSize;
1599 selectionSize = 0; 1600 selectionSize = 0;
1600 1601
1601 size_t fadeIn = 0, fadeOut = 0; 1602 int fadeIn = 0, fadeOut = 0;
1602 1603
1603 if (constrained) { 1604 if (constrained) {
1604 1605
1605 size_t rChunkStart = 1606 int rChunkStart =
1606 m_viewManager->alignPlaybackFrameToReference(chunkStart); 1607 m_viewManager->alignPlaybackFrameToReference(chunkStart);
1607 1608
1608 Selection selection = 1609 Selection selection =
1609 m_viewManager->getContainingSelection(rChunkStart, true); 1610 m_viewManager->getContainingSelection(rChunkStart, true);
1610 1611
1622 chunkSize = 0; 1623 chunkSize = 0;
1623 nextChunkStart = chunkStart; 1624 nextChunkStart = chunkStart;
1624 1625
1625 } else { 1626 } else {
1626 1627
1627 size_t sf = m_viewManager->alignReferenceToPlaybackFrame 1628 int sf = m_viewManager->alignReferenceToPlaybackFrame
1628 (selection.getStartFrame()); 1629 (selection.getStartFrame());
1629 size_t ef = m_viewManager->alignReferenceToPlaybackFrame 1630 int ef = m_viewManager->alignReferenceToPlaybackFrame
1630 (selection.getEndFrame()); 1631 (selection.getEndFrame());
1631 1632
1632 selectionSize = ef - sf; 1633 selectionSize = ef - sf;
1633 1634
1634 if (chunkStart < sf) { 1635 if (chunkStart < sf) {
1672 1673
1673 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1674 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1674 cout << "Selection playback: chunk at " << chunkStart << " -> " << nextChunkStart << " (size " << chunkSize << ")" << endl; 1675 cout << "Selection playback: chunk at " << chunkStart << " -> " << nextChunkStart << " (size " << chunkSize << ")" << endl;
1675 #endif 1676 #endif
1676 1677
1677 size_t got = 0;
1678
1679 if (selectionSize < 100) { 1678 if (selectionSize < 100) {
1680 fadeIn = 0; 1679 fadeIn = 0;
1681 fadeOut = 0; 1680 fadeOut = 0;
1682 } else if (selectionSize < 300) { 1681 } else if (selectionSize < 300) {
1683 if (fadeIn > 0) fadeIn = 10; 1682 if (fadeIn > 0) fadeIn = 10;
1697 } 1696 }
1698 1697
1699 for (std::set<Model *>::iterator mi = m_models.begin(); 1698 for (std::set<Model *>::iterator mi = m_models.begin();
1700 mi != m_models.end(); ++mi) { 1699 mi != m_models.end(); ++mi) {
1701 1700
1702 got = m_audioGenerator->mixModel(*mi, chunkStart, 1701 (void) m_audioGenerator->mixModel(*mi, chunkStart,
1703 chunkSize, chunkBufferPtrs, 1702 chunkSize, chunkBufferPtrs,
1704 fadeIn, fadeOut); 1703 fadeIn, fadeOut);
1705 } 1704 }
1706 1705
1707 for (size_t c = 0; c < channels; ++c) { 1706 for (int c = 0; c < channels; ++c) {
1708 chunkBufferPtrs[c] += chunkSize; 1707 chunkBufferPtrs[c] += chunkSize;
1709 } 1708 }
1710 1709
1711 processed += chunkSize; 1710 processed += chunkSize;
1712 chunkStart = nextChunkStart; 1711 chunkStart = nextChunkStart;
1724 AudioCallbackPlaySource::unifyRingBuffers() 1723 AudioCallbackPlaySource::unifyRingBuffers()
1725 { 1724 {
1726 if (m_readBuffers == m_writeBuffers) return; 1725 if (m_readBuffers == m_writeBuffers) return;
1727 1726
1728 // only unify if there will be something to read 1727 // only unify if there will be something to read
1729 for (size_t c = 0; c < getTargetChannelCount(); ++c) { 1728 for (int c = 0; c < getTargetChannelCount(); ++c) {
1730 RingBuffer<float> *wb = getWriteRingBuffer(c); 1729 RingBuffer<float> *wb = getWriteRingBuffer(c);
1731 if (wb) { 1730 if (wb) {
1732 if (wb->getReadSpace() < m_blockSize * 2) { 1731 if (wb->getReadSpace() < m_blockSize * 2) {
1733 if ((m_writeBufferFill + m_blockSize * 2) < 1732 if ((m_writeBufferFill + m_blockSize * 2) <
1734 m_lastModelEndFrame) { 1733 m_lastModelEndFrame) {
1742 } 1741 }
1743 break; 1742 break;
1744 } 1743 }
1745 } 1744 }
1746 1745
1747 size_t rf = m_readBufferFill; 1746 int rf = m_readBufferFill;
1748 RingBuffer<float> *rb = getReadRingBuffer(0); 1747 RingBuffer<float> *rb = getReadRingBuffer(0);
1749 if (rb) { 1748 if (rb) {
1750 size_t rs = rb->getReadSpace(); 1749 int rs = rb->getReadSpace();
1751 //!!! incorrect when in non-contiguous selection, see comments elsewhere 1750 //!!! incorrect when in non-contiguous selection, see comments elsewhere
1752 // cout << "rs = " << rs << endl; 1751 // cout << "rs = " << rs << endl;
1753 if (rs < rf) rf -= rs; 1752 if (rs < rf) rf -= rs;
1754 else rf = 0; 1753 else rf = 0;
1755 } 1754 }
1756 1755
1757 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1756 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1758 SVDEBUG << "AudioCallbackPlaySource::unifyRingBuffers: m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << endl; 1757 SVDEBUG << "AudioCallbackPlaySource::unifyRingBuffers: m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << endl;
1759 #endif 1758 #endif
1760 1759
1761 size_t wf = m_writeBufferFill; 1760 int wf = m_writeBufferFill;
1762 size_t skip = 0; 1761 int skip = 0;
1763 for (size_t c = 0; c < getTargetChannelCount(); ++c) { 1762 for (int c = 0; c < getTargetChannelCount(); ++c) {
1764 RingBuffer<float> *wb = getWriteRingBuffer(c); 1763 RingBuffer<float> *wb = getWriteRingBuffer(c);
1765 if (wb) { 1764 if (wb) {
1766 if (c == 0) { 1765 if (c == 0) {
1767 1766
1768 size_t wrs = wb->getReadSpace(); 1767 int wrs = wb->getReadSpace();
1769 // cout << "wrs = " << wrs << endl; 1768 // cout << "wrs = " << wrs << endl;
1770 1769
1771 if (wrs < wf) wf -= wrs; 1770 if (wrs < wf) wf -= wrs;
1772 else wf = 0; 1771 else wf = 0;
1773 // cout << "wf = " << wf << endl; 1772 // cout << "wf = " << wf << endl;
1831 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1830 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1832 if (!s.m_playing) cout << endl; 1831 if (!s.m_playing) cout << endl;
1833 cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << endl; 1832 cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << endl;
1834 #endif 1833 #endif
1835 1834
1836 s.m_condition.wait(&s.m_mutex, size_t(ms)); 1835 s.m_condition.wait(&s.m_mutex, int(ms));
1837 } 1836 }
1838 1837
1839 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1838 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1840 cout << "AudioCallbackPlaySourceFillThread: awoken" << endl; 1839 cout << "AudioCallbackPlaySourceFillThread: awoken" << endl;
1841 #endif 1840 #endif
1853 1852
1854 if (playing && !previouslyPlaying) { 1853 if (playing && !previouslyPlaying) {
1855 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1854 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1856 cout << "AudioCallbackPlaySourceFillThread: playback state changed, resetting" << endl; 1855 cout << "AudioCallbackPlaySourceFillThread: playback state changed, resetting" << endl;
1857 #endif 1856 #endif
1858 for (size_t c = 0; c < s.getTargetChannelCount(); ++c) { 1857 for (int c = 0; c < s.getTargetChannelCount(); ++c) {
1859 RingBuffer<float> *rb = s.getReadRingBuffer(c); 1858 RingBuffer<float> *rb = s.getReadRingBuffer(c);
1860 if (rb) rb->reset(); 1859 if (rb) rb->reset();
1861 } 1860 }
1862 } 1861 }
1863 previouslyPlaying = playing; 1862 previouslyPlaying = playing;