Mercurial > hg > svcore
comparison data/model/WaveFileModel.cpp @ 175:b0f4555b625e
* Introduce WritableWaveFileModel, and use it as an output model for audio
real-time plugin transforms. Updates aren't working correctly yet.
author | Chris Cannam |
---|---|
date | Tue, 03 Oct 2006 14:17:37 +0000 |
parents | 4148ad087959 |
children | 570794f6f6a7 |
comparison
equal
deleted
inserted
replaced
174:f8cf055dbf34 | 175:b0f4555b625e |
---|---|
33 using std::cerr; | 33 using std::cerr; |
34 using std::endl; | 34 using std::endl; |
35 | 35 |
36 WaveFileModel::WaveFileModel(QString path) : | 36 WaveFileModel::WaveFileModel(QString path) : |
37 m_path(path), | 37 m_path(path), |
38 m_myReader(true), | |
38 m_fillThread(0), | 39 m_fillThread(0), |
39 m_updateTimer(0), | 40 m_updateTimer(0), |
40 m_lastFillExtent(0), | 41 m_lastFillExtent(0), |
41 m_exiting(false) | 42 m_exiting(false) |
42 { | 43 { |
43 m_reader = AudioFileReaderFactory::createReader(path); | 44 m_reader = AudioFileReaderFactory::createReader(path); |
45 connect(m_reader, SIGNAL(frameCountChanged()), | |
46 this, SLOT(frameCountChanged())); | |
44 setObjectName(QFileInfo(path).fileName()); | 47 setObjectName(QFileInfo(path).fileName()); |
45 if (isOK()) fillCache(); | 48 if (isOK()) fillCache(); |
46 } | 49 } |
47 | 50 |
51 WaveFileModel::WaveFileModel(QString path, AudioFileReader *reader) : | |
52 m_path(path), | |
53 m_myReader(false), | |
54 m_fillThread(0), | |
55 m_updateTimer(0), | |
56 m_lastFillExtent(0), | |
57 m_exiting(false) | |
58 { | |
59 m_reader = reader; | |
60 connect(m_reader, SIGNAL(frameCountChanged()), | |
61 this, SLOT(frameCountChanged())); | |
62 setObjectName(QFileInfo(path).fileName()); | |
63 if (isOK()) fillCache(); | |
64 } | |
65 | |
48 WaveFileModel::~WaveFileModel() | 66 WaveFileModel::~WaveFileModel() |
49 { | 67 { |
50 m_exiting = true; | 68 m_exiting = true; |
51 if (m_fillThread) m_fillThread->wait(); | 69 if (m_fillThread) m_fillThread->wait(); |
52 delete m_reader; | 70 if (m_myReader) delete m_reader; |
53 m_reader = 0; | 71 m_reader = 0; |
54 } | 72 } |
55 | 73 |
56 bool | 74 bool |
57 WaveFileModel::isOK() const | 75 WaveFileModel::isOK() const |
109 << end << " < " << start << ")" << std::endl; | 127 << end << " < " << start << ")" << std::endl; |
110 assert(end >= start); | 128 assert(end >= start); |
111 } | 129 } |
112 | 130 |
113 if (!m_reader || !m_reader->isOK()) return 0; | 131 if (!m_reader || !m_reader->isOK()) return 0; |
132 | |
133 // std::cerr << "WaveFileModel::getValues(" << channel << ", " | |
134 // << start << ", " << end << "): calling reader" << std::endl; | |
114 | 135 |
115 SampleBlock frames; | 136 SampleBlock frames; |
116 m_reader->getInterleavedFrames(start, end - start, frames); | 137 m_reader->getInterleavedFrames(start, end - start, frames); |
117 | 138 |
118 size_t i = 0; | 139 size_t i = 0; |
355 m_updateTimer->start(100); | 376 m_updateTimer->start(100); |
356 m_fillThread = new RangeCacheFillThread(*this); | 377 m_fillThread = new RangeCacheFillThread(*this); |
357 connect(m_fillThread, SIGNAL(finished()), this, SLOT(cacheFilled())); | 378 connect(m_fillThread, SIGNAL(finished()), this, SLOT(cacheFilled())); |
358 m_mutex.unlock(); | 379 m_mutex.unlock(); |
359 m_fillThread->start(); | 380 m_fillThread->start(); |
381 std::cerr << "WaveFileModel::fillCache: started fill thread" << std::endl; | |
360 } | 382 } |
383 | |
384 void | |
385 WaveFileModel::frameCountChanged() | |
386 { | |
387 m_mutex.lock(); | |
388 if (m_updateTimer) { | |
389 std::cerr << "WaveFileModel::frameCountChanged: updating existing fill thread" << std::endl; | |
390 m_fillThread->frameCountChanged(); | |
391 m_mutex.unlock(); | |
392 } else { | |
393 std::cerr << "WaveFileModel::frameCountChanged: restarting [inefficient]" << std::endl; | |
394 m_cache[0].clear(); | |
395 m_cache[1].clear(); | |
396 m_mutex.unlock(); | |
397 fillCache(); | |
398 } | |
399 } | |
361 | 400 |
362 void | 401 void |
363 WaveFileModel::fillTimerTimedOut() | 402 WaveFileModel::fillTimerTimedOut() |
364 { | 403 { |
365 if (m_fillThread) { | 404 if (m_fillThread) { |
366 size_t fillExtent = m_fillThread->getFillExtent(); | 405 size_t fillExtent = m_fillThread->getFillExtent(); |
406 cerr << "WaveFileModel::fillTimerTimedOut: extent = " << fillExtent << endl; | |
367 if (fillExtent > m_lastFillExtent) { | 407 if (fillExtent > m_lastFillExtent) { |
368 emit modelChanged(m_lastFillExtent, fillExtent); | 408 emit modelChanged(m_lastFillExtent, fillExtent); |
369 m_lastFillExtent = fillExtent; | 409 m_lastFillExtent = fillExtent; |
370 } | 410 } |
371 } else { | 411 } else { |
412 cerr << "WaveFileModel::fillTimerTimedOut: no thread" << std::endl; | |
372 emit modelChanged(); | 413 emit modelChanged(); |
373 } | 414 } |
374 } | 415 } |
375 | 416 |
376 void | 417 void |
381 m_fillThread = 0; | 422 m_fillThread = 0; |
382 delete m_updateTimer; | 423 delete m_updateTimer; |
383 m_updateTimer = 0; | 424 m_updateTimer = 0; |
384 m_mutex.unlock(); | 425 m_mutex.unlock(); |
385 emit modelChanged(); | 426 emit modelChanged(); |
386 // cerr << "WaveFileModel::cacheFilled" << endl; | 427 cerr << "WaveFileModel::cacheFilled" << endl; |
428 } | |
429 | |
430 void | |
431 WaveFileModel::RangeCacheFillThread::frameCountChanged() | |
432 { | |
433 m_frameCount = m_model.getFrameCount(); | |
387 } | 434 } |
388 | 435 |
389 void | 436 void |
390 WaveFileModel::RangeCacheFillThread::run() | 437 WaveFileModel::RangeCacheFillThread::run() |
391 { | 438 { |
399 SampleBlock block; | 446 SampleBlock block; |
400 | 447 |
401 if (!m_model.isOK()) return; | 448 if (!m_model.isOK()) return; |
402 | 449 |
403 size_t channels = m_model.getChannelCount(); | 450 size_t channels = m_model.getChannelCount(); |
404 size_t frames = m_model.getFrameCount(); | |
405 | 451 |
406 Range *range = new Range[2 * channels]; | 452 Range *range = new Range[2 * channels]; |
407 size_t count[2]; | 453 size_t count[2]; |
408 count[0] = count[1] = 0; | 454 count[0] = count[1] = 0; |
409 | 455 |
410 while (frame < frames) { | 456 while (frame < m_frameCount) { |
457 | |
458 std::cerr << "WaveFileModel::fill: frame = " << frame << ", count = " << m_frameCount << std::endl; | |
411 | 459 |
412 m_model.m_reader->getInterleavedFrames(frame, readBlockSize, block); | 460 m_model.m_reader->getInterleavedFrames(frame, readBlockSize, block); |
413 | 461 |
414 for (size_t i = 0; i < readBlockSize; ++i) { | 462 for (size_t i = 0; i < readBlockSize; ++i) { |
415 | 463 |
470 MUNLOCK(&rr, m_model.m_cache[ct].capacity() * sizeof(Range)); | 518 MUNLOCK(&rr, m_model.m_cache[ct].capacity() * sizeof(Range)); |
471 } | 519 } |
472 | 520 |
473 delete[] range; | 521 delete[] range; |
474 | 522 |
475 m_fillExtent = frames; | 523 m_fillExtent = m_frameCount; |
476 | 524 |
477 // for (size_t ct = 0; ct < 2; ++ct) { | 525 for (size_t ct = 0; ct < 2; ++ct) { |
478 // cerr << "Cache type " << ct << " now contains " << m_model.m_cache[ct].size() << " ranges" << endl; | 526 cerr << "Cache type " << ct << " now contains " << m_model.m_cache[ct].size() << " ranges" << endl; |
479 // } | 527 } |
480 } | 528 } |
481 | 529 |
482 void | 530 void |
483 WaveFileModel::toXml(QTextStream &out, | 531 WaveFileModel::toXml(QTextStream &out, |
484 QString indent, | 532 QString indent, |