annotate data/fileio/BQAFileReader.cpp @ 1833:21c792334c2e sensible-delimited-data-strings

Rewrite all the DelimitedDataString stuff so as to return vectors of individual cell strings rather than having the classes add the delimiters themselves. Rename accordingly to names based on StringExport. Take advantage of this in the CSV writer code so as to properly quote cells that contain delimiter characters.
author Chris Cannam
date Fri, 03 Apr 2020 17:11:05 +0100
parents 8aa1447fe27e
children 14747f24ad04
rev   line source
Chris@1583 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1583 2
Chris@1583 3 /*
Chris@1583 4 Sonic Visualiser
Chris@1583 5 An audio file viewer and annotation editor.
Chris@1583 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1583 7
Chris@1583 8 This program is free software; you can redistribute it and/or
Chris@1583 9 modify it under the terms of the GNU General Public License as
Chris@1583 10 published by the Free Software Foundation; either version 2 of the
Chris@1583 11 License, or (at your option) any later version. See the file
Chris@1583 12 COPYING included with this distribution for more information.
Chris@1583 13 */
Chris@1583 14
Chris@1583 15 #include "BQAFileReader.h"
Chris@1583 16
Chris@1583 17 #include <bqaudiostream/AudioReadStreamFactory.h>
Chris@1583 18 #include <bqaudiostream/AudioReadStream.h>
Chris@1583 19 #include <bqaudiostream/Exceptions.h>
Chris@1583 20
Chris@1583 21 #include "base/Profiler.h"
Chris@1583 22 #include "base/ProgressReporter.h"
Chris@1583 23
Chris@1583 24 #include <QFileInfo>
Chris@1583 25
Chris@1583 26 using namespace std;
Chris@1583 27
Chris@1583 28 BQAFileReader::BQAFileReader(FileSource source,
Chris@1583 29 DecodeMode decodeMode,
Chris@1583 30 CacheMode mode,
Chris@1583 31 sv_samplerate_t targetRate,
Chris@1583 32 bool normalised,
Chris@1583 33 ProgressReporter *reporter) :
Chris@1583 34 CodedAudioFileReader(mode, targetRate, normalised),
Chris@1583 35 m_source(source),
Chris@1583 36 m_path(source.getLocalFilename()),
Chris@1583 37 m_cancelled(false),
Chris@1583 38 m_completion(0),
Chris@1583 39 m_reporter(reporter),
Chris@1583 40 m_decodeThread(0)
Chris@1583 41 {
Chris@1583 42 SVDEBUG << "BQAFileReader: local path: \"" << m_path
Chris@1583 43 << "\", decode mode: " << decodeMode << " ("
Chris@1583 44 << (decodeMode == DecodeAtOnce ? "DecodeAtOnce" : "DecodeThreaded")
Chris@1583 45 << ")" << endl;
Chris@1583 46
Chris@1583 47 m_channelCount = 0;
Chris@1583 48 m_fileRate = 0;
Chris@1583 49
Chris@1583 50 Profiler profiler("BQAFileReader::BQAFileReader");
Chris@1583 51
Chris@1583 52 try {
Chris@1583 53 m_stream = breakfastquay::AudioReadStreamFactory::createReadStream
Chris@1583 54 (m_path.toUtf8().data());
Chris@1583 55 } catch (const std::exception &e) {
Chris@1583 56 m_error = e.what();
Chris@1595 57 SVDEBUG << "BQAFileReader: createReadStream failed: " << m_error << endl;
Chris@1583 58 m_stream = 0;
Chris@1583 59 return;
Chris@1583 60 }
Chris@1583 61
Chris@1584 62 m_channelCount = int(m_stream->getChannelCount());
Chris@1584 63 m_fileRate = sv_samplerate_t(m_stream->getSampleRate());
Chris@1587 64 m_title = QString::fromUtf8(m_stream->getTrackName().c_str());
Chris@1587 65 m_maker = QString::fromUtf8(m_stream->getArtistName().c_str());
Chris@1583 66
Chris@1583 67 initialiseDecodeCache();
Chris@1583 68
Chris@1583 69 if (decodeMode == DecodeAtOnce) {
Chris@1583 70
Chris@1583 71 if (m_reporter) {
Chris@1583 72 connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled()));
Chris@1583 73 m_reporter->setMessage
Chris@1583 74 (tr("Decoding %1...").arg(QFileInfo(m_path).fileName()));
Chris@1583 75 }
Chris@1583 76
Chris@1583 77 sv_frame_t blockSize = 65536;
Chris@1583 78 floatvec_t block(blockSize * m_channelCount, 0.f);
Chris@1583 79
Chris@1583 80 while (true) {
Chris@1583 81 try {
Chris@1583 82 sv_frame_t retrieved =
Chris@1583 83 m_stream->getInterleavedFrames(blockSize, block.data());
Chris@1583 84
Chris@1583 85 addSamplesToDecodeCache(block.data(), retrieved);
Chris@1583 86
Chris@1583 87 if (retrieved < blockSize) {
Chris@1583 88 break;
Chris@1583 89 }
Chris@1583 90 } catch (const breakfastquay::InvalidFileFormat &f) {
Chris@1583 91 m_error = f.what();
Chris@1595 92 SVDEBUG << "BQAFileReader: init failed: " << m_error << endl;
Chris@1583 93 break;
Chris@1583 94 }
Chris@1583 95
Chris@1583 96 if (m_cancelled) break;
Chris@1583 97 }
Chris@1583 98
Chris@1583 99 if (isDecodeCacheInitialised()) finishDecodeCache();
Chris@1583 100 endSerialised();
Chris@1583 101
Chris@1583 102 if (m_reporter) m_reporter->setProgress(100);
Chris@1583 103
Chris@1583 104 delete m_stream;
Chris@1583 105 m_stream = 0;
Chris@1583 106
Chris@1583 107 } else {
Chris@1583 108
Chris@1583 109 if (m_reporter) m_reporter->setProgress(100);
Chris@1583 110
Chris@1583 111 m_decodeThread = new DecodeThread(this);
Chris@1583 112 m_decodeThread->start();
Chris@1583 113 }
Chris@1583 114 }
Chris@1583 115
Chris@1583 116 BQAFileReader::~BQAFileReader()
Chris@1583 117 {
Chris@1583 118 if (m_decodeThread) {
Chris@1583 119 m_cancelled = true;
Chris@1583 120 m_decodeThread->wait();
Chris@1583 121 delete m_decodeThread;
Chris@1583 122 }
Chris@1583 123
Chris@1583 124 delete m_stream;
Chris@1583 125 }
Chris@1583 126
Chris@1583 127 void
Chris@1583 128 BQAFileReader::cancelled()
Chris@1583 129 {
Chris@1583 130 m_cancelled = true;
Chris@1583 131 }
Chris@1583 132
Chris@1583 133 void
Chris@1583 134 BQAFileReader::DecodeThread::run()
Chris@1583 135 {
Chris@1583 136 if (m_reader->m_cacheMode == CacheInTemporaryFile) {
Chris@1583 137 m_reader->startSerialised("BQAFileReader::Decode");
Chris@1583 138 }
Chris@1583 139
Chris@1583 140 sv_frame_t blockSize = 65536;
Chris@1583 141 floatvec_t block(blockSize * m_reader->getChannelCount(), 0.f);
Chris@1583 142
Chris@1583 143 while (true) {
Chris@1583 144 try {
Chris@1583 145 sv_frame_t retrieved =
Chris@1583 146 m_reader->m_stream->getInterleavedFrames
Chris@1583 147 (blockSize, block.data());
Chris@1583 148
Chris@1583 149 m_reader->addSamplesToDecodeCache(block.data(), retrieved);
Chris@1583 150
Chris@1583 151 if (retrieved < blockSize) {
Chris@1583 152 break;
Chris@1583 153 }
Chris@1583 154 } catch (const breakfastquay::InvalidFileFormat &f) {
Chris@1583 155 m_reader->m_error = f.what();
Chris@1595 156 SVDEBUG << "BQAFileReader: decode failed: " << m_reader->m_error << endl;
Chris@1583 157 break;
Chris@1583 158 }
Chris@1583 159
Chris@1583 160 if (m_reader->m_cancelled) break;
Chris@1583 161 }
Chris@1583 162
Chris@1583 163 if (m_reader->isDecodeCacheInitialised()) m_reader->finishDecodeCache();
Chris@1583 164 m_reader->m_completion = 100;
Chris@1583 165
Chris@1583 166 m_reader->endSerialised();
Chris@1583 167
Chris@1583 168 delete m_reader->m_stream;
Chris@1583 169 m_reader->m_stream = 0;
Chris@1583 170 }
Chris@1583 171
Chris@1583 172 void
Chris@1583 173 BQAFileReader::getSupportedExtensions(set<QString> &extensions)
Chris@1583 174 {
Chris@1583 175 vector<string> exts =
Chris@1583 176 breakfastquay::AudioReadStreamFactory::getSupportedFileExtensions();
Chris@1583 177 for (auto e: exts) {
Chris@1583 178 extensions.insert(QString::fromUtf8(e.c_str()));
Chris@1583 179 }
Chris@1583 180 }
Chris@1583 181
Chris@1583 182 bool
Chris@1583 183 BQAFileReader::supportsExtension(QString extension)
Chris@1583 184 {
Chris@1583 185 set<QString> extensions;
Chris@1583 186 getSupportedExtensions(extensions);
Chris@1583 187 return (extensions.find(extension.toLower()) != extensions.end());
Chris@1583 188 }
Chris@1583 189
Chris@1583 190 bool
Chris@1604 191 BQAFileReader::supportsContentType(QString type)
Chris@1583 192 {
Chris@1604 193 // extremely optimistic, but it's better than rejecting everything
Chris@1604 194 //!!! todo: be more sensible
Chris@1604 195 return (type.startsWith("audio/"));
Chris@1583 196 }
Chris@1583 197
Chris@1583 198 bool
Chris@1583 199 BQAFileReader::supports(FileSource &source)
Chris@1583 200 {
Chris@1583 201 return (supportsExtension(source.getExtension()) ||
Chris@1583 202 supportsContentType(source.getContentType()));
Chris@1583 203 }
Chris@1583 204