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