BQAFileReader.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version. See the file
12  COPYING included with this distribution for more information.
13 */
14 
15 #include "BQAFileReader.h"
16 
17 #include <bqaudiostream/AudioReadStreamFactory.h>
18 #include <bqaudiostream/AudioReadStream.h>
19 #include <bqaudiostream/Exceptions.h>
20 
21 #include "base/Profiler.h"
22 #include "base/ProgressReporter.h"
23 
24 #include <QFileInfo>
25 
26 using namespace std;
27 
29  DecodeMode decodeMode,
30  CacheMode mode,
31  sv_samplerate_t targetRate,
32  bool normalised,
33  ProgressReporter *reporter) :
34  CodedAudioFileReader(mode, targetRate, normalised),
35  m_source(source),
36  m_path(source.getLocalFilename()),
37  m_cancelled(false),
38  m_completion(0),
39  m_reporter(reporter),
40  m_decodeThread(0)
41 {
42  SVDEBUG << "BQAFileReader: local path: \"" << m_path
43  << "\", decode mode: " << decodeMode << " ("
44  << (decodeMode == DecodeAtOnce ? "DecodeAtOnce" : "DecodeThreaded")
45  << ")" << endl;
46 
47  m_channelCount = 0;
48  m_fileRate = 0;
49 
50  Profiler profiler("BQAFileReader::BQAFileReader");
51 
52  try {
53  m_stream = breakfastquay::AudioReadStreamFactory::createReadStream
54  (m_path.toUtf8().data());
55  } catch (const std::exception &e) {
56  m_error = e.what();
57  SVDEBUG << "BQAFileReader: createReadStream failed: " << m_error << endl;
58  m_stream = 0;
59  return;
60  }
61 
62  m_channelCount = int(m_stream->getChannelCount());
63  m_fileRate = sv_samplerate_t(m_stream->getSampleRate());
64  m_title = QString::fromUtf8(m_stream->getTrackName().c_str());
65  m_maker = QString::fromUtf8(m_stream->getArtistName().c_str());
66 
68 
69  if (decodeMode == DecodeAtOnce) {
70 
71  if (m_reporter) {
72  connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled()));
74  (tr("Decoding %1...").arg(QFileInfo(m_path).fileName()));
75  }
76 
77  sv_frame_t blockSize = 65536;
78  floatvec_t block(blockSize * m_channelCount, 0.f);
79 
80  while (true) {
81  try {
82  sv_frame_t retrieved =
83  m_stream->getInterleavedFrames(blockSize, block.data());
84 
85  addSamplesToDecodeCache(block.data(), retrieved);
86 
87  if (retrieved < blockSize) {
88  break;
89  }
90  } catch (const breakfastquay::InvalidFileFormat &f) {
91  m_error = f.what();
92  SVDEBUG << "BQAFileReader: init failed: " << m_error << endl;
93  break;
94  }
95 
96  if (m_cancelled) break;
97  }
98 
100  endSerialised();
101 
102  if (m_reporter) m_reporter->setProgress(100);
103 
104  delete m_stream;
105  m_stream = 0;
106 
107  } else {
108 
109  if (m_reporter) m_reporter->setProgress(100);
110 
111  m_decodeThread = new DecodeThread(this);
113  }
114 }
115 
117 {
118  Profiler profiler("BQAFileReader::~BQAFileReader");
119 
120  if (m_decodeThread) {
121  m_cancelled = true;
122  m_decodeThread->wait();
123  delete m_decodeThread;
124  }
125 
126  delete m_stream;
127 }
128 
129 void
131 {
132  m_cancelled = true;
133 }
134 
135 void
137 {
138  if (m_reader->m_cacheMode == CacheInTemporaryFile) {
139  m_reader->startSerialised("BQAFileReader::Decode",
140  &m_reader->m_cancelled);
141  if (m_reader->m_cancelled) {
142  return;
143  }
144  }
145 
146  sv_frame_t blockSize = 65536;
147  floatvec_t block(blockSize * m_reader->getChannelCount(), 0.f);
148 
149  while (true) {
150  try {
151  sv_frame_t retrieved =
152  m_reader->m_stream->getInterleavedFrames
153  (blockSize, block.data());
154 
155  m_reader->addSamplesToDecodeCache(block.data(), retrieved);
156 
157  if (retrieved < blockSize) {
158  break;
159  }
160  } catch (const breakfastquay::InvalidFileFormat &f) {
161  m_reader->m_error = f.what();
162  SVDEBUG << "BQAFileReader: decode failed: " << m_reader->m_error << endl;
163  break;
164  }
165 
166  if (m_reader->m_cancelled) break;
167  }
168 
169  if (m_reader->isDecodeCacheInitialised()) m_reader->finishDecodeCache();
170  m_reader->m_completion = 100;
171 
172  m_reader->endSerialised();
173 
174  delete m_reader->m_stream;
175  m_reader->m_stream = 0;
176 }
177 
178 void
179 BQAFileReader::getSupportedExtensions(set<QString> &extensions)
180 {
181  vector<string> exts =
182  breakfastquay::AudioReadStreamFactory::getSupportedFileExtensions();
183  for (auto e: exts) {
184  extensions.insert(QString::fromUtf8(e.c_str()));
185  }
186 }
187 
188 bool
190 {
191  set<QString> extensions;
192  getSupportedExtensions(extensions);
193  return (extensions.find(extension.toLower()) != extensions.end());
194 }
195 
196 bool
198 {
199  // extremely optimistic, but it's better than rejecting everything
201  return (type.startsWith("audio/"));
202 }
203 
204 bool
206 {
207  return (supportsExtension(source.getExtension()) ||
209 }
210 
QString m_title
Definition: BQAFileReader.h:68
double sv_samplerate_t
Sample rate.
Definition: BaseTypes.h:51
QString m_maker
Definition: BQAFileReader.h:69
std::atomic< bool > m_cancelled
Definition: BQAFileReader.h:73
static bool supports(FileSource &source)
int64_t sv_frame_t
Frame index, the unit of our time axis.
Definition: BaseTypes.h:31
static void getSupportedExtensions(std::set< QString > &extensions)
static bool supportsExtension(QString ext)
void start()
Definition: Thread.cpp:34
std::vector< float, breakfastquay::StlAllocator< float > > floatvec_t
Definition: BaseTypes.h:53
ProgressReporter * m_reporter
Definition: BQAFileReader.h:75
BQAFileReader(FileSource source, DecodeMode decodeMode, CacheMode cacheMode, sv_samplerate_t targetRate=0, bool normalised=false, ProgressReporter *reporter=0)
FileSource is a class used to refer to the contents of a file that may be either local or at a remote...
Definition: FileSource.h:59
void addSamplesToDecodeCache(float **samples, sv_frame_t nframes)
virtual ~BQAFileReader()
QString getContentType() const
Return the MIME content type of this file, if known.
Definition: FileSource.cpp:634
QString m_path
Definition: BQAFileReader.h:66
virtual void setProgress(int percentage)=0
#define SVDEBUG
Definition: Debug.h:106
breakfastquay::AudioReadStream * m_stream
Definition: BQAFileReader.h:71
DecodeThread * m_decodeThread
Definition: BQAFileReader.h:84
virtual void setMessage(QString text)=0
QString getExtension() const
Return the file extension for this file, if any.
Definition: FileSource.cpp:640
static bool supportsContentType(QString type)
QString m_error
Definition: BQAFileReader.h:67
bool isDecodeCacheInitialised() const
Profile point instance class.
Definition: Profiler.h:93