comparison audioio/AudioCallbackPlaySource.cpp @ 106:f8e362511b2f

* Probable fix to occasional channel misalignment during playback
author Chris Cannam
date Mon, 26 Feb 2007 16:32:37 +0000
parents 0581d552481d
children b4110b17bca8
comparison
equal deleted inserted replaced
105:0581d552481d 106:f8e362511b2f
124 if (dtvm) modelChannels = dtvm->getChannelCount(); 124 if (dtvm) modelChannels = dtvm->getChannelCount();
125 if (modelChannels > m_sourceChannelCount) { 125 if (modelChannels > m_sourceChannelCount) {
126 m_sourceChannelCount = modelChannels; 126 m_sourceChannelCount = modelChannels;
127 } 127 }
128 128
129 // std::cerr << "Adding model with " << modelChannels << " channels " << std::endl; 129 // std::cout << "Adding model with " << modelChannels << " channels " << std::endl;
130 130
131 if (m_sourceSampleRate == 0) { 131 if (m_sourceSampleRate == 0) {
132 132
133 m_sourceSampleRate = model->getSampleRate(); 133 m_sourceSampleRate = model->getSampleRate();
134 srChanged = true; 134 srChanged = true;
193 m_fillThread = new AudioCallbackPlaySourceFillThread(*this); 193 m_fillThread = new AudioCallbackPlaySourceFillThread(*this);
194 m_fillThread->start(); 194 m_fillThread->start();
195 } 195 }
196 196
197 #ifdef DEBUG_AUDIO_PLAY_SOURCE 197 #ifdef DEBUG_AUDIO_PLAY_SOURCE
198 std::cerr << "AudioCallbackPlaySource::addModel: emitting modelReplaced" << std::endl; 198 std::cout << "AudioCallbackPlaySource::addModel: emitting modelReplaced" << std::endl;
199 #endif 199 #endif
200 200
201 if (buffersChanged || srChanged) { 201 if (buffersChanged || srChanged) {
202 emit modelReplaced(); 202 emit modelReplaced();
203 } 203 }
223 } 223 }
224 224
225 size_t lastEnd = 0; 225 size_t lastEnd = 0;
226 for (std::set<Model *>::const_iterator i = m_models.begin(); 226 for (std::set<Model *>::const_iterator i = m_models.begin();
227 i != m_models.end(); ++i) { 227 i != m_models.end(); ++i) {
228 // std::cerr << "AudioCallbackPlaySource::removeModel(" << model << "): checking end frame on model " << *i << std::endl; 228 // std::cout << "AudioCallbackPlaySource::removeModel(" << model << "): checking end frame on model " << *i << std::endl;
229 if ((*i)->getEndFrame() > lastEnd) lastEnd = (*i)->getEndFrame(); 229 if ((*i)->getEndFrame() > lastEnd) lastEnd = (*i)->getEndFrame();
230 // std::cerr << "(done, lastEnd now " << lastEnd << ")" << std::endl; 230 // std::cout << "(done, lastEnd now " << lastEnd << ")" << std::endl;
231 } 231 }
232 m_lastModelEndFrame = lastEnd; 232 m_lastModelEndFrame = lastEnd;
233 233
234 m_mutex.unlock(); 234 m_mutex.unlock();
235 235
291 291
292 for (size_t i = 0; i < count; ++i) { 292 for (size_t i = 0; i < count; ++i) {
293 m_writeBuffers->push_back(new RingBuffer<float>(m_ringBufferSize)); 293 m_writeBuffers->push_back(new RingBuffer<float>(m_ringBufferSize));
294 } 294 }
295 295
296 // std::cerr << "AudioCallbackPlaySource::clearRingBuffers: Created " 296 // std::cout << "AudioCallbackPlaySource::clearRingBuffers: Created "
297 // << count << " write buffers" << std::endl; 297 // << count << " write buffers" << std::endl;
298 298
299 if (!haveLock) { 299 if (!haveLock) {
300 m_mutex.unlock(); 300 m_mutex.unlock();
301 } 301 }
411 } 411 }
412 412
413 void 413 void
414 AudioCallbackPlaySource::setTargetBlockSize(size_t size) 414 AudioCallbackPlaySource::setTargetBlockSize(size_t size)
415 { 415 {
416 // std::cerr << "AudioCallbackPlaySource::setTargetBlockSize() -> " << size << std::endl; 416 // std::cout << "AudioCallbackPlaySource::setTargetBlockSize() -> " << size << std::endl;
417 assert(size < m_ringBufferSize); 417 assert(size < m_ringBufferSize);
418 m_blockSize = size; 418 m_blockSize = size;
419 } 419 }
420 420
421 size_t 421 size_t
422 AudioCallbackPlaySource::getTargetBlockSize() const 422 AudioCallbackPlaySource::getTargetBlockSize() const
423 { 423 {
424 // std::cerr << "AudioCallbackPlaySource::getTargetBlockSize() -> " << m_blockSize << std::endl; 424 // std::cout << "AudioCallbackPlaySource::getTargetBlockSize() -> " << m_blockSize << std::endl;
425 return m_blockSize; 425 return m_blockSize;
426 } 426 }
427 427
428 void 428 void
429 AudioCallbackPlaySource::setTargetPlayLatency(size_t latency) 429 AudioCallbackPlaySource::setTargetPlayLatency(size_t latency)
507 if (i->contains(bufferedFrame)) break; 507 if (i->contains(bufferedFrame)) break;
508 } 508 }
509 509
510 size_t f = bufferedFrame; 510 size_t f = bufferedFrame;
511 511
512 // std::cerr << "getCurrentPlayingFrame: f=" << f << ", latency=" << latency << ", rangeEnd=" << rangeEnd << std::endl; 512 // std::cout << "getCurrentPlayingFrame: f=" << f << ", latency=" << latency << ", rangeEnd=" << rangeEnd << std::endl;
513 513
514 if (i == selections.end()) { 514 if (i == selections.end()) {
515 --i; 515 --i;
516 if (i->getEndFrame() + latency < f) { 516 if (i->getEndFrame() + latency < f) {
517 // std::cerr << "framePlaying = " << framePlaying << ", rangeEnd = " << rangeEnd << std::endl; 517 // std::cout << "framePlaying = " << framePlaying << ", rangeEnd = " << rangeEnd << std::endl;
518 518
519 if (!looping && (framePlaying > rangeEnd)) { 519 if (!looping && (framePlaying > rangeEnd)) {
520 // std::cerr << "STOPPING" << std::endl; 520 // std::cout << "STOPPING" << std::endl;
521 stop(); 521 stop();
522 return rangeEnd; 522 return rangeEnd;
523 } else { 523 } else {
524 return framePlaying; 524 return framePlaying;
525 } 525 }
526 } else { 526 } else {
527 // std::cerr << "latency <- " << latency << "-(" << f << "-" << i->getEndFrame() << ")" << std::endl; 527 // std::cout << "latency <- " << latency << "-(" << f << "-" << i->getEndFrame() << ")" << std::endl;
528 latency -= (f - i->getEndFrame()); 528 latency -= (f - i->getEndFrame());
529 f = i->getEndFrame(); 529 f = i->getEndFrame();
530 } 530 }
531 } 531 }
532 532
533 // std::cerr << "i=(" << i->getStartFrame() << "," << i->getEndFrame() << ") f=" << f << ", latency=" << latency << std::endl; 533 // std::cout << "i=(" << i->getStartFrame() << "," << i->getEndFrame() << ") f=" << f << ", latency=" << latency << std::endl;
534 534
535 while (latency > 0) { 535 while (latency > 0) {
536 size_t offset = f - i->getStartFrame(); 536 size_t offset = f - i->getStartFrame();
537 if (offset >= latency) { 537 if (offset >= latency) {
538 if (f > latency) { 538 if (f > latency) {
743 } 743 }
744 } 744 }
745 return 0; 745 return 0;
746 } 746 }
747 747
748 // Ensure that all buffers have at least the amount of data we
749 // need -- else reduce the size of our requests correspondingly
750
751 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
752
753 RingBuffer<float> *rb = getReadRingBuffer(ch);
754
755 if (!rb) {
756 std::cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: "
757 << "No ring buffer available for channel " << ch
758 << ", returning no data here" << std::endl;
759 count = 0;
760 break;
761 }
762
763 size_t rs = rb->getReadSpace();
764 if (rs < count) {
765 #ifdef DEBUG_AUDIO_PLAY_SOURCE
766 std::cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: "
767 << "Ring buffer for channel " << ch << " has only "
768 << rs << " (of " << count << ") samples available, "
769 << "reducing request size" << std::endl;
770 #endif
771 count = rs;
772 }
773 }
774
775 if (count == 0) return 0;
776
748 PhaseVocoderTimeStretcher *ts = m_timeStretcher; 777 PhaseVocoderTimeStretcher *ts = m_timeStretcher;
749 778
750 if (!ts || ts->getRatio() == 1) { 779 if (!ts || ts->getRatio() == 1) {
751 780
752 size_t got = 0; 781 size_t got = 0;
763 if (ch > 0) request = got; 792 if (ch > 0) request = got;
764 793
765 got = rb->read(buffer[ch], request); 794 got = rb->read(buffer[ch], request);
766 795
767 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 796 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
768 std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " samples on channel " << ch << ", signalling for more (possibly)" << std::endl; 797 std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << std::endl;
769 #endif 798 #endif
770 } 799 }
771 800
772 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { 801 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
773 for (size_t i = got; i < count; ++i) { 802 for (size_t i = got; i < count; ++i) {
1040 1069
1041 int err = 0; 1070 int err = 0;
1042 1071
1043 if (m_timeStretcher && m_timeStretcher->getRatio() < 0.4) { 1072 if (m_timeStretcher && m_timeStretcher->getRatio() < 0.4) {
1044 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1073 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1045 std::cerr << "Using crappy converter" << std::endl; 1074 std::cout << "Using crappy converter" << std::endl;
1046 #endif 1075 #endif
1047 src_process(m_crapConverter, &data); 1076 src_process(m_crapConverter, &data);
1048 } else { 1077 } else {
1049 src_process(m_converter, &data); 1078 src_process(m_converter, &data);
1050 } 1079 }
1058 //!!! Then what? 1087 //!!! Then what?
1059 } else { 1088 } else {
1060 got = data.input_frames_used; 1089 got = data.input_frames_used;
1061 toCopy = data.output_frames_gen; 1090 toCopy = data.output_frames_gen;
1062 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1091 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1063 std::cerr << "Resampled " << got << " frames to " << toCopy << " frames" << std::endl; 1092 std::cout << "Resampled " << got << " frames to " << toCopy << " frames" << std::endl;
1064 #endif 1093 #endif
1065 } 1094 }
1066 1095
1067 for (size_t c = 0; c < channels; ++c) { 1096 for (size_t c = 0; c < channels; ++c) {
1068 for (size_t i = 0; i < toCopy; ++i) { 1097 for (size_t i = 0; i < toCopy; ++i) {
1099 size_t got = mixModels(f, space, bufferPtrs); 1128 size_t got = mixModels(f, space, bufferPtrs);
1100 1129
1101 for (size_t c = 0; c < channels; ++c) { 1130 for (size_t c = 0; c < channels; ++c) {
1102 1131
1103 RingBuffer<float> *wb = getWriteRingBuffer(c); 1132 RingBuffer<float> *wb = getWriteRingBuffer(c);
1104 if (wb) wb->write(bufferPtrs[c], got); 1133 if (wb) {
1105 1134 size_t actual = wb->write(bufferPtrs[c], got);
1106 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1135 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1107 if (wb) 1136 std::cout << "Wrote " << actual << " samples for ch " << c << ", now "
1108 std::cerr << "Wrote " << got << " frames for ch " << c << ", now "
1109 << wb->getReadSpace() << " to read" 1137 << wb->getReadSpace() << " to read"
1110 << std::endl; 1138 << std::endl;
1111 #endif 1139 #endif
1140 if (actual < got) {
1141 std::cerr << "WARNING: Buffer overrun in channel " << c
1142 << ": wrote " << actual << " of " << got
1143 << " samples" << std::endl;
1144 }
1145 }
1112 } 1146 }
1113 1147
1114 m_writeBufferFill = f; 1148 m_writeBufferFill = f;
1115 if (readWriteEqual) m_readBufferFill = f; 1149 if (readWriteEqual) m_readBufferFill = f;
1116 1150
1136 static float **chunkBufferPtrs = 0; 1170 static float **chunkBufferPtrs = 0;
1137 static size_t chunkBufferPtrCount = 0; 1171 static size_t chunkBufferPtrCount = 0;
1138 size_t channels = getTargetChannelCount(); 1172 size_t channels = getTargetChannelCount();
1139 1173
1140 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1174 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1141 std::cerr << "Selection playback: start " << frame << ", size " << count <<", channels " << channels << std::endl; 1175 std::cout << "Selection playback: start " << frame << ", size " << count <<", channels " << channels << std::endl;
1142 #endif 1176 #endif
1143 1177
1144 if (chunkBufferPtrCount < channels) { 1178 if (chunkBufferPtrCount < channels) {
1145 if (chunkBufferPtrs) delete[] chunkBufferPtrs; 1179 if (chunkBufferPtrs) delete[] chunkBufferPtrs;
1146 chunkBufferPtrs = new float *[channels]; 1180 chunkBufferPtrs = new float *[channels];
1207 chunkSize = m_lastModelEndFrame - chunkStart; 1241 chunkSize = m_lastModelEndFrame - chunkStart;
1208 } 1242 }
1209 nextChunkStart = chunkStart + chunkSize; 1243 nextChunkStart = chunkStart + chunkSize;
1210 } 1244 }
1211 1245
1212 // std::cerr << "chunkStart " << chunkStart << ", chunkSize " << chunkSize << ", nextChunkStart " << nextChunkStart << ", frame " << frame << ", count " << count << ", processed " << processed << std::endl; 1246 // std::cout << "chunkStart " << chunkStart << ", chunkSize " << chunkSize << ", nextChunkStart " << nextChunkStart << ", frame " << frame << ", count " << count << ", processed " << processed << std::endl;
1213 1247
1214 if (!chunkSize) { 1248 if (!chunkSize) {
1215 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1249 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1216 std::cerr << "Ending selection playback at " << nextChunkStart << std::endl; 1250 std::cout << "Ending selection playback at " << nextChunkStart << std::endl;
1217 #endif 1251 #endif
1218 // We need to maintain full buffers so that the other 1252 // We need to maintain full buffers so that the other
1219 // thread can tell where it's got to in the playback -- so 1253 // thread can tell where it's got to in the playback -- so
1220 // return the full amount here 1254 // return the full amount here
1221 frame = frame + count; 1255 frame = frame + count;
1222 return count; 1256 return count;
1223 } 1257 }
1224 1258
1225 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1259 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1226 std::cerr << "Selection playback: chunk at " << chunkStart << " -> " << nextChunkStart << " (size " << chunkSize << ")" << std::endl; 1260 std::cout << "Selection playback: chunk at " << chunkStart << " -> " << nextChunkStart << " (size " << chunkSize << ")" << std::endl;
1227 #endif 1261 #endif
1228 1262
1229 size_t got = 0; 1263 size_t got = 0;
1230 1264
1231 if (selectionSize < 100) { 1265 if (selectionSize < 100) {
1263 processed += chunkSize; 1297 processed += chunkSize;
1264 chunkStart = nextChunkStart; 1298 chunkStart = nextChunkStart;
1265 } 1299 }
1266 1300
1267 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1301 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1268 std::cerr << "Returning selection playback " << processed << " frames to " << nextChunkStart << std::endl; 1302 std::cout << "Returning selection playback " << processed << " frames to " << nextChunkStart << std::endl;
1269 #endif 1303 #endif
1270 1304
1271 frame = nextChunkStart; 1305 frame = nextChunkStart;
1272 return processed; 1306 return processed;
1273 } 1307 }
1296 size_t rf = m_readBufferFill; 1330 size_t rf = m_readBufferFill;
1297 RingBuffer<float> *rb = getReadRingBuffer(0); 1331 RingBuffer<float> *rb = getReadRingBuffer(0);
1298 if (rb) { 1332 if (rb) {
1299 size_t rs = rb->getReadSpace(); 1333 size_t rs = rb->getReadSpace();
1300 //!!! incorrect when in non-contiguous selection, see comments elsewhere 1334 //!!! incorrect when in non-contiguous selection, see comments elsewhere
1301 // std::cerr << "rs = " << rs << std::endl; 1335 // std::cout << "rs = " << rs << std::endl;
1302 if (rs < rf) rf -= rs; 1336 if (rs < rf) rf -= rs;
1303 else rf = 0; 1337 else rf = 0;
1304 } 1338 }
1305 1339
1306 //std::cerr << "m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << std::endl; 1340 //std::cout << "m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << std::endl;
1307 1341
1308 size_t wf = m_writeBufferFill; 1342 size_t wf = m_writeBufferFill;
1309 size_t skip = 0; 1343 size_t skip = 0;
1310 for (size_t c = 0; c < getTargetChannelCount(); ++c) { 1344 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
1311 RingBuffer<float> *wb = getWriteRingBuffer(c); 1345 RingBuffer<float> *wb = getWriteRingBuffer(c);
1312 if (wb) { 1346 if (wb) {
1313 if (c == 0) { 1347 if (c == 0) {
1314 1348
1315 size_t wrs = wb->getReadSpace(); 1349 size_t wrs = wb->getReadSpace();
1316 // std::cerr << "wrs = " << wrs << std::endl; 1350 // std::cout << "wrs = " << wrs << std::endl;
1317 1351
1318 if (wrs < wf) wf -= wrs; 1352 if (wrs < wf) wf -= wrs;
1319 else wf = 0; 1353 else wf = 0;
1320 // std::cerr << "wf = " << wf << std::endl; 1354 // std::cout << "wf = " << wf << std::endl;
1321 1355
1322 if (wf < rf) skip = rf - wf; 1356 if (wf < rf) skip = rf - wf;
1323 if (skip == 0) break; 1357 if (skip == 0) break;
1324 } 1358 }
1325 1359
1326 // std::cerr << "skipping " << skip << std::endl; 1360 // std::cout << "skipping " << skip << std::endl;
1327 wb->skip(skip); 1361 wb->skip(skip);
1328 } 1362 }
1329 } 1363 }
1330 1364
1331 m_bufferScavenger.claim(m_readBuffers); 1365 m_bufferScavenger.claim(m_readBuffers);
1332 m_readBuffers = m_writeBuffers; 1366 m_readBuffers = m_writeBuffers;
1333 m_readBufferFill = m_writeBufferFill; 1367 m_readBufferFill = m_writeBufferFill;
1334 // std::cerr << "unified" << std::endl; 1368 // std::cout << "unified" << std::endl;
1335 } 1369 }
1336 1370
1337 void 1371 void
1338 AudioCallbackPlaySource::AudioCallbackPlaySourceFillThread::run() 1372 AudioCallbackPlaySource::AudioCallbackPlaySourceFillThread::run()
1339 { 1373 {
1340 AudioCallbackPlaySource &s(m_source); 1374 AudioCallbackPlaySource &s(m_source);
1341 1375
1342 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1376 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1343 std::cerr << "AudioCallbackPlaySourceFillThread starting" << std::endl; 1377 std::cout << "AudioCallbackPlaySourceFillThread starting" << std::endl;
1344 #endif 1378 #endif
1345 1379
1346 s.m_mutex.lock(); 1380 s.m_mutex.lock();
1347 1381
1348 bool previouslyPlaying = s.m_playing; 1382 bool previouslyPlaying = s.m_playing;
1370 if (s.getSourceSampleRate() > 0) { 1404 if (s.getSourceSampleRate() > 0) {
1371 ms = float(m_ringBufferSize) / float(s.getSourceSampleRate()) * 1000.0; 1405 ms = float(m_ringBufferSize) / float(s.getSourceSampleRate()) * 1000.0;
1372 } 1406 }
1373 1407
1374 if (s.m_playing) ms /= 10; 1408 if (s.m_playing) ms /= 10;
1375 1409
1376 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1410 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1411 if (!s.m_playing) std::cout << std::endl;
1377 std::cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << std::endl; 1412 std::cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << std::endl;
1378 #endif 1413 #endif
1379 1414
1380 s.m_condition.wait(&s.m_mutex, size_t(ms)); 1415 s.m_condition.wait(&s.m_mutex, size_t(ms));
1381 } 1416 }