comparison audio/AudioCallbackPlaySource.cpp @ 559:7b115a6505b8 3.0-integration

Handle increases in the overall channel count by closing and reopening the audio device.
author Chris Cannam
date Tue, 13 Dec 2016 12:03:48 +0000
parents 206d65e2b69a
children 3c846b06c518
comparison
equal deleted inserted replaced
558:206d65e2b69a 559:7b115a6505b8
28 #include "plugin/RealTimePluginInstance.h" 28 #include "plugin/RealTimePluginInstance.h"
29 29
30 #include "bqaudioio/SystemPlaybackTarget.h" 30 #include "bqaudioio/SystemPlaybackTarget.h"
31 #include "bqaudioio/ResamplerWrapper.h" 31 #include "bqaudioio/ResamplerWrapper.h"
32 32
33 #include "bqvec/VectorOps.h"
34
33 #include <rubberband/RubberBandStretcher.h> 35 #include <rubberband/RubberBandStretcher.h>
34 using namespace RubberBand; 36 using namespace RubberBand;
37
38 using breakfastquay::v_zero_channels;
35 39
36 #include <iostream> 40 #include <iostream>
37 #include <cassert> 41 #include <cassert>
38 42
39 //#define DEBUG_AUDIO_PLAY_SOURCE 1 43 //#define DEBUG_AUDIO_PLAY_SOURCE 1
53 m_bufferScavenger(1), 57 m_bufferScavenger(1),
54 m_sourceChannelCount(0), 58 m_sourceChannelCount(0),
55 m_blockSize(1024), 59 m_blockSize(1024),
56 m_sourceSampleRate(0), 60 m_sourceSampleRate(0),
57 m_deviceSampleRate(0), 61 m_deviceSampleRate(0),
62 m_deviceChannelCount(0),
58 m_playLatency(0), 63 m_playLatency(0),
59 m_target(0), 64 m_target(0),
60 m_lastRetrievalTimestamp(0.0), 65 m_lastRetrievalTimestamp(0.0),
61 m_lastRetrievedBlockSize(0), 66 m_lastRetrievedBlockSize(0),
62 m_trustworthyTimestamps(true), 67 m_trustworthyTimestamps(true),
156 m_models.insert(model); 161 m_models.insert(model);
157 if (model->getEndFrame() > m_lastModelEndFrame) { 162 if (model->getEndFrame() > m_lastModelEndFrame) {
158 m_lastModelEndFrame = model->getEndFrame(); 163 m_lastModelEndFrame = model->getEndFrame();
159 } 164 }
160 165
161 bool buffersChanged = false, srChanged = false; 166 bool buffersIncreased = false, srChanged = false;
162 167
163 int modelChannels = 1; 168 int modelChannels = 1;
164 ReadOnlyWaveFileModel *rowfm = qobject_cast<ReadOnlyWaveFileModel *>(model); 169 ReadOnlyWaveFileModel *rowfm = qobject_cast<ReadOnlyWaveFileModel *>(model);
165 if (rowfm) modelChannels = rowfm->getChannelCount(); 170 if (rowfm) modelChannels = rowfm->getChannelCount();
166 if (modelChannels > m_sourceChannelCount) { 171 if (modelChannels > m_sourceChannelCount) {
223 } 228 }
224 } 229 }
225 230
226 if (!m_writeBuffers || (int)m_writeBuffers->size() < getTargetChannelCount()) { 231 if (!m_writeBuffers || (int)m_writeBuffers->size() < getTargetChannelCount()) {
227 clearRingBuffers(true, getTargetChannelCount()); 232 clearRingBuffers(true, getTargetChannelCount());
228 buffersChanged = true; 233 buffersIncreased = true;
229 } else { 234 } else {
230 if (willPlay) clearRingBuffers(true); 235 if (willPlay) clearRingBuffers(true);
231 } 236 }
232 237
233 if (srChanged) { 238 if (srChanged) {
254 259
255 rebuildRangeLists(); 260 rebuildRangeLists();
256 261
257 m_mutex.unlock(); 262 m_mutex.unlock();
258 263
259 //!!! 264 m_audioGenerator->setTargetChannelCount(getTargetChannelCount());
265
266 if (buffersIncreased) {
267 SVDEBUG << "AudioCallbackPlaySource::addModel: Number of buffers increased, signalling channelCountIncreased" << endl;
268 emit channelCountIncreased();
269 }
260 270
261 m_audioGenerator->setTargetChannelCount(getTargetChannelCount());
262
263 if (!m_fillThread) { 271 if (!m_fillThread) {
264 m_fillThread = new FillThread(*this); 272 m_fillThread = new FillThread(*this);
265 m_fillThread->start(); 273 m_fillThread->start();
266 } 274 }
267 275
268 #ifdef DEBUG_AUDIO_PLAY_SOURCE 276 #ifdef DEBUG_AUDIO_PLAY_SOURCE
269 cout << "AudioCallbackPlaySource::addModel: now have " << m_models.size() << " model(s)" << endl; 277 SVDEBUG << "AudioCallbackPlaySource::addModel: now have " << m_models.size() << " model(s)" << endl;
270 #endif 278 #endif
271 279
272 connect(model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), 280 connect(model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)),
273 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); 281 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t)));
274 282
275 #ifdef DEBUG_AUDIO_PLAY_SOURCE 283 #ifdef DEBUG_AUDIO_PLAY_SOURCE
276 cout << "AudioCallbackPlaySource::addModel: awakening thread" << endl; 284 cout << "AudioCallbackPlaySource::addModel: awakening thread" << endl;
277 #endif 285 #endif
278 286
279 m_condition.wakeAll(); 287 m_condition.wakeAll();
280 } 288 }
281 289
282 void 290 void
283 AudioCallbackPlaySource::modelChangedWithin(sv_frame_t 291 AudioCallbackPlaySource::modelChangedWithin(sv_frame_t
578 } 586 }
579 587
580 void 588 void
581 AudioCallbackPlaySource::setSystemPlaybackTarget(breakfastquay::SystemPlaybackTarget *target) 589 AudioCallbackPlaySource::setSystemPlaybackTarget(breakfastquay::SystemPlaybackTarget *target)
582 { 590 {
591 if (target == 0) {
592 // reset target-related facts and figures
593 m_deviceSampleRate = 0;
594 m_deviceChannelCount = 0;
595 }
583 m_target = target; 596 m_target = target;
584 } 597 }
585 598
586 void 599 void
587 AudioCallbackPlaySource::setResamplerWrapper(breakfastquay::ResamplerWrapper *w) 600 AudioCallbackPlaySource::setResamplerWrapper(breakfastquay::ResamplerWrapper *w)
946 { 959 {
947 m_deviceSampleRate = sr; 960 m_deviceSampleRate = sr;
948 } 961 }
949 962
950 void 963 void
951 AudioCallbackPlaySource::setSystemPlaybackChannelCount(int) 964 AudioCallbackPlaySource::setSystemPlaybackChannelCount(int count)
952 { 965 {
966 m_deviceChannelCount = count;
953 } 967 }
954 968
955 void 969 void
956 AudioCallbackPlaySource::setAuditioningEffect(Auditionable *a) 970 AudioCallbackPlaySource::setAuditioningEffect(Auditionable *a)
957 { 971 {
995 int 1009 int
996 AudioCallbackPlaySource::getTargetChannelCount() const 1010 AudioCallbackPlaySource::getTargetChannelCount() const
997 { 1011 {
998 if (m_sourceChannelCount < 2) return 2; 1012 if (m_sourceChannelCount < 2) return 2;
999 return m_sourceChannelCount; 1013 return m_sourceChannelCount;
1014 }
1015
1016 int
1017 AudioCallbackPlaySource::getDeviceChannelCount() const
1018 {
1019 return m_deviceChannelCount;
1000 } 1020 }
1001 1021
1002 sv_samplerate_t 1022 sv_samplerate_t
1003 AudioCallbackPlaySource::getSourceSampleRate() const 1023 AudioCallbackPlaySource::getSourceSampleRate() const
1004 { 1024 {
1039 1059
1040 emit activity(tr("Change time-stretch factor to %1").arg(factor)); 1060 emit activity(tr("Change time-stretch factor to %1").arg(factor));
1041 } 1061 }
1042 1062
1043 int 1063 int
1044 AudioCallbackPlaySource::getSourceSamples(int count, float **buffer) 1064 AudioCallbackPlaySource::getSourceSamples(float *const *buffer,
1045 { 1065 int requestedChannels,
1066 int count)
1067 {
1068 // In principle, the target will handle channel mapping in cases
1069 // where our channel count differs from the device's. But that
1070 // only holds if our channel count doesn't change -- i.e. if
1071 // getApplicationChannelCount() always returns the same value as
1072 // it did when the target was created, and if this function always
1073 // returns that number of channels.
1074 //
1075 // Unfortunately that can't hold for us -- we always have at least
1076 // 2 channels but if the user opens a new main model with more
1077 // channels than that (and more than the last main model) then our
1078 // target channel count necessarily gets increased.
1079 //
1080 // We have:
1081 //
1082 // getSourceChannelCount() -> number of channels available to
1083 // provide from real model data
1084 //
1085 // getTargetChannelCount() -> number we will actually provide;
1086 // same as getSourceChannelCount() except that it is always at
1087 // least 2
1088 //
1089 // getDeviceChannelCount() -> number the device will emit, usually
1090 // equal to the value of getTargetChannelCount() at the time the
1091 // device was initialised, unless the device could not provide
1092 // that number
1093 //
1094 // requestedChannels -> number the device is expecting from us,
1095 // always equal to the value of getTargetChannelCount() at the
1096 // time the device was initialised
1097 //
1098 // If the requested channel count is at least the target channel
1099 // count, then we go ahead and provide the target channels as
1100 // expected. We just zero any spare channels.
1101 //
1102 // If the requested channel count is smaller than the target
1103 // channel count, then we don't know what to do and we provide
1104 // nothing. This shouldn't happen as long as management is on the
1105 // ball -- we emit channelCountIncreased() when the target channel
1106 // count increases, and whatever code "owns" the driver should
1107 // have reopened the audio device when it got that signal. But
1108 // there's a race condition there, which we accommodate with this
1109 // check.
1110
1111 int channels = getTargetChannelCount();
1112
1046 if (!m_playing) { 1113 if (!m_playing) {
1047 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1114 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1048 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not playing" << endl; 1115 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not playing" << endl;
1049 #endif 1116 #endif
1050 for (int ch = 0; ch < getTargetChannelCount(); ++ch) { 1117 v_zero_channels(buffer, requestedChannels, count);
1051 for (int i = 0; i < count; ++i) {
1052 buffer[ch][i] = 0.0;
1053 }
1054 }
1055 return 0; 1118 return 0;
1119 }
1120 if (requestedChannels < channels) {
1121 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not enough device channels (" << requestedChannels << ", need " << channels << "); hoping device is about to be reopened" << endl;
1122 v_zero_channels(buffer, requestedChannels, count);
1123 return 0;
1124 }
1125 if (requestedChannels > channels) {
1126 v_zero_channels(buffer + channels, requestedChannels - channels, count);
1056 } 1127 }
1057 1128
1058 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1129 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1059 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Playing" << endl; 1130 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Playing" << endl;
1060 #endif 1131 #endif
1061 1132
1062 // Ensure that all buffers have at least the amount of data we 1133 // Ensure that all buffers have at least the amount of data we
1063 // need -- else reduce the size of our requests correspondingly 1134 // need -- else reduce the size of our requests correspondingly
1064 1135
1065 for (int ch = 0; ch < getTargetChannelCount(); ++ch) { 1136 for (int ch = 0; ch < channels; ++ch) {
1066 1137
1067 RingBuffer<float> *rb = getReadRingBuffer(ch); 1138 RingBuffer<float> *rb = getReadRingBuffer(ch);
1068 1139
1069 if (!rb) { 1140 if (!rb) {
1070 cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: " 1141 cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: "
1123 1194
1124 if (!ts || ratio == 1.f) { 1195 if (!ts || ratio == 1.f) {
1125 1196
1126 int got = 0; 1197 int got = 0;
1127 1198
1128 cerr << "getTargetChannelCount() == " << getTargetChannelCount() << endl; 1199 cerr << "channels == " << channels << endl;
1129 1200
1130 for (int ch = 0; ch < getTargetChannelCount(); ++ch) { 1201 for (int ch = 0; ch < channels; ++ch) {
1131 1202
1132 RingBuffer<float> *rb = getReadRingBuffer(ch); 1203 RingBuffer<float> *rb = getReadRingBuffer(ch);
1133 1204
1134 if (rb) { 1205 if (rb) {
1135 1206
1143 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1214 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1144 cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << endl; 1215 cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << endl;
1145 #endif 1216 #endif
1146 } 1217 }
1147 1218
1148 for (int ch = 0; ch < getTargetChannelCount(); ++ch) { 1219 for (int ch = 0; ch < channels; ++ch) {
1149 for (int i = got; i < count; ++i) { 1220 for (int i = got; i < count; ++i) {
1150 buffer[ch][i] = 0.0; 1221 buffer[ch][i] = 0.0;
1151 } 1222 }
1152 } 1223 }
1153 } 1224 }
1161 m_condition.wakeAll(); 1232 m_condition.wakeAll();
1162 1233
1163 return got; 1234 return got;
1164 } 1235 }
1165 1236
1166 int channels = getTargetChannelCount();
1167 sv_frame_t available; 1237 sv_frame_t available;
1168 sv_frame_t fedToStretcher = 0; 1238 sv_frame_t fedToStretcher = 0;
1169 int warned = 0; 1239 int warned = 0;
1170 1240
1171 // The input block for a given output is approx output / ratio, 1241 // The input block for a given output is approx output / ratio,
1236 } 1306 }
1237 } 1307 }
1238 1308
1239 ts->retrieve(buffer, size_t(count)); 1309 ts->retrieve(buffer, size_t(count));
1240 1310
1241 for (int c = stretchChannels; c < getTargetChannelCount(); ++c) { 1311 v_zero_channels(buffer + stretchChannels, channels - stretchChannels, count);
1242 for (int i = 0; i < count; ++i) {
1243 buffer[c][i] = buffer[0][i];
1244 }
1245 }
1246 1312
1247 applyAuditioningEffect(count, buffer); 1313 applyAuditioningEffect(count, buffer);
1248 1314
1249 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1315 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1250 cout << "AudioCallbackPlaySource::getSamples [stretched]: awakening thread" << endl; 1316 cout << "AudioCallbackPlaySource::getSamples [stretched]: awakening thread" << endl;
1254 1320
1255 return count; 1321 return count;
1256 } 1322 }
1257 1323
1258 void 1324 void
1259 AudioCallbackPlaySource::applyAuditioningEffect(sv_frame_t count, float **buffers) 1325 AudioCallbackPlaySource::applyAuditioningEffect(sv_frame_t count, float *const *buffers)
1260 { 1326 {
1261 if (m_auditioningPluginBypassed) return; 1327 if (m_auditioningPluginBypassed) return;
1262 RealTimePluginInstance *plugin = m_auditioningPlugin; 1328 RealTimePluginInstance *plugin = m_auditioningPlugin;
1263 if (!plugin) return; 1329 if (!plugin) return;
1264 1330