Mercurial > hg > svcore
comparison data/fileio/CodedAudioFileReader.cpp @ 1126:39019ce29178 tony-2.0-integration
Merge through to branch for Tony 2.0
author | Chris Cannam |
---|---|
date | Thu, 20 Aug 2015 14:54:21 +0100 |
parents | 457a1a619c5f |
children | 6877f4200912 |
comparison
equal
deleted
inserted
replaced
1119:e22bfe8ca248 | 1126:39019ce29178 |
---|---|
19 #include "base/TempDirectory.h" | 19 #include "base/TempDirectory.h" |
20 #include "base/Exceptions.h" | 20 #include "base/Exceptions.h" |
21 #include "base/Profiler.h" | 21 #include "base/Profiler.h" |
22 #include "base/Serialiser.h" | 22 #include "base/Serialiser.h" |
23 #include "base/Resampler.h" | 23 #include "base/Resampler.h" |
24 #include "base/StorageAdviser.h" | |
24 | 25 |
25 #include <stdint.h> | 26 #include <stdint.h> |
26 #include <iostream> | 27 #include <iostream> |
27 #include <QDir> | 28 #include <QDir> |
28 #include <QMutexLocker> | 29 #include <QMutexLocker> |
30 | |
31 using namespace std; | |
29 | 32 |
30 CodedAudioFileReader::CodedAudioFileReader(CacheMode cacheMode, | 33 CodedAudioFileReader::CodedAudioFileReader(CacheMode cacheMode, |
31 sv_samplerate_t targetRate, | 34 sv_samplerate_t targetRate, |
32 bool normalised) : | 35 bool normalised) : |
33 m_cacheMode(cacheMode), | 36 m_cacheMode(cacheMode), |
55 CodedAudioFileReader::~CodedAudioFileReader() | 58 CodedAudioFileReader::~CodedAudioFileReader() |
56 { | 59 { |
57 QMutexLocker locker(&m_cacheMutex); | 60 QMutexLocker locker(&m_cacheMutex); |
58 | 61 |
59 endSerialised(); | 62 endSerialised(); |
60 | 63 |
61 if (m_cacheFileWritePtr) sf_close(m_cacheFileWritePtr); | 64 if (m_cacheFileWritePtr) sf_close(m_cacheFileWritePtr); |
62 | 65 |
63 SVDEBUG << "CodedAudioFileReader::~CodedAudioFileReader: deleting cache file reader" << endl; | 66 SVDEBUG << "CodedAudioFileReader::~CodedAudioFileReader: deleting cache file reader" << endl; |
64 | 67 |
65 delete m_cacheFileReader; | 68 delete m_cacheFileReader; |
71 } | 74 } |
72 } | 75 } |
73 | 76 |
74 delete m_resampler; | 77 delete m_resampler; |
75 delete[] m_resampleBuffer; | 78 delete[] m_resampleBuffer; |
79 | |
80 if (!m_data.empty()) { | |
81 StorageAdviser::notifyDoneAllocation | |
82 (StorageAdviser::MemoryAllocation, | |
83 (m_data.size() * sizeof(float)) / 1024); | |
84 } | |
76 } | 85 } |
77 | 86 |
78 void | 87 void |
79 CodedAudioFileReader::startSerialised(QString id) | 88 CodedAudioFileReader::startSerialised(QString id) |
80 { | 89 { |
240 } | 249 } |
241 } | 250 } |
242 } | 251 } |
243 | 252 |
244 void | 253 void |
245 CodedAudioFileReader::addSamplesToDecodeCache(const SampleBlock &samples) | 254 CodedAudioFileReader::addSamplesToDecodeCache(const vector<float> &samples) |
246 { | 255 { |
247 QMutexLocker locker(&m_cacheMutex); | 256 QMutexLocker locker(&m_cacheMutex); |
248 | 257 |
249 if (!m_initialised) return; | 258 if (!m_initialised) return; |
250 | 259 |
290 | 299 |
291 delete m_resampler; | 300 delete m_resampler; |
292 m_resampler = 0; | 301 m_resampler = 0; |
293 | 302 |
294 if (m_cacheMode == CacheInTemporaryFile) { | 303 if (m_cacheMode == CacheInTemporaryFile) { |
304 | |
295 sf_close(m_cacheFileWritePtr); | 305 sf_close(m_cacheFileWritePtr); |
296 m_cacheFileWritePtr = 0; | 306 m_cacheFileWritePtr = 0; |
297 if (m_cacheFileReader) m_cacheFileReader->updateFrameCount(); | 307 if (m_cacheFileReader) m_cacheFileReader->updateFrameCount(); |
308 | |
309 } else { | |
310 // I know, I know, we already allocated it... | |
311 StorageAdviser::notifyPlannedAllocation | |
312 (StorageAdviser::MemoryAllocation, | |
313 (m_data.size() * sizeof(float)) / 1024); | |
298 } | 314 } |
299 } | 315 } |
300 | 316 |
301 void | 317 void |
302 CodedAudioFileReader::pushBuffer(float *buffer, sv_frame_t sz, bool final) | 318 CodedAudioFileReader::pushBuffer(float *buffer, sv_frame_t sz, bool final) |
349 throw InsufficientDiscSpace(TempDirectory::getInstance()->getPath()); | 365 throw InsufficientDiscSpace(TempDirectory::getInstance()->getPath()); |
350 } | 366 } |
351 break; | 367 break; |
352 | 368 |
353 case CacheInMemory: | 369 case CacheInMemory: |
354 m_dataLock.lockForWrite(); | 370 m_dataLock.lock(); |
355 for (sv_frame_t s = 0; s < count; ++s) { | 371 m_data.insert(m_data.end(), buffer, buffer + count); |
356 m_data.push_back(buffer[s]); | |
357 } | |
358 m_dataLock.unlock(); | 372 m_dataLock.unlock(); |
359 break; | 373 break; |
360 } | 374 } |
361 } | 375 } |
362 | 376 |
406 pushBufferNonResampling(m_resampleBuffer, out); | 420 pushBufferNonResampling(m_resampleBuffer, out); |
407 delete[] padding; | 421 delete[] padding; |
408 } | 422 } |
409 } | 423 } |
410 | 424 |
411 SampleBlock | 425 vector<float> |
412 CodedAudioFileReader::getInterleavedFrames(sv_frame_t start, sv_frame_t count) const | 426 CodedAudioFileReader::getInterleavedFrames(sv_frame_t start, sv_frame_t count) const |
413 { | 427 { |
414 // Lock is only required in CacheInMemory mode (the cache file | 428 // Lock is only required in CacheInMemory mode (the cache file |
415 // reader is expected to be thread safe and manage its own | 429 // reader is expected to be thread safe and manage its own |
416 // locking) | 430 // locking) |
417 | 431 |
418 if (!m_initialised) { | 432 if (!m_initialised) { |
419 SVDEBUG << "CodedAudioFileReader::getInterleavedFrames: not initialised" << endl; | 433 SVDEBUG << "CodedAudioFileReader::getInterleavedFrames: not initialised" << endl; |
420 return SampleBlock(); | 434 return {}; |
421 } | 435 } |
422 | 436 |
423 SampleBlock frames; | 437 vector<float> frames; |
424 | 438 |
425 switch (m_cacheMode) { | 439 switch (m_cacheMode) { |
426 | 440 |
427 case CacheInTemporaryFile: | 441 case CacheInTemporaryFile: |
428 if (m_cacheFileReader) { | 442 if (m_cacheFileReader) { |
430 } | 444 } |
431 break; | 445 break; |
432 | 446 |
433 case CacheInMemory: | 447 case CacheInMemory: |
434 { | 448 { |
435 if (!isOK()) return SampleBlock(); | 449 if (!isOK()) return {}; |
436 if (count == 0) return SampleBlock(); | 450 if (count == 0) return {}; |
437 | 451 |
438 sv_frame_t idx = start * m_channelCount; | 452 sv_frame_t ix0 = start * m_channelCount; |
439 sv_frame_t i = 0; | 453 sv_frame_t ix1 = ix0 + (count * m_channelCount); |
440 sv_frame_t n = count * m_channelCount; | 454 |
441 | 455 |
442 frames.resize(n); | 456 // This lock used to be a QReadWriteLock, but it appears that |
443 | 457 // its lock mechanism is significantly slower than QMutex so |
444 m_dataLock.lockForRead(); | 458 // it's not a good idea in cases like this where we don't |
445 while (i < n && in_range_for(m_data, idx)) { | 459 // really have threads taking a long time to read concurrently |
446 frames[i++] = m_data[idx++]; | 460 m_dataLock.lock(); |
447 } | 461 sv_frame_t n = sv_frame_t(m_data.size()); |
462 if (ix1 > n) ix1 = n; | |
463 frames = vector<float>(m_data.begin() + ix0, m_data.begin() + ix1); | |
448 m_dataLock.unlock(); | 464 m_dataLock.unlock(); |
449 | |
450 frames.resize(i); | |
451 } | 465 } |
452 } | 466 } |
453 | 467 |
454 if (m_normalised) { | 468 if (m_normalised) { |
455 for (auto &f: frames) f *= m_gain; | 469 for (auto &f: frames) f *= m_gain; |