annotate data/fileio/DecodingWavFileReader.cpp @ 823:f0558e69a074

Rename Resampling- to DecodingWavFileReader, and use it whenever we have an audio file that is not quickly seekable using libsndfile. Avoids very slow performance when analysing ogg files.
author Chris Cannam
date Wed, 17 Jul 2013 15:40:01 +0100
parents data/fileio/ResamplingWavFileReader.cpp@1424aa29ae95
children f3cda3280398 59e7fe1b1003
rev   line source
Chris@297 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@297 2
Chris@297 3 /*
Chris@297 4 Sonic Visualiser
Chris@297 5 An audio file viewer and annotation editor.
Chris@297 6 Centre for Digital Music, Queen Mary, University of London.
Chris@297 7 This file copyright 2007 QMUL.
Chris@297 8
Chris@297 9 This program is free software; you can redistribute it and/or
Chris@297 10 modify it under the terms of the GNU General Public License as
Chris@297 11 published by the Free Software Foundation; either version 2 of the
Chris@297 12 License, or (at your option) any later version. See the file
Chris@297 13 COPYING included with this distribution for more information.
Chris@297 14 */
Chris@297 15
Chris@823 16 #include "DecodingWavFileReader.h"
Chris@297 17
Chris@297 18 #include "WavFileReader.h"
Chris@297 19 #include "base/Profiler.h"
Chris@392 20 #include "base/ProgressReporter.h"
Chris@297 21
Chris@297 22 #include <QFileInfo>
Chris@297 23
Chris@823 24 DecodingWavFileReader::DecodingWavFileReader(FileSource source,
Chris@297 25 ResampleMode resampleMode,
Chris@297 26 CacheMode mode,
Chris@392 27 size_t targetRate,
Chris@392 28 ProgressReporter *reporter) :
Chris@297 29 CodedAudioFileReader(mode, targetRate),
Chris@316 30 m_source(source),
Chris@316 31 m_path(source.getLocalFilename()),
Chris@297 32 m_cancelled(false),
Chris@297 33 m_processed(0),
Chris@297 34 m_completion(0),
Chris@297 35 m_original(0),
Chris@392 36 m_reporter(reporter),
Chris@297 37 m_decodeThread(0)
Chris@297 38 {
Chris@297 39 m_channelCount = 0;
Chris@297 40 m_fileRate = 0;
Chris@297 41
Chris@823 42 SVDEBUG << "DecodingWavFileReader::DecodingWavFileReader(\""
Chris@687 43 << m_path << "\"): rate " << targetRate << endl;
Chris@297 44
Chris@823 45 Profiler profiler("DecodingWavFileReader::DecodingWavFileReader", true);
Chris@297 46
Chris@316 47 m_original = new WavFileReader(m_path);
Chris@297 48 if (!m_original->isOK()) {
Chris@297 49 m_error = m_original->getError();
Chris@297 50 return;
Chris@297 51 }
Chris@297 52
Chris@297 53 m_channelCount = m_original->getChannelCount();
Chris@297 54 m_fileRate = m_original->getSampleRate();
Chris@297 55
Chris@297 56 initialiseDecodeCache();
Chris@297 57
Chris@297 58 if (resampleMode == ResampleAtOnce) {
Chris@297 59
Chris@392 60 if (m_reporter) {
Chris@392 61 connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled()));
Chris@392 62 m_reporter->setMessage
Chris@823 63 (tr("Decoding %1...").arg(QFileInfo(m_path).fileName()));
Chris@327 64 }
Chris@297 65
Chris@297 66 size_t blockSize = 16384;
Chris@297 67 size_t total = m_original->getFrameCount();
Chris@297 68
Chris@297 69 SampleBlock block;
Chris@297 70
Chris@297 71 for (size_t i = 0; i < total; i += blockSize) {
Chris@297 72
Chris@297 73 size_t count = blockSize;
Chris@297 74 if (i + count > total) count = total - i;
Chris@297 75
Chris@297 76 m_original->getInterleavedFrames(i, count, block);
Chris@297 77 addBlock(block);
Chris@297 78
Chris@297 79 if (m_cancelled) break;
Chris@297 80 }
Chris@297 81
Chris@297 82 if (isDecodeCacheInitialised()) finishDecodeCache();
Chris@398 83 endSerialised();
Chris@297 84
Chris@403 85 if (m_reporter) m_reporter->setProgress(100);
Chris@403 86
Chris@297 87 delete m_original;
Chris@297 88 m_original = 0;
Chris@297 89
Chris@392 90 } else {
Chris@297 91
Chris@392 92 if (m_reporter) m_reporter->setProgress(100);
Chris@297 93
Chris@297 94 m_decodeThread = new DecodeThread(this);
Chris@297 95 m_decodeThread->start();
Chris@297 96 }
Chris@297 97 }
Chris@297 98
Chris@823 99 DecodingWavFileReader::~DecodingWavFileReader()
Chris@297 100 {
Chris@297 101 if (m_decodeThread) {
Chris@297 102 m_cancelled = true;
Chris@297 103 m_decodeThread->wait();
Chris@297 104 delete m_decodeThread;
Chris@297 105 }
Chris@297 106
Chris@297 107 delete m_original;
Chris@297 108 }
Chris@297 109
Chris@297 110 void
Chris@823 111 DecodingWavFileReader::cancelled()
Chris@392 112 {
Chris@392 113 m_cancelled = true;
Chris@392 114 }
Chris@392 115
Chris@392 116 void
Chris@823 117 DecodingWavFileReader::DecodeThread::run()
Chris@297 118 {
Chris@297 119 if (m_reader->m_cacheMode == CacheInTemporaryFile) {
Chris@823 120 m_reader->startSerialised("DecodingWavFileReader::Decode");
Chris@297 121 }
Chris@297 122
Chris@297 123 size_t blockSize = 16384;
Chris@297 124 size_t total = m_reader->m_original->getFrameCount();
Chris@297 125
Chris@297 126 SampleBlock block;
Chris@297 127
Chris@297 128 for (size_t i = 0; i < total; i += blockSize) {
Chris@297 129
Chris@297 130 size_t count = blockSize;
Chris@297 131 if (i + count > total) count = total - i;
Chris@297 132
Chris@297 133 m_reader->m_original->getInterleavedFrames(i, count, block);
Chris@297 134 m_reader->addBlock(block);
Chris@297 135
Chris@297 136 if (m_reader->m_cancelled) break;
Chris@297 137 }
Chris@297 138
Chris@297 139 if (m_reader->isDecodeCacheInitialised()) m_reader->finishDecodeCache();
Chris@297 140 m_reader->m_completion = 100;
Chris@297 141
Chris@297 142 m_reader->endSerialised();
Chris@297 143
Chris@297 144 delete m_reader->m_original;
Chris@297 145 m_reader->m_original = 0;
Chris@297 146 }
Chris@297 147
Chris@297 148 void
Chris@823 149 DecodingWavFileReader::addBlock(const SampleBlock &frames)
Chris@297 150 {
Chris@297 151 addSamplesToDecodeCache(frames);
Chris@297 152
Chris@297 153 m_processed += frames.size();
Chris@297 154
Chris@403 155 float ratio = float(m_sampleRate) / float(m_fileRate);
Chris@403 156
Chris@403 157 int progress = lrint((float(m_processed) * ratio * 100) /
Chris@297 158 float(m_original->getFrameCount()));
Chris@297 159
Chris@297 160 if (progress > 99) progress = 99;
Chris@297 161 m_completion = progress;
Chris@297 162
Chris@392 163 if (m_reporter) {
Chris@392 164 m_reporter->setProgress(progress);
Chris@297 165 }
Chris@297 166 }
Chris@297 167
Chris@297 168 void
Chris@823 169 DecodingWavFileReader::getSupportedExtensions(std::set<QString> &extensions)
Chris@297 170 {
Chris@297 171 WavFileReader::getSupportedExtensions(extensions);
Chris@297 172 }
Chris@297 173
Chris@316 174 bool
Chris@823 175 DecodingWavFileReader::supportsExtension(QString extension)
Chris@316 176 {
Chris@316 177 return WavFileReader::supportsExtension(extension);
Chris@316 178 }
Chris@297 179
Chris@316 180 bool
Chris@823 181 DecodingWavFileReader::supportsContentType(QString type)
Chris@316 182 {
Chris@316 183 return WavFileReader::supportsContentType(type);
Chris@316 184 }
Chris@316 185
Chris@316 186 bool
Chris@823 187 DecodingWavFileReader::supports(FileSource &source)
Chris@316 188 {
Chris@316 189 return WavFileReader::supports(source);
Chris@316 190 }
Chris@316 191
Chris@316 192