svcore  1.9
AudioFileReaderFactory.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  This file copyright 2006 Chris Cannam and QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "AudioFileReaderFactory.h"
17 
18 #include "WavFileReader.h"
19 #include "DecodingWavFileReader.h"
20 #include "OggVorbisFileReader.h"
21 #include "MP3FileReader.h"
22 #include "QuickTimeFileReader.h"
23 #include "CoreAudioFileReader.h"
24 
25 #include <QString>
26 #include <QFileInfo>
27 #include <iostream>
28 
29 QString
31 {
32  std::set<QString> extensions;
33 
35 #ifdef HAVE_MAD
37 #endif
38 #ifdef HAVE_OGGZ
39 #ifdef HAVE_FISHSOUND
41 #endif
42 #endif
43 #ifdef HAVE_QUICKTIME
44  QuickTimeFileReader::getSupportedExtensions(extensions);
45 #endif
46 #ifdef HAVE_COREAUDIO
47  CoreAudioFileReader::getSupportedExtensions(extensions);
48 #endif
49 
50  QString rv;
51  for (std::set<QString>::const_iterator i = extensions.begin();
52  i != extensions.end(); ++i) {
53  if (i != extensions.begin()) rv += " ";
54  rv += "*." + *i;
55  }
56 
57  return rv;
58 }
59 
62  int targetRate,
63  bool normalised,
64  ProgressReporter *reporter)
65 {
66  return create(source, targetRate, normalised, false, reporter);
67 }
68 
71  int targetRate,
72  bool normalised,
73  ProgressReporter *reporter)
74 {
75  return create(source, targetRate, normalised, true, reporter);
76 }
77 
80  int targetRate,
81  bool normalised,
82  bool threading,
83  ProgressReporter *reporter)
84 {
85  QString err;
86 
87  SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << endl;
88 
89  if (!source.isOK()) {
90  cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl;
91  return 0;
92  }
93 
94  if (!source.isAvailable()) {
95  SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl;
96  return 0;
97  }
98 
99  AudioFileReader *reader = 0;
100 
101  // Try to construct a preferred reader based on the extension or
102  // MIME type.
103 
104  if (WavFileReader::supports(source)) {
105 
106  reader = new WavFileReader(source);
107 
108  int fileRate = reader->getSampleRate();
109 
110  if (reader->isOK() &&
111  (!reader->isQuicklySeekable() ||
112  normalised ||
113  (targetRate != 0 && fileRate != targetRate))) {
114 
115  SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
116 
117  delete reader;
118  reader = new DecodingWavFileReader
119  (source,
120  threading ?
124  targetRate ? targetRate : fileRate,
125  normalised,
126  reporter);
127  if (!reader->isOK()) {
128  delete reader;
129  reader = 0;
130  }
131  }
132  }
133 
134 #ifdef HAVE_OGGZ
135 #ifdef HAVE_FISHSOUND
136  if (!reader) {
137  if (OggVorbisFileReader::supports(source)) {
138  reader = new OggVorbisFileReader
139  (source,
140  threading ?
144  targetRate,
145  normalised,
146  reporter);
147  if (!reader->isOK()) {
148  delete reader;
149  reader = 0;
150  }
151  }
152  }
153 #endif
154 #endif
155 
156 #ifdef HAVE_MAD
157  if (!reader) {
158  if (MP3FileReader::supports(source)) {
159  reader = new MP3FileReader
160  (source,
161  threading ?
165  targetRate,
166  normalised,
167  reporter);
168  if (!reader->isOK()) {
169  delete reader;
170  reader = 0;
171  }
172  }
173  }
174 #endif
175 
176 #ifdef HAVE_QUICKTIME
177  if (!reader) {
178  if (QuickTimeFileReader::supports(source)) {
179  reader = new QuickTimeFileReader
180  (source,
181  threading ?
182  QuickTimeFileReader::DecodeThreaded :
183  QuickTimeFileReader::DecodeAtOnce,
184  QuickTimeFileReader::CacheInTemporaryFile,
185  targetRate,
186  normalised,
187  reporter);
188  if (!reader->isOK()) {
189  delete reader;
190  reader = 0;
191  }
192  }
193  }
194 #endif
195 
196 #ifdef HAVE_COREAUDIO
197  if (!reader) {
198  if (CoreAudioFileReader::supports(source)) {
199  reader = new CoreAudioFileReader
200  (source,
201  threading ?
202  CoreAudioFileReader::DecodeThreaded :
203  CoreAudioFileReader::DecodeAtOnce,
204  CoreAudioFileReader::CacheInTemporaryFile,
205  targetRate,
206  normalised,
207  reporter);
208  if (!reader->isOK()) {
209  delete reader;
210  reader = 0;
211  }
212  }
213  }
214 #endif
215 
216 
217  // If none of the readers claimed to support this file extension,
218  // perhaps the extension is missing or misleading. Try again,
219  // ignoring it. We have to be confident that the reader won't
220  // open just any old text file or whatever and pretend it's
221  // succeeded
222 
223  if (!reader) {
224 
225  reader = new WavFileReader(source);
226 
227  int fileRate = reader->getSampleRate();
228 
229  if (reader->isOK() &&
230  (!reader->isQuicklySeekable() ||
231  normalised ||
232  (targetRate != 0 && fileRate != targetRate))) {
233 
234  SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
235 
236  delete reader;
237  reader = new DecodingWavFileReader
238  (source,
239  threading ?
243  targetRate ? targetRate : fileRate,
244  normalised,
245  reporter);
246  }
247 
248  if (!reader->isOK()) {
249  delete reader;
250  reader = 0;
251  }
252  }
253 
254 #ifdef HAVE_OGGZ
255 #ifdef HAVE_FISHSOUND
256  if (!reader) {
257  reader = new OggVorbisFileReader
258  (source,
259  threading ?
263  targetRate,
264  reporter);
265 
266  if (!reader->isOK()) {
267  delete reader;
268  reader = 0;
269  }
270  }
271 #endif
272 #endif
273 
274 #ifdef HAVE_MAD
275  if (!reader) {
276  reader = new MP3FileReader
277  (source,
278  threading ?
282  targetRate,
283  reporter);
284 
285  if (!reader->isOK()) {
286  delete reader;
287  reader = 0;
288  }
289  }
290 #endif
291 
292 #ifdef HAVE_QUICKTIME
293  if (!reader) {
294  reader = new QuickTimeFileReader
295  (source,
296  threading ?
297  QuickTimeFileReader::DecodeThreaded :
298  QuickTimeFileReader::DecodeAtOnce,
299  QuickTimeFileReader::CacheInTemporaryFile,
300  targetRate,
301  reporter);
302 
303  if (!reader->isOK()) {
304  delete reader;
305  reader = 0;
306  }
307  }
308 #endif
309 
310 #ifdef HAVE_COREAUDIO
311  if (!reader) {
312  reader = new CoreAudioFileReader
313  (source,
314  threading ?
315  CoreAudioFileReader::DecodeThreaded :
316  CoreAudioFileReader::DecodeAtOnce,
317  CoreAudioFileReader::CacheInTemporaryFile,
318  targetRate,
319  reporter);
320 
321  if (!reader->isOK()) {
322  delete reader;
323  reader = 0;
324  }
325  }
326 #endif
327 
328  if (reader) {
329  if (reader->isOK()) {
330  SVDEBUG << "AudioFileReaderFactory: Reader is OK" << endl;
331  return reader;
332  }
333  cerr << "AudioFileReaderFactory: Preferred reader for "
334  << "url \"" << source.getLocation()
335  << "\" (content type \""
336  << source.getContentType() << "\") failed";
337 
338  if (reader->getError() != "") {
339  cerr << ": \"" << reader->getError() << "\"";
340  }
341  cerr << endl;
342  delete reader;
343  reader = 0;
344  }
345 
346  cerr << "AudioFileReaderFactory: No reader" << endl;
347  return reader;
348 }
349 
virtual QString getError() const
static AudioFileReader * createThreadingReader(FileSource source, int targetRate=0, bool normalised=false, ProgressReporter *reporter=0)
Return an audio file reader initialised to the file at the given path, or NULL if no suitable reader ...
static void getSupportedExtensions(std::set< QString > &extensions)
QString getLocation() const
Return the location filename or URL as passed to the constructor.
Definition: FileSource.cpp:595
Reader for audio files using libsndfile.
Definition: WavFileReader.h:36
static AudioFileReader * createReader(FileSource source, int targetRate=0, bool normalised=false, ProgressReporter *reporter=0)
Return an audio file reader initialised to the file at the given path, or NULL if no suitable reader ...
static void getSupportedExtensions(std::set< QString > &extensions)
bool isOK() const
static QString getKnownExtensions()
Return the file extensions that we have audio file readers for, in a format suitable for use with QFi...
bool isOK() const
Return true if the FileSource object is valid and neither error nor cancellation occurred while retri...
Definition: FileSource.cpp:565
static bool supports(FileSource &source)
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
static void getSupportedExtensions(std::set< QString > &extensions)
QString getErrorString() const
Return an error message, if isOK() is false.
Definition: FileSource.cpp:629
static bool supports(FileSource &source)
#define SVDEBUG
Definition: Debug.h:42
QString getContentType() const
Return the MIME content type of this file, if known.
Definition: FileSource.cpp:613
virtual bool isQuicklySeekable() const =0
Return true if this file supports fast seek and random access.
int getSampleRate() const
static AudioFileReader * create(FileSource source, int targetRate, bool normalised, bool threading, ProgressReporter *reporter)
static bool supports(FileSource &source)
bool isAvailable()
Return true if the file or remote URL exists.
Definition: FileSource.cpp:523