comparison audioio/AudioCallbackPlaySource.cpp @ 130:4c9c04645685

* Reduce time stretcher to one channel when overload occurs
author Chris Cannam
date Mon, 07 Jul 2008 16:49:53 +0000
parents ab861544f998
children 883f7fc7fd34
comparison
equal deleted inserted replaced
129:df5f16b3c925 130:4c9c04645685
67 m_auditioningPlugin(0), 67 m_auditioningPlugin(0),
68 m_auditioningPluginBypassed(false), 68 m_auditioningPluginBypassed(false),
69 m_playStartFrame(0), 69 m_playStartFrame(0),
70 m_playStartFramePassed(false), 70 m_playStartFramePassed(false),
71 m_timeStretcher(0), 71 m_timeStretcher(0),
72 m_monoStretcher(0),
72 m_stretchRatio(1.0), 73 m_stretchRatio(1.0),
73 m_stretcherInputCount(0), 74 m_stretcherInputCount(0),
74 m_stretcherInputs(0), 75 m_stretcherInputs(0),
75 m_stretcherInputSizes(0), 76 m_stretcherInputSizes(0),
76 m_fillThread(0), 77 m_fillThread(0),
119 for (size_t i = 0; i < m_stretcherInputCount; ++i) { 120 for (size_t i = 0; i < m_stretcherInputCount; ++i) {
120 delete[] m_stretcherInputs[i]; 121 delete[] m_stretcherInputs[i];
121 } 122 }
122 delete[] m_stretcherInputSizes; 123 delete[] m_stretcherInputSizes;
123 delete[] m_stretcherInputs; 124 delete[] m_stretcherInputs;
125
126 delete m_timeStretcher;
127 delete m_monoStretcher;
124 128
125 m_bufferScavenger.scavenge(true); 129 m_bufferScavenger.scavenge(true);
126 m_pluginScavenger.scavenge(true); 130 m_pluginScavenger.scavenge(true);
127 } 131 }
128 132
386 m_mutex.lock(); 390 m_mutex.lock();
387 391
388 if (m_timeStretcher) { 392 if (m_timeStretcher) {
389 m_timeStretcher->reset(); 393 m_timeStretcher->reset();
390 } 394 }
395 if (m_monoStretcher) {
396 m_monoStretcher->reset();
397 }
391 398
392 m_readBufferFill = m_writeBufferFill = startFrame; 399 m_readBufferFill = m_writeBufferFill = startFrame;
393 if (m_readBuffers) { 400 if (m_readBuffers) {
394 for (size_t c = 0; c < getTargetChannelCount(); ++c) { 401 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
395 RingBuffer<float> *rb = getReadRingBuffer(c); 402 RingBuffer<float> *rb = getReadRingBuffer(c);
467 } 474 }
468 475
469 void 476 void
470 AudioCallbackPlaySource::audioProcessingOverload() 477 AudioCallbackPlaySource::audioProcessingOverload()
471 { 478 {
479 std::cerr << "Audio processing overload!" << std::endl;
480
481 if (!m_playing) return;
482
472 RealTimePluginInstance *ap = m_auditioningPlugin; 483 RealTimePluginInstance *ap = m_auditioningPlugin;
473 if (ap && m_playing && !m_auditioningPluginBypassed) { 484 if (ap && !m_auditioningPluginBypassed) {
474 m_auditioningPluginBypassed = true; 485 m_auditioningPluginBypassed = true;
475 emit audioOverloadPluginDisabled(); 486 emit audioOverloadPluginDisabled();
487 return;
488 }
489
490 if (m_timeStretcher &&
491 m_timeStretcher->getTimeRatio() < 1.0 &&
492 m_stretcherInputCount > 1 &&
493 m_monoStretcher && !m_stretchMono) {
494 m_stretchMono = true;
495 emit audioTimeStretchMultiChannelDisabled();
496 return;
476 } 497 }
477 } 498 }
478 499
479 void 500 void
480 AudioCallbackPlaySource::setTarget(AudioCallbackPlayTarget *target, size_t size) 501 AudioCallbackPlaySource::setTarget(AudioCallbackPlayTarget *target, size_t size)
954 RubberBandStretcher *stretcher = new RubberBandStretcher 975 RubberBandStretcher *stretcher = new RubberBandStretcher
955 (getTargetSampleRate(), 976 (getTargetSampleRate(),
956 m_stretcherInputCount, 977 m_stretcherInputCount,
957 RubberBandStretcher::OptionProcessRealTime, 978 RubberBandStretcher::OptionProcessRealTime,
958 factor); 979 factor);
980 RubberBandStretcher *monoStretcher = new RubberBandStretcher
981 (getTargetSampleRate(),
982 1,
983 RubberBandStretcher::OptionProcessRealTime,
984 factor);
959 m_stretcherInputs = new float *[m_stretcherInputCount]; 985 m_stretcherInputs = new float *[m_stretcherInputCount];
960 m_stretcherInputSizes = new size_t[m_stretcherInputCount]; 986 m_stretcherInputSizes = new size_t[m_stretcherInputCount];
961 for (size_t c = 0; c < m_stretcherInputCount; ++c) { 987 for (size_t c = 0; c < m_stretcherInputCount; ++c) {
962 m_stretcherInputSizes[c] = 16384; 988 m_stretcherInputSizes[c] = 16384;
963 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]]; 989 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]];
964 } 990 }
991 m_monoStretcher = monoStretcher;
965 m_timeStretcher = stretcher; 992 m_timeStretcher = stretcher;
966 return; 993 return;
967 } 994 }
968 } 995 }
969 996
970 size_t 997 size_t
971 AudioCallbackPlaySource::getSourceSamples(size_t count, float **buffer) 998 AudioCallbackPlaySource::getSourceSamples(size_t ucount, float **buffer)
972 { 999 {
1000 int count = ucount;
1001
973 if (!m_playing) { 1002 if (!m_playing) {
974 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { 1003 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
975 for (size_t i = 0; i < count; ++i) { 1004 for (int i = 0; i < count; ++i) {
976 buffer[ch][i] = 0.0; 1005 buffer[ch][i] = 0.0;
977 } 1006 }
978 } 1007 }
979 return 0; 1008 return 0;
980 } 1009 }
1007 } 1036 }
1008 1037
1009 if (count == 0) return 0; 1038 if (count == 0) return 0;
1010 1039
1011 RubberBandStretcher *ts = m_timeStretcher; 1040 RubberBandStretcher *ts = m_timeStretcher;
1041 RubberBandStretcher *ms = m_monoStretcher;
1042
1012 float ratio = ts ? ts->getTimeRatio() : 1.f; 1043 float ratio = ts ? ts->getTimeRatio() : 1.f;
1013 1044
1014 if (ratio != m_stretchRatio) { 1045 if (ratio != m_stretchRatio) {
1015 if (!ts) { 1046 if (!ts) {
1016 std::cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: Time ratio change to " << m_stretchRatio << " is pending, but no stretcher is set" << std::endl; 1047 std::cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: Time ratio change to " << m_stretchRatio << " is pending, but no stretcher is set" << std::endl;
1017 m_stretchRatio = 1.f; 1048 m_stretchRatio = 1.f;
1018 } else { 1049 } else {
1019 ts->setTimeRatio(m_stretchRatio); 1050 ts->setTimeRatio(m_stretchRatio);
1051 if (ms) ms->setTimeRatio(m_stretchRatio);
1052 if (m_stretchRatio >= 1.0) m_stretchMono = false;
1053 }
1054 }
1055
1056 int stretchChannels = m_stretcherInputCount;
1057 if (m_stretchMono) {
1058 if (ms) {
1059 ts = ms;
1060 stretchChannels = 1;
1061 } else {
1062 m_stretchMono = false;
1020 } 1063 }
1021 } 1064 }
1022 1065
1023 if (m_target) { 1066 if (m_target) {
1024 m_lastRetrievedBlockSize = count; 1067 m_lastRetrievedBlockSize = count;
1025 m_lastRetrievalTimestamp = m_target->getCurrentTime(); 1068 m_lastRetrievalTimestamp = m_target->getCurrentTime();
1026 } 1069 }
1027 1070
1028 if (!ts || ratio == 1.f) { 1071 if (!ts || ratio == 1.f) {
1029 1072
1030 size_t got = 0; 1073 int got = 0;
1031 1074
1032 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { 1075 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
1033 1076
1034 RingBuffer<float> *rb = getReadRingBuffer(ch); 1077 RingBuffer<float> *rb = getReadRingBuffer(ch);
1035 1078
1046 std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << std::endl; 1089 std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << std::endl;
1047 #endif 1090 #endif
1048 } 1091 }
1049 1092
1050 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { 1093 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
1051 for (size_t i = got; i < count; ++i) { 1094 for (int i = got; i < count; ++i) {
1052 buffer[ch][i] = 0.0; 1095 buffer[ch][i] = 0.0;
1053 } 1096 }
1054 } 1097 }
1055 } 1098 }
1056 1099
1080 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1123 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1081 std::cerr << "reqd = " <<reqd << ", channels = " << channels << ", ic = " << m_stretcherInputCount << std::endl; 1124 std::cerr << "reqd = " <<reqd << ", channels = " << channels << ", ic = " << m_stretcherInputCount << std::endl;
1082 #endif 1125 #endif
1083 1126
1084 for (size_t c = 0; c < channels; ++c) { 1127 for (size_t c = 0; c < channels; ++c) {
1085 if (c >= m_stretcherInputCount) continue; 1128 if (c >= m_stretcherInputSizes) continue;
1086 if (reqd > m_stretcherInputSizes[c]) { 1129 if (reqd > m_stretcherInputSizes[c]) {
1087 if (c == 0) { 1130 if (c == 0) {
1088 std::cerr << "WARNING: resizing stretcher input buffer from " << m_stretcherInputSizes[c] << " to " << (reqd * 2) << std::endl; 1131 std::cerr << "WARNING: resizing stretcher input buffer from " << m_stretcherInputSizes[c] << " to " << (reqd * 2) << std::endl;
1089 } 1132 }
1090 delete[] m_stretcherInputs[c]; 1133 delete[] m_stretcherInputs[c];
1092 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]]; 1135 m_stretcherInputs[c] = new float[m_stretcherInputSizes[c]];
1093 } 1136 }
1094 } 1137 }
1095 1138
1096 for (size_t c = 0; c < channels; ++c) { 1139 for (size_t c = 0; c < channels; ++c) {
1097 if (c >= m_stretcherInputCount) continue; 1140 if (c >= m_stretcherInputSizes) continue;
1098 RingBuffer<float> *rb = getReadRingBuffer(c); 1141 RingBuffer<float> *rb = getReadRingBuffer(c);
1099 if (rb) { 1142 if (rb) {
1100 size_t gotHere = rb->read(m_stretcherInputs[c], got); 1143 size_t gotHere;
1144 if (stretchChannels == 1 && c > 0) {
1145 gotHere = rb->readAdding(m_stretcherInputs[0], got);
1146 } else {
1147 gotHere = rb->read(m_stretcherInputs[c], got);
1148 }
1101 if (gotHere < got) got = gotHere; 1149 if (gotHere < got) got = gotHere;
1102 1150
1103 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1151 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1104 if (c == 0) { 1152 if (c == 0) {
1105 std::cerr << "feeding stretcher: got " << gotHere 1153 std::cerr << "feeding stretcher: got " << gotHere
1128 if (++warned == 5) break; 1176 if (++warned == 5) break;
1129 } 1177 }
1130 } 1178 }
1131 1179
1132 ts->retrieve(buffer, count); 1180 ts->retrieve(buffer, count);
1181
1182 for (int c = stretchChannels; c < getTargetChannelCount(); ++c) {
1183 for (int i = 0; i < count; ++i) {
1184 buffer[c][i] = buffer[0][i];
1185 }
1186 }
1133 1187
1134 applyAuditioningEffect(count, buffer); 1188 applyAuditioningEffect(count, buffer);
1135 1189
1136 m_condition.wakeAll(); 1190 m_condition.wakeAll();
1137 1191