Mercurial > hg > svcore
comparison data/model/ReadOnlyWaveFileModel.cpp @ 1527:710e6250a401 zoom
Merge from default branch
author | Chris Cannam |
---|---|
date | Mon, 17 Sep 2018 13:51:14 +0100 |
parents | d4a28d1479a8 0925b37a3ed1 |
children | 1ae6a19464a7 d93e34684da7 |
comparison
equal
deleted
inserted
replaced
1324:d4a28d1479a8 | 1527:710e6250a401 |
---|---|
104 { | 104 { |
105 m_exiting = true; | 105 m_exiting = true; |
106 if (m_fillThread) m_fillThread->wait(); | 106 if (m_fillThread) m_fillThread->wait(); |
107 if (m_myReader) delete m_reader; | 107 if (m_myReader) delete m_reader; |
108 m_reader = 0; | 108 m_reader = 0; |
109 | |
110 SVDEBUG << "ReadOnlyWaveFileModel: Destructor exiting; we had caches of " | |
111 << (m_cache[0].size() * sizeof(Range)) << " and " | |
112 << (m_cache[1].size() * sizeof(Range)) << " bytes" << endl; | |
109 } | 113 } |
110 | 114 |
111 bool | 115 bool |
112 ReadOnlyWaveFileModel::isOK() const | 116 ReadOnlyWaveFileModel::isOK() const |
113 { | 117 { |
200 { | 204 { |
201 if (m_reader) return m_reader->getLocalFilename(); | 205 if (m_reader) return m_reader->getLocalFilename(); |
202 return ""; | 206 return ""; |
203 } | 207 } |
204 | 208 |
205 vector<float> | 209 floatvec_t |
206 ReadOnlyWaveFileModel::getData(int channel, sv_frame_t start, sv_frame_t count) const | 210 ReadOnlyWaveFileModel::getData(int channel, |
207 { | 211 sv_frame_t start, |
208 // Read directly from the file. This is used for e.g. audio | 212 sv_frame_t count) |
209 // playback or input to transforms. | 213 const |
210 | 214 { |
215 // Read a single channel (if channel >= 0) or a mixdown of all | |
216 // channels (if channel == -1) directly from the file. This is | |
217 // used for e.g. audio playback or input to transforms. | |
218 | |
219 Profiler profiler("ReadOnlyWaveFileModel::getData"); | |
220 | |
211 #ifdef DEBUG_WAVE_FILE_MODEL | 221 #ifdef DEBUG_WAVE_FILE_MODEL |
212 cout << "ReadOnlyWaveFileModel::getData[" << this << "]: " << channel << ", " << start << ", " << count << endl; | 222 cout << "ReadOnlyWaveFileModel::getData[" << this << "]: " << channel << ", " << start << ", " << count << endl; |
213 #endif | 223 #endif |
214 | 224 |
215 int channels = getChannelCount(); | 225 int channels = getChannelCount(); |
216 | 226 |
217 if (channel >= channels) { | 227 if (channel >= channels) { |
218 cerr << "ERROR: WaveFileModel::getData: channel (" | 228 SVCERR << "ERROR: WaveFileModel::getData: channel (" |
219 << channel << ") >= channel count (" << channels << ")" | 229 << channel << ") >= channel count (" << channels << ")" |
220 << endl; | 230 << endl; |
221 return {}; | 231 return {}; |
222 } | 232 } |
223 | 233 |
234 count -= (m_startFrame - start); | 244 count -= (m_startFrame - start); |
235 start = 0; | 245 start = 0; |
236 } | 246 } |
237 } | 247 } |
238 | 248 |
239 vector<float> interleaved = m_reader->getInterleavedFrames(start, count); | 249 floatvec_t interleaved = m_reader->getInterleavedFrames(start, count); |
240 if (channels == 1) return interleaved; | 250 if (channels == 1) return interleaved; |
241 | 251 |
242 sv_frame_t obtained = interleaved.size() / channels; | 252 sv_frame_t obtained = interleaved.size() / channels; |
243 | 253 |
244 vector<float> result(obtained, 0.f); | 254 floatvec_t result(obtained, 0.f); |
245 | 255 |
246 if (channel != -1) { | 256 if (channel != -1) { |
247 // get a single channel | 257 // get a single channel |
248 for (int i = 0; i < obtained; ++i) { | 258 for (int i = 0; i < obtained; ++i) { |
249 result[i] = interleaved[i * channels + channel]; | 259 result[i] = interleaved[i * channels + channel]; |
258 } | 268 } |
259 | 269 |
260 return result; | 270 return result; |
261 } | 271 } |
262 | 272 |
263 vector<vector<float>> | 273 vector<floatvec_t> |
264 ReadOnlyWaveFileModel::getMultiChannelData(int fromchannel, int tochannel, | 274 ReadOnlyWaveFileModel::getMultiChannelData(int fromchannel, int tochannel, |
265 sv_frame_t start, sv_frame_t count) const | 275 sv_frame_t start, sv_frame_t count) const |
266 { | 276 { |
267 // Read directly from the file. This is used for e.g. audio | 277 // Read a set of channels directly from the file. This is used |
268 // playback or input to transforms. | 278 // for e.g. audio playback or input to transforms. |
279 | |
280 Profiler profiler("ReadOnlyWaveFileModel::getMultiChannelData"); | |
269 | 281 |
270 #ifdef DEBUG_WAVE_FILE_MODEL | 282 #ifdef DEBUG_WAVE_FILE_MODEL |
271 cout << "ReadOnlyWaveFileModel::getData[" << this << "]: " << fromchannel << "," << tochannel << ", " << start << ", " << count << endl; | 283 cout << "ReadOnlyWaveFileModel::getData[" << this << "]: " << fromchannel << "," << tochannel << ", " << start << ", " << count << endl; |
272 #endif | 284 #endif |
273 | 285 |
274 int channels = getChannelCount(); | 286 int channels = getChannelCount(); |
275 | 287 |
276 if (fromchannel > tochannel) { | 288 if (fromchannel > tochannel) { |
277 cerr << "ERROR: ReadOnlyWaveFileModel::getData: fromchannel (" | 289 SVCERR << "ERROR: ReadOnlyWaveFileModel::getMultiChannelData: " |
278 << fromchannel << ") > tochannel (" << tochannel << ")" | 290 << "fromchannel (" << fromchannel |
279 << endl; | 291 << ") > tochannel (" << tochannel << ")" |
292 << endl; | |
280 return {}; | 293 return {}; |
281 } | 294 } |
282 | 295 |
283 if (tochannel >= channels) { | 296 if (tochannel >= channels) { |
284 cerr << "ERROR: ReadOnlyWaveFileModel::getData: tochannel (" | 297 SVCERR << "ERROR: ReadOnlyWaveFileModel::getMultiChannelData: " |
285 << tochannel << ") >= channel count (" << channels << ")" | 298 << "tochannel (" << tochannel |
286 << endl; | 299 << ") >= channel count (" << channels << ")" |
300 << endl; | |
287 return {}; | 301 return {}; |
288 } | 302 } |
289 | 303 |
290 if (!m_reader || !m_reader->isOK() || count == 0) { | 304 if (!m_reader || !m_reader->isOK() || count == 0) { |
291 return {}; | 305 return {}; |
302 count -= (m_startFrame - start); | 316 count -= (m_startFrame - start); |
303 start = 0; | 317 start = 0; |
304 } | 318 } |
305 } | 319 } |
306 | 320 |
307 vector<float> interleaved = m_reader->getInterleavedFrames(start, count); | 321 floatvec_t interleaved = m_reader->getInterleavedFrames(start, count); |
308 if (channels == 1) return { interleaved }; | 322 if (channels == 1) return { interleaved }; |
309 | 323 |
310 sv_frame_t obtained = interleaved.size() / channels; | 324 sv_frame_t obtained = interleaved.size() / channels; |
311 vector<vector<float>> result(reqchannels, vector<float>(obtained, 0.f)); | 325 vector<floatvec_t> result(reqchannels, floatvec_t(obtained, 0.f)); |
312 | 326 |
313 for (int c = fromchannel; c <= tochannel; ++c) { | 327 for (int c = fromchannel; c <= tochannel; ++c) { |
314 int destc = c - fromchannel; | 328 int destc = c - fromchannel; |
315 for (int i = 0; i < obtained; ++i) { | 329 for (int i = 0; i < obtained; ++i) { |
316 result[destc][i] = interleaved[i * channels + c]; | 330 result[destc][i] = interleaved[i * channels + c]; |
359 | 373 |
360 int channels = getChannelCount(); | 374 int channels = getChannelCount(); |
361 | 375 |
362 if (cacheType != 0 && cacheType != 1) { | 376 if (cacheType != 0 && cacheType != 1) { |
363 | 377 |
364 // We need to read directly from the file. We haven't got | 378 // We need to read directly from the file. We haven't got |
365 // this cached. Hope the requested area is small. This is | 379 // this cached. Hope the requested area is small. This is |
366 // not optimal -- we'll end up reading the same frames twice | 380 // not optimal -- we'll end up reading the same frames twice |
367 // for stereo files, in two separate calls to this method. | 381 // for stereo files, in two separate calls to this method. |
368 // We could fairly trivially handle this for most cases that | 382 // We could fairly trivially handle this for most cases that |
369 // matter by putting a single cache in getInterleavedFrames | 383 // matter by putting a single cache in getInterleavedFrames |
370 // for short queries. | 384 // for short queries. |
371 | 385 |
372 m_directReadMutex.lock(); | 386 m_directReadMutex.lock(); |
373 | 387 |
374 if (m_lastDirectReadStart != start || | 388 if (m_lastDirectReadStart != start || |
375 m_lastDirectReadCount != count || | 389 m_lastDirectReadCount != count || |
378 m_directRead = m_reader->getInterleavedFrames(start, count); | 392 m_directRead = m_reader->getInterleavedFrames(start, count); |
379 m_lastDirectReadStart = start; | 393 m_lastDirectReadStart = start; |
380 m_lastDirectReadCount = count; | 394 m_lastDirectReadCount = count; |
381 } | 395 } |
382 | 396 |
383 float max = 0.0, min = 0.0, total = 0.0; | 397 float max = 0.0, min = 0.0, total = 0.0; |
384 sv_frame_t i = 0, got = 0; | 398 sv_frame_t i = 0, got = 0; |
385 | 399 |
386 while (i < count) { | 400 while (i < count) { |
387 | 401 |
388 sv_frame_t index = i * channels + channel; | 402 sv_frame_t index = i * channels + channel; |
389 if (index >= (sv_frame_t)m_directRead.size()) break; | 403 if (index >= (sv_frame_t)m_directRead.size()) break; |
390 | 404 |
391 float sample = m_directRead[index]; | 405 float sample = m_directRead[index]; |
392 if (sample > max || got == 0) max = sample; | 406 if (sample > max || got == 0) max = sample; |
393 if (sample < min || got == 0) min = sample; | 407 if (sample < min || got == 0) min = sample; |
394 total += fabsf(sample); | 408 total += fabsf(sample); |
395 | 409 |
396 ++i; | 410 ++i; |
397 ++got; | 411 ++got; |
398 | 412 |
399 if (got == blockSize) { | 413 if (got == blockSize) { |
400 ranges.push_back(Range(min, max, total / float(got))); | 414 ranges.push_back(Range(min, max, total / float(got))); |
401 min = max = total = 0.0f; | 415 min = max = total = 0.0f; |
402 got = 0; | 416 got = 0; |
403 } | 417 } |
404 } | 418 } |
405 | 419 |
406 m_directReadMutex.unlock(); | 420 m_directReadMutex.unlock(); |
407 | 421 |
408 if (got > 0) { | 422 if (got > 0) { |
409 ranges.push_back(Range(min, max, total / float(got))); | 423 ranges.push_back(Range(min, max, total / float(got))); |
410 } | 424 } |
411 | 425 |
412 return; | 426 return; |
413 | 427 |
414 } else { | 428 } else { |
415 | 429 |
416 QMutexLocker locker(&m_mutex); | 430 QMutexLocker locker(&m_mutex); |
417 | 431 |
418 const RangeBlock &cache = m_cache[cacheType]; | 432 const RangeBlock &cache = m_cache[cacheType]; |
419 | 433 |
420 blockSize = roundedBlockSize; | 434 blockSize = roundedBlockSize; |
421 | 435 |
422 sv_frame_t cacheBlock, div; | 436 sv_frame_t cacheBlock, div; |
423 | 437 |
424 cacheBlock = (sv_frame_t(1) << m_zoomConstraint.getMinCachePower()); | 438 cacheBlock = (sv_frame_t(1) << m_zoomConstraint.getMinCachePower()); |
425 if (cacheType == 1) { | 439 if (cacheType == 1) { |
426 cacheBlock = sv_frame_t(double(cacheBlock) * sqrt(2.) + 0.01); | 440 cacheBlock = sv_frame_t(double(cacheBlock) * sqrt(2.) + 0.01); |
427 } | 441 } |
428 div = blockSize / cacheBlock; | 442 div = blockSize / cacheBlock; |
429 | 443 |
430 sv_frame_t startIndex = start / cacheBlock; | 444 sv_frame_t startIndex = start / cacheBlock; |
431 sv_frame_t endIndex = (start + count) / cacheBlock; | 445 sv_frame_t endIndex = (start + count) / cacheBlock; |
432 | 446 |
433 float max = 0.0, min = 0.0, total = 0.0; | 447 float max = 0.0, min = 0.0, total = 0.0; |
434 sv_frame_t i = 0, got = 0; | 448 sv_frame_t i = 0, got = 0; |
435 | 449 |
436 #ifdef DEBUG_WAVE_FILE_MODEL | 450 #ifdef DEBUG_WAVE_FILE_MODEL |
437 cerr << "blockSize is " << blockSize << ", cacheBlock " << cacheBlock << ", start " << start << ", count " << count << " (frame count " << getFrameCount() << "), power is " << power << ", div is " << div << ", startIndex " << startIndex << ", endIndex " << endIndex << endl; | 451 cerr << "blockSize is " << blockSize << ", cacheBlock " << cacheBlock << ", start " << start << ", count " << count << " (frame count " << getFrameCount() << "), power is " << power << ", div is " << div << ", startIndex " << startIndex << ", endIndex " << endIndex << endl; |
438 #endif | 452 #endif |
439 | 453 |
440 for (i = 0; i <= endIndex - startIndex; ) { | 454 for (i = 0; i <= endIndex - startIndex; ) { |
441 | 455 |
442 sv_frame_t index = (i + startIndex) * channels + channel; | 456 sv_frame_t index = (i + startIndex) * channels + channel; |
443 if (!in_range_for(cache, index)) break; | 457 if (!in_range_for(cache, index)) break; |
444 | 458 |
445 const Range &range = cache[index]; | 459 const Range &range = cache[index]; |
446 if (range.max() > max || got == 0) max = range.max(); | 460 if (range.max() > max || got == 0) max = range.max(); |
447 if (range.min() < min || got == 0) min = range.min(); | 461 if (range.min() < min || got == 0) min = range.min(); |
448 total += range.absmean(); | 462 total += range.absmean(); |
449 | 463 |
450 ++i; | 464 ++i; |
451 ++got; | 465 ++got; |
452 | 466 |
453 if (got == div) { | 467 if (got == div) { |
454 ranges.push_back(Range(min, max, total / float(got))); | 468 ranges.push_back(Range(min, max, total / float(got))); |
455 min = max = total = 0.0f; | 469 min = max = total = 0.0f; |
456 got = 0; | 470 got = 0; |
457 } | 471 } |
458 } | 472 } |
459 | 473 |
460 if (got > 0) { | 474 if (got > 0) { |
461 ranges.push_back(Range(min, max, total / float(got))); | 475 ranges.push_back(Range(min, max, total / float(got))); |
462 } | 476 } |
463 } | 477 } |
464 | 478 |
465 #ifdef DEBUG_WAVE_FILE_MODEL | 479 #ifdef DEBUG_WAVE_FILE_MODEL |
466 cerr << "returning " << ranges.size() << " ranges" << endl; | 480 cerr << "returning " << ranges.size() << " ranges" << endl; |
467 #endif | 481 #endif |
542 | 556 |
543 void | 557 void |
544 ReadOnlyWaveFileModel::fillTimerTimedOut() | 558 ReadOnlyWaveFileModel::fillTimerTimedOut() |
545 { | 559 { |
546 if (m_fillThread) { | 560 if (m_fillThread) { |
547 sv_frame_t fillExtent = m_fillThread->getFillExtent(); | 561 sv_frame_t fillExtent = m_fillThread->getFillExtent(); |
548 #ifdef DEBUG_WAVE_FILE_MODEL | 562 #ifdef DEBUG_WAVE_FILE_MODEL |
549 SVDEBUG << "ReadOnlyWaveFileModel::fillTimerTimedOut: extent = " << fillExtent << endl; | 563 SVDEBUG << "ReadOnlyWaveFileModel::fillTimerTimedOut: extent = " << fillExtent << endl; |
550 #endif | 564 #endif |
551 if (fillExtent > m_lastFillExtent) { | 565 if (fillExtent > m_lastFillExtent) { |
552 emit modelChangedWithin(m_lastFillExtent, fillExtent); | 566 emit modelChangedWithin(m_lastFillExtent, fillExtent); |
553 m_lastFillExtent = fillExtent; | 567 m_lastFillExtent = fillExtent; |
554 } | 568 } |
555 } else { | 569 } else { |
556 #ifdef DEBUG_WAVE_FILE_MODEL | 570 #ifdef DEBUG_WAVE_FILE_MODEL |
557 SVDEBUG << "ReadOnlyWaveFileModel::fillTimerTimedOut: no thread" << endl; | 571 SVDEBUG << "ReadOnlyWaveFileModel::fillTimerTimedOut: no thread" << endl; |
558 #endif | 572 #endif |
559 emit modelChanged(); | 573 emit modelChanged(); |
560 } | 574 } |
561 } | 575 } |
562 | 576 |
563 void | 577 void |
564 ReadOnlyWaveFileModel::cacheFilled() | 578 ReadOnlyWaveFileModel::cacheFilled() |
587 cacheBlockSize[1] = (int((1 << m_model.m_zoomConstraint.getMinCachePower()) * | 601 cacheBlockSize[1] = (int((1 << m_model.m_zoomConstraint.getMinCachePower()) * |
588 sqrt(2.) + 0.01)); | 602 sqrt(2.) + 0.01)); |
589 | 603 |
590 sv_frame_t frame = 0; | 604 sv_frame_t frame = 0; |
591 const sv_frame_t readBlockSize = 32768; | 605 const sv_frame_t readBlockSize = 32768; |
592 vector<float> block; | 606 floatvec_t block; |
593 | 607 |
594 if (!m_model.isOK()) return; | 608 if (!m_model.isOK()) return; |
595 | 609 |
596 int channels = m_model.getChannelCount(); | 610 int channels = m_model.getChannelCount(); |
597 bool updating = m_model.m_reader->isUpdating(); | 611 bool updating = m_model.m_reader->isUpdating(); |
641 sv_frame_t gotBlockSize = block.size() / channels; | 655 sv_frame_t gotBlockSize = block.size() / channels; |
642 | 656 |
643 m_model.m_mutex.lock(); | 657 m_model.m_mutex.lock(); |
644 | 658 |
645 for (sv_frame_t i = 0; i < gotBlockSize; ++i) { | 659 for (sv_frame_t i = 0; i < gotBlockSize; ++i) { |
646 | 660 |
647 for (int ch = 0; ch < channels; ++ch) { | 661 for (int ch = 0; ch < channels; ++ch) { |
648 | 662 |
649 sv_frame_t index = channels * i + ch; | 663 sv_frame_t index = channels * i + ch; |
650 float sample = block[index]; | 664 float sample = block[index]; |
651 | 665 |