Mercurial > hg > svapp
comparison audio/AudioCallbackPlaySource.cpp @ 550:c732251237b1 bqresample
Merge from branch 3.0-integration
author | Chris Cannam |
---|---|
date | Wed, 07 Dec 2016 12:04:41 +0000 |
parents | c4391f6c7484 4de547a5905c |
children | b9d8c7a690d6 |
comparison
equal
deleted
inserted
replaced
549:ec189ad4d38f | 550:c732251237b1 |
---|---|
75 m_stretchRatio(1.0), | 75 m_stretchRatio(1.0), |
76 m_stretchMono(false), | 76 m_stretchMono(false), |
77 m_stretcherInputCount(0), | 77 m_stretcherInputCount(0), |
78 m_stretcherInputs(0), | 78 m_stretcherInputs(0), |
79 m_stretcherInputSizes(0), | 79 m_stretcherInputSizes(0), |
80 m_fillThread(0), | 80 m_fillThread(0) |
81 m_resampler(0) | |
82 { | 81 { |
83 m_viewManager->setAudioPlaySource(this); | 82 m_viewManager->setAudioPlaySource(this); |
84 | 83 |
85 connect(m_viewManager, SIGNAL(selectionChanged()), | 84 connect(m_viewManager, SIGNAL(selectionChanged()), |
86 this, SLOT(selectionChanged())); | 85 this, SLOT(selectionChanged())); |
228 } else { | 227 } else { |
229 if (willPlay) clearRingBuffers(true); | 228 if (willPlay) clearRingBuffers(true); |
230 } | 229 } |
231 | 230 |
232 if (buffersChanged || srChanged) { | 231 if (buffersChanged || srChanged) { |
233 if (m_resampler) { | 232 |
234 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 233 // There are more channels than there were before, or the |
235 cerr << "AudioCallbackPlaySource::addModel: Buffers or sample rate changed, deleting existing resampler" << endl; | 234 // source sample rate has changed |
236 #endif | 235 |
237 delete m_resampler; | 236 //!!! |
238 m_resampler = 0; | 237 |
239 } | |
240 } | 238 } |
241 | 239 |
242 rebuildRangeLists(); | 240 rebuildRangeLists(); |
243 | 241 |
244 m_mutex.unlock(); | 242 m_mutex.unlock(); |
245 | 243 |
246 initialiseResampler(); | 244 //!!! |
247 | 245 |
248 m_audioGenerator->setTargetChannelCount(getTargetChannelCount()); | 246 m_audioGenerator->setTargetChannelCount(getTargetChannelCount()); |
249 | 247 |
250 if (!m_fillThread) { | 248 if (!m_fillThread) { |
251 m_fillThread = new FillThread(*this); | 249 m_fillThread = new FillThread(*this); |
299 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); | 297 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); |
300 | 298 |
301 m_models.erase(model); | 299 m_models.erase(model); |
302 | 300 |
303 if (m_models.empty()) { | 301 if (m_models.empty()) { |
304 if (m_resampler) { | |
305 #ifdef DEBUG_AUDIO_PLAY_SOURCE | |
306 cerr << "AudioCallbackPlaySource::removeModel: No models left, deleting resampler" << endl; | |
307 #endif | |
308 delete m_resampler; | |
309 m_resampler = 0; | |
310 } | |
311 m_sourceSampleRate = 0; | 302 m_sourceSampleRate = 0; |
312 } | 303 } |
313 | 304 |
314 sv_frame_t lastEnd = 0; | 305 sv_frame_t lastEnd = 0; |
315 for (std::set<Model *>::const_iterator i = m_models.begin(); | 306 for (std::set<Model *>::const_iterator i = m_models.begin(); |
341 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 332 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
342 cout << "AudioCallbackPlaySource::clearModels()" << endl; | 333 cout << "AudioCallbackPlaySource::clearModels()" << endl; |
343 #endif | 334 #endif |
344 | 335 |
345 m_models.clear(); | 336 m_models.clear(); |
346 | |
347 if (m_resampler) { | |
348 #ifdef DEBUG_AUDIO_PLAY_SOURCE | |
349 cerr << "AudioCallbackPlaySource::clearModels: Deleting resampler" << endl; | |
350 #endif | |
351 delete m_resampler; | |
352 m_resampler = 0; | |
353 } | |
354 | 337 |
355 m_lastModelEndFrame = 0; | 338 m_lastModelEndFrame = 0; |
356 | 339 |
357 m_sourceSampleRate = 0; | 340 m_sourceSampleRate = 0; |
358 | 341 |
469 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 452 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
470 cerr << "reset ring buffer for channel " << c << endl; | 453 cerr << "reset ring buffer for channel " << c << endl; |
471 #endif | 454 #endif |
472 if (rb) rb->reset(); | 455 if (rb) rb->reset(); |
473 } | 456 } |
474 } | |
475 if (m_resampler) { | |
476 m_resampler->reset(); | |
477 } | 457 } |
478 | 458 |
479 m_mutex.unlock(); | 459 m_mutex.unlock(); |
480 | 460 |
481 m_audioGenerator->reset(); | 461 m_audioGenerator->reset(); |
945 AudioCallbackPlaySource::setSystemPlaybackSampleRate(int sr) | 925 AudioCallbackPlaySource::setSystemPlaybackSampleRate(int sr) |
946 { | 926 { |
947 bool first = (m_targetSampleRate == 0); | 927 bool first = (m_targetSampleRate == 0); |
948 | 928 |
949 m_targetSampleRate = sr; | 929 m_targetSampleRate = sr; |
950 initialiseResampler(); | |
951 | 930 |
952 if (first && (m_stretchRatio != 1.f)) { | 931 if (first && (m_stretchRatio != 1.f)) { |
953 // couldn't create a stretcher before because we had no sample | 932 // couldn't create a stretcher before because we had no sample |
954 // rate: make one now | 933 // rate: make one now |
955 setTimeStretch(m_stretchRatio); | 934 setTimeStretch(m_stretchRatio); |
956 } | 935 } |
957 } | 936 } |
958 | 937 |
959 void | 938 void |
960 AudioCallbackPlaySource::initialiseResampler() | 939 AudioCallbackPlaySource::setSystemPlaybackChannelCount(int c) |
961 { | 940 { |
962 m_mutex.lock(); | |
963 | |
964 #ifdef DEBUG_AUDIO_PLAY_SOURCE | |
965 cerr << "AudioCallbackPlaySource::initialiseResampler(): from " | |
966 << getSourceSampleRate() << " to " << getTargetSampleRate() << endl; | |
967 #endif | |
968 | |
969 if (m_resampler) { | |
970 delete m_resampler; | |
971 m_resampler = 0; | |
972 } | |
973 | |
974 if (getSourceSampleRate() != getTargetSampleRate()) { | |
975 | |
976 m_resampler = new breakfastquay::Resampler | |
977 (breakfastquay::Resampler::FastestTolerable, | |
978 getTargetChannelCount()); | |
979 | |
980 m_mutex.unlock(); | |
981 | |
982 emit sampleRateMismatch(getSourceSampleRate(), | |
983 getTargetSampleRate(), | |
984 true); | |
985 } else { | |
986 m_mutex.unlock(); | |
987 } | |
988 } | 941 } |
989 | 942 |
990 void | 943 void |
991 AudioCallbackPlaySource::setAuditioningEffect(Auditionable *a) | 944 AudioCallbackPlaySource::setAuditioningEffect(Auditionable *a) |
992 { | 945 { |
1371 | 1324 |
1372 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 1325 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
1373 cout << "buffered to " << f << " already" << endl; | 1326 cout << "buffered to " << f << " already" << endl; |
1374 #endif | 1327 #endif |
1375 | 1328 |
1376 bool resample = (getSourceSampleRate() != getTargetSampleRate()); | |
1377 | |
1378 #ifdef DEBUG_AUDIO_PLAY_SOURCE | |
1379 cout << (resample ? "" : "not ") << "resampling (source " << getSourceSampleRate() << ", target " << getTargetSampleRate() << ")" << endl; | |
1380 #endif | |
1381 | |
1382 int channels = getTargetChannelCount(); | 1329 int channels = getTargetChannelCount(); |
1383 | 1330 |
1384 sv_frame_t orig = space; | 1331 sv_frame_t orig = space; |
1385 sv_frame_t got = 0; | |
1386 | 1332 |
1387 static float **bufferPtrs = 0; | 1333 static float **bufferPtrs = 0; |
1388 static int bufferPtrCount = 0; | 1334 static int bufferPtrCount = 0; |
1389 | 1335 |
1390 if (bufferPtrCount < channels) { | 1336 if (bufferPtrCount < channels) { |
1393 bufferPtrCount = channels; | 1339 bufferPtrCount = channels; |
1394 } | 1340 } |
1395 | 1341 |
1396 sv_frame_t generatorBlockSize = m_audioGenerator->getBlockSize(); | 1342 sv_frame_t generatorBlockSize = m_audioGenerator->getBlockSize(); |
1397 | 1343 |
1398 if (resample && !m_resampler) { | 1344 // space must be a multiple of generatorBlockSize |
1399 throw std::logic_error("Sample rates differ, but no resampler available!"); | 1345 sv_frame_t reqSpace = space; |
1400 } | 1346 space = (reqSpace / generatorBlockSize) * generatorBlockSize; |
1401 | 1347 if (space == 0) { |
1402 if (resample && m_resampler) { | 1348 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
1403 | 1349 cout << "requested fill of " << reqSpace |
1404 double ratio = | 1350 << " is less than generator block size of " |
1405 double(getTargetSampleRate()) / double(getSourceSampleRate()); | 1351 << generatorBlockSize << ", leaving it" << endl; |
1406 orig = sv_frame_t(double(orig) / ratio + 0.1); | 1352 #endif |
1407 | 1353 return false; |
1408 // orig must be a multiple of generatorBlockSize | 1354 } |
1409 orig = (orig / generatorBlockSize) * generatorBlockSize; | 1355 |
1410 if (orig == 0) return false; | 1356 if (tmpSize < channels * space) { |
1411 | 1357 delete[] tmp; |
1412 sv_frame_t work = std::max(orig, space); | 1358 tmp = new float[channels * space]; |
1413 | 1359 tmpSize = channels * space; |
1414 // We only allocate one buffer, but we use it in two halves. | 1360 } |
1415 // We place the non-interleaved values in the second half of | 1361 |
1416 // the buffer (orig samples for channel 0, orig samples for | 1362 for (int c = 0; c < channels; ++c) { |
1417 // channel 1 etc), and then interleave them into the first | 1363 |
1418 // half of the buffer. Then we resample back into the second | 1364 bufferPtrs[c] = tmp + c * space; |
1419 // half (interleaved) and de-interleave the results back to | |
1420 // the start of the buffer for insertion into the ringbuffers. | |
1421 // What a faff -- especially as we've already de-interleaved | |
1422 // the audio data from the source file elsewhere before we | |
1423 // even reach this point. | |
1424 | |
1425 if (tmpSize < channels * work * 2) { | |
1426 delete[] tmp; | |
1427 tmp = new float[channels * work * 2]; | |
1428 tmpSize = channels * work * 2; | |
1429 } | |
1430 | |
1431 float *nonintlv = tmp + channels * work; | |
1432 float *intlv = tmp; | |
1433 float *srcout = tmp + channels * work; | |
1434 | |
1435 for (int c = 0; c < channels; ++c) { | |
1436 for (int i = 0; i < orig; ++i) { | |
1437 nonintlv[channels * i + c] = 0.0f; | |
1438 } | |
1439 } | |
1440 | |
1441 for (int c = 0; c < channels; ++c) { | |
1442 bufferPtrs[c] = nonintlv + c * orig; | |
1443 } | |
1444 | |
1445 got = mixModels(f, orig, bufferPtrs); // also modifies f | |
1446 | |
1447 // and interleave into first half | |
1448 for (int c = 0; c < channels; ++c) { | |
1449 for (int i = 0; i < got; ++i) { | |
1450 float sample = nonintlv[c * got + i]; | |
1451 intlv[channels * i + c] = sample; | |
1452 } | |
1453 } | |
1454 | |
1455 sv_frame_t toCopy = m_resampler->resampleInterleaved | |
1456 (intlv, srcout, got, ratio, false); | |
1457 | |
1458 SRC_DATA data; | |
1459 data.data_in = intlv; | |
1460 data.data_out = srcout; | |
1461 data.input_frames = long(got); | |
1462 data.output_frames = long(work); | |
1463 data.src_ratio = ratio; | |
1464 data.end_of_input = 0; | |
1465 | |
1466 int err = src_process(m_converter, &data); | |
1467 | |
1468 sv_frame_t toCopy = sv_frame_t(double(got) * ratio + 0.1); | |
1469 | |
1470 if (err) { | |
1471 cerr | |
1472 << "AudioCallbackPlaySourceFillThread: ERROR in samplerate conversion: " | |
1473 << src_strerror(err) << endl; | |
1474 //!!! Then what? | |
1475 } else { | |
1476 got = data.input_frames_used; | |
1477 toCopy = data.output_frames_gen; | |
1478 #ifdef DEBUG_AUDIO_PLAY_SOURCE | |
1479 cout << "Resampled " << got << " frames to " << toCopy << " frames" << endl; | |
1480 #endif | |
1481 } | |
1482 | |
1483 for (int c = 0; c < channels; ++c) { | |
1484 for (int i = 0; i < toCopy; ++i) { | |
1485 tmp[i] = srcout[channels * i + c]; | |
1486 } | |
1487 RingBuffer<float> *wb = getWriteRingBuffer(c); | |
1488 if (wb) wb->write(tmp, int(toCopy)); | |
1489 } | |
1490 | |
1491 m_writeBufferFill = f; | |
1492 if (readWriteEqual) m_readBufferFill = f; | |
1493 | |
1494 } else { | |
1495 | |
1496 // space must be a multiple of generatorBlockSize | |
1497 sv_frame_t reqSpace = space; | |
1498 space = (reqSpace / generatorBlockSize) * generatorBlockSize; | |
1499 if (space == 0) { | |
1500 #ifdef DEBUG_AUDIO_PLAY_SOURCE | |
1501 cout << "requested fill of " << reqSpace | |
1502 << " is less than generator block size of " | |
1503 << generatorBlockSize << ", leaving it" << endl; | |
1504 #endif | |
1505 return false; | |
1506 } | |
1507 | |
1508 if (tmpSize < channels * space) { | |
1509 delete[] tmp; | |
1510 tmp = new float[channels * space]; | |
1511 tmpSize = channels * space; | |
1512 } | |
1513 | |
1514 for (int c = 0; c < channels; ++c) { | |
1515 | |
1516 bufferPtrs[c] = tmp + c * space; | |
1517 | 1365 |
1518 for (int i = 0; i < space; ++i) { | 1366 for (int i = 0; i < space; ++i) { |
1519 tmp[c * space + i] = 0.0f; | 1367 tmp[c * space + i] = 0.0f; |
1520 } | 1368 } |
1521 } | 1369 } |
1522 | 1370 |
1523 sv_frame_t got = mixModels(f, space, bufferPtrs); // also modifies f | 1371 sv_frame_t got = mixModels(f, space, bufferPtrs); // also modifies f |
1524 | 1372 |
1525 for (int c = 0; c < channels; ++c) { | 1373 for (int c = 0; c < channels; ++c) { |
1526 | 1374 |
1527 RingBuffer<float> *wb = getWriteRingBuffer(c); | 1375 RingBuffer<float> *wb = getWriteRingBuffer(c); |
1528 if (wb) { | 1376 if (wb) { |
1529 int actual = wb->write(bufferPtrs[c], int(got)); | 1377 int actual = wb->write(bufferPtrs[c], int(got)); |
1530 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 1378 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
1531 cout << "Wrote " << actual << " samples for ch " << c << ", now " | 1379 cout << "Wrote " << actual << " samples for ch " << c << ", now " |
1532 << wb->getReadSpace() << " to read" | 1380 << wb->getReadSpace() << " to read" |
1533 << endl; | 1381 << endl; |
1534 #endif | 1382 #endif |
1535 if (actual < got) { | 1383 if (actual < got) { |
1536 cerr << "WARNING: Buffer overrun in channel " << c | 1384 cerr << "WARNING: Buffer overrun in channel " << c |
1537 << ": wrote " << actual << " of " << got | 1385 << ": wrote " << actual << " of " << got |
1538 << " samples" << endl; | 1386 << " samples" << endl; |
1539 } | |
1540 } | 1387 } |
1541 } | 1388 } |
1542 | 1389 } |
1543 m_writeBufferFill = f; | 1390 |
1544 if (readWriteEqual) m_readBufferFill = f; | 1391 m_writeBufferFill = f; |
1545 | 1392 if (readWriteEqual) m_readBufferFill = f; |
1546 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 1393 |
1547 cout << "Read buffer fill is now " << m_readBufferFill << endl; | 1394 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
1548 #endif | 1395 cout << "Read buffer fill is now " << m_readBufferFill << endl; |
1549 | 1396 #endif |
1550 //!!! how do we know when ended? need to mark up a fully-buffered flag and check this if we find the buffers empty in getSourceSamples | 1397 |
1551 } | 1398 //!!! how do we know when ended? need to mark up a fully-buffered flag and check this if we find the buffers empty in getSourceSamples |
1552 | 1399 |
1553 return true; | 1400 return true; |
1554 } | 1401 } |
1555 | 1402 |
1556 sv_frame_t | 1403 sv_frame_t |