Mercurial > hg > svapp
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; |