annotate data/fileio/AudioFileReaderFactory.cpp @ 862:786ee8d1f30e

Fix handling of negative frame times in returned features from plugin -- we don't handle them, so don't insert them into the model (instead of blowing up)
author Chris Cannam
date Wed, 11 Dec 2013 21:40:27 +0000
parents f5cd33909744
children f3cda3280398 59e7fe1b1003
rev   line source
Chris@386 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@386 2
Chris@386 3 /*
Chris@386 4 Sonic Visualiser
Chris@386 5 An audio file viewer and annotation editor.
Chris@386 6 Centre for Digital Music, Queen Mary, University of London.
Chris@386 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@386 8
Chris@386 9 This program is free software; you can redistribute it and/or
Chris@386 10 modify it under the terms of the GNU General Public License as
Chris@386 11 published by the Free Software Foundation; either version 2 of the
Chris@386 12 License, or (at your option) any later version. See the file
Chris@386 13 COPYING included with this distribution for more information.
Chris@386 14 */
Chris@386 15
Chris@386 16 #include "AudioFileReaderFactory.h"
Chris@386 17
Chris@386 18 #include "WavFileReader.h"
Chris@823 19 #include "DecodingWavFileReader.h"
Chris@386 20 #include "OggVorbisFileReader.h"
Chris@386 21 #include "MP3FileReader.h"
Chris@386 22 #include "QuickTimeFileReader.h"
luisf@665 23 #include "CoreAudioFileReader.h"
Chris@386 24
Chris@386 25 #include <QString>
Chris@386 26 #include <QFileInfo>
Chris@386 27 #include <iostream>
Chris@386 28
Chris@386 29 QString
Chris@386 30 AudioFileReaderFactory::getKnownExtensions()
Chris@386 31 {
Chris@386 32 std::set<QString> extensions;
Chris@386 33
Chris@386 34 WavFileReader::getSupportedExtensions(extensions);
Chris@386 35 #ifdef HAVE_MAD
Chris@386 36 MP3FileReader::getSupportedExtensions(extensions);
Chris@386 37 #endif
Chris@386 38 #ifdef HAVE_OGGZ
Chris@386 39 #ifdef HAVE_FISHSOUND
Chris@386 40 OggVorbisFileReader::getSupportedExtensions(extensions);
Chris@386 41 #endif
Chris@386 42 #endif
Chris@386 43 #ifdef HAVE_QUICKTIME
Chris@386 44 QuickTimeFileReader::getSupportedExtensions(extensions);
Chris@386 45 #endif
luisf@665 46 #ifdef HAVE_COREAUDIO
luisf@665 47 CoreAudioFileReader::getSupportedExtensions(extensions);
luisf@665 48 #endif
Chris@386 49
Chris@386 50 QString rv;
Chris@386 51 for (std::set<QString>::const_iterator i = extensions.begin();
Chris@386 52 i != extensions.end(); ++i) {
Chris@386 53 if (i != extensions.begin()) rv += " ";
Chris@386 54 rv += "*." + *i;
Chris@386 55 }
Chris@386 56
Chris@386 57 return rv;
Chris@386 58 }
Chris@386 59
Chris@386 60 AudioFileReader *
Chris@392 61 AudioFileReaderFactory::createReader(FileSource source, size_t targetRate,
Chris@392 62 ProgressReporter *reporter)
Chris@386 63 {
Chris@392 64 return create(source, targetRate, false, reporter);
Chris@386 65 }
Chris@386 66
Chris@386 67 AudioFileReader *
Chris@392 68 AudioFileReaderFactory::createThreadingReader(FileSource source, size_t targetRate,
Chris@392 69 ProgressReporter *reporter)
Chris@386 70 {
Chris@392 71 return create(source, targetRate, true, reporter);
Chris@386 72 }
Chris@386 73
Chris@386 74 AudioFileReader *
Chris@392 75 AudioFileReaderFactory::create(FileSource source, size_t targetRate, bool threading,
Chris@392 76 ProgressReporter *reporter)
Chris@386 77 {
Chris@386 78 QString err;
Chris@386 79
Chris@742 80 SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << endl;
Chris@386 81
Chris@667 82 if (!source.isOK()) {
Chris@843 83 cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl;
Chris@667 84 return 0;
Chris@667 85 }
Chris@667 86
Chris@667 87 if (!source.isAvailable()) {
Chris@690 88 SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl;
Chris@386 89 return 0;
Chris@386 90 }
Chris@386 91
Chris@386 92 AudioFileReader *reader = 0;
Chris@386 93
Chris@386 94 // Try to construct a preferred reader based on the extension or
Chris@386 95 // MIME type.
Chris@386 96
Chris@386 97 if (WavFileReader::supports(source)) {
Chris@386 98
Chris@386 99 reader = new WavFileReader(source);
Chris@386 100
Chris@823 101 int fileRate = reader->getSampleRate();
Chris@386 102
Chris@823 103 if (reader->isOK() &&
Chris@823 104 (!reader->isQuicklySeekable() ||
Chris@823 105 (targetRate != 0 && fileRate != targetRate))) {
Chris@823 106
Chris@823 107 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
Chris@386 108
Chris@386 109 delete reader;
Chris@823 110 reader = new DecodingWavFileReader
Chris@386 111 (source,
Chris@386 112 threading ?
Chris@823 113 DecodingWavFileReader::ResampleThreaded :
Chris@823 114 DecodingWavFileReader::ResampleAtOnce,
Chris@823 115 DecodingWavFileReader::CacheInTemporaryFile,
Chris@823 116 targetRate ? targetRate : fileRate,
Chris@392 117 reporter);
Chris@440 118 if (!reader->isOK()) {
Chris@440 119 delete reader;
Chris@440 120 reader = 0;
Chris@440 121 }
Chris@386 122 }
Chris@386 123 }
Chris@386 124
Chris@386 125 #ifdef HAVE_OGGZ
Chris@386 126 #ifdef HAVE_FISHSOUND
Chris@386 127 if (!reader) {
Chris@386 128 if (OggVorbisFileReader::supports(source)) {
Chris@386 129 reader = new OggVorbisFileReader
Chris@386 130 (source,
Chris@386 131 threading ?
Chris@386 132 OggVorbisFileReader::DecodeThreaded :
Chris@386 133 OggVorbisFileReader::DecodeAtOnce,
Chris@386 134 OggVorbisFileReader::CacheInTemporaryFile,
Chris@392 135 targetRate,
Chris@392 136 reporter);
Chris@440 137 if (!reader->isOK()) {
Chris@440 138 delete reader;
Chris@440 139 reader = 0;
Chris@440 140 }
Chris@386 141 }
Chris@386 142 }
Chris@386 143 #endif
Chris@386 144 #endif
Chris@386 145
Chris@386 146 #ifdef HAVE_MAD
Chris@386 147 if (!reader) {
Chris@386 148 if (MP3FileReader::supports(source)) {
Chris@386 149 reader = new MP3FileReader
Chris@386 150 (source,
Chris@386 151 threading ?
Chris@386 152 MP3FileReader::DecodeThreaded :
Chris@386 153 MP3FileReader::DecodeAtOnce,
Chris@386 154 MP3FileReader::CacheInTemporaryFile,
Chris@392 155 targetRate,
Chris@392 156 reporter);
Chris@440 157 if (!reader->isOK()) {
Chris@440 158 delete reader;
Chris@440 159 reader = 0;
Chris@440 160 }
Chris@386 161 }
Chris@386 162 }
Chris@386 163 #endif
Chris@386 164
Chris@386 165 #ifdef HAVE_QUICKTIME
Chris@386 166 if (!reader) {
Chris@386 167 if (QuickTimeFileReader::supports(source)) {
Chris@386 168 reader = new QuickTimeFileReader
Chris@386 169 (source,
Chris@386 170 threading ?
Chris@386 171 QuickTimeFileReader::DecodeThreaded :
Chris@386 172 QuickTimeFileReader::DecodeAtOnce,
Chris@386 173 QuickTimeFileReader::CacheInTemporaryFile,
Chris@392 174 targetRate,
Chris@392 175 reporter);
Chris@440 176 if (!reader->isOK()) {
Chris@440 177 delete reader;
Chris@440 178 reader = 0;
Chris@440 179 }
Chris@440 180 }
Chris@440 181 }
Chris@440 182 #endif
Chris@440 183
luisf@665 184 #ifdef HAVE_COREAUDIO
luisf@665 185 if (!reader) {
luisf@665 186 if (CoreAudioFileReader::supports(source)) {
luisf@665 187 reader = new CoreAudioFileReader
luisf@665 188 (source,
luisf@665 189 threading ?
luisf@665 190 CoreAudioFileReader::DecodeThreaded :
luisf@665 191 CoreAudioFileReader::DecodeAtOnce,
luisf@665 192 CoreAudioFileReader::CacheInTemporaryFile,
luisf@665 193 targetRate,
luisf@665 194 reporter);
luisf@665 195 if (!reader->isOK()) {
luisf@665 196 delete reader;
luisf@665 197 reader = 0;
luisf@665 198 }
luisf@665 199 }
luisf@665 200 }
luisf@665 201 #endif
luisf@665 202
luisf@665 203
Chris@440 204 // If none of the readers claimed to support this file extension,
Chris@440 205 // perhaps the extension is missing or misleading. Try again,
Chris@440 206 // ignoring it. We have to be confident that the reader won't
Chris@440 207 // open just any old text file or whatever and pretend it's
Chris@440 208 // succeeded
Chris@440 209
Chris@440 210 if (!reader) {
Chris@440 211
Chris@440 212 reader = new WavFileReader(source);
Chris@440 213
Chris@823 214 int fileRate = reader->getSampleRate();
Chris@440 215
Chris@823 216 if (reader->isOK() &&
Chris@823 217 (!reader->isQuicklySeekable() ||
Chris@823 218 (targetRate != 0 && fileRate != targetRate))) {
Chris@823 219
Chris@823 220 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
Chris@440 221
Chris@440 222 delete reader;
Chris@823 223 reader = new DecodingWavFileReader
Chris@440 224 (source,
Chris@440 225 threading ?
Chris@823 226 DecodingWavFileReader::ResampleThreaded :
Chris@823 227 DecodingWavFileReader::ResampleAtOnce,
Chris@823 228 DecodingWavFileReader::CacheInTemporaryFile,
Chris@823 229 targetRate ? targetRate : fileRate,
Chris@440 230 reporter);
Chris@440 231 }
Chris@440 232
Chris@440 233 if (!reader->isOK()) {
Chris@440 234 delete reader;
Chris@440 235 reader = 0;
Chris@440 236 }
Chris@440 237 }
Chris@440 238
Chris@440 239 #ifdef HAVE_OGGZ
Chris@440 240 #ifdef HAVE_FISHSOUND
Chris@440 241 if (!reader) {
Chris@440 242 reader = new OggVorbisFileReader
Chris@440 243 (source,
Chris@440 244 threading ?
Chris@440 245 OggVorbisFileReader::DecodeThreaded :
Chris@440 246 OggVorbisFileReader::DecodeAtOnce,
Chris@440 247 OggVorbisFileReader::CacheInTemporaryFile,
Chris@440 248 targetRate,
Chris@440 249 reporter);
Chris@440 250
Chris@440 251 if (!reader->isOK()) {
Chris@440 252 delete reader;
Chris@440 253 reader = 0;
Chris@440 254 }
Chris@440 255 }
Chris@440 256 #endif
Chris@440 257 #endif
Chris@440 258
Chris@440 259 #ifdef HAVE_MAD
Chris@440 260 if (!reader) {
Chris@440 261 reader = new MP3FileReader
Chris@440 262 (source,
Chris@440 263 threading ?
Chris@440 264 MP3FileReader::DecodeThreaded :
Chris@440 265 MP3FileReader::DecodeAtOnce,
Chris@440 266 MP3FileReader::CacheInTemporaryFile,
Chris@440 267 targetRate,
Chris@440 268 reporter);
Chris@440 269
Chris@440 270 if (!reader->isOK()) {
Chris@440 271 delete reader;
Chris@440 272 reader = 0;
Chris@440 273 }
Chris@440 274 }
Chris@440 275 #endif
Chris@440 276
Chris@440 277 #ifdef HAVE_QUICKTIME
Chris@440 278 if (!reader) {
Chris@440 279 reader = new QuickTimeFileReader
Chris@440 280 (source,
Chris@440 281 threading ?
Chris@440 282 QuickTimeFileReader::DecodeThreaded :
Chris@440 283 QuickTimeFileReader::DecodeAtOnce,
Chris@440 284 QuickTimeFileReader::CacheInTemporaryFile,
Chris@440 285 targetRate,
Chris@440 286 reporter);
Chris@440 287
Chris@440 288 if (!reader->isOK()) {
Chris@440 289 delete reader;
Chris@440 290 reader = 0;
Chris@386 291 }
Chris@386 292 }
Chris@386 293 #endif
Chris@386 294
luisf@665 295 #ifdef HAVE_COREAUDIO
luisf@665 296 if (!reader) {
luisf@665 297 reader = new CoreAudioFileReader
luisf@665 298 (source,
luisf@665 299 threading ?
luisf@665 300 CoreAudioFileReader::DecodeThreaded :
luisf@665 301 CoreAudioFileReader::DecodeAtOnce,
luisf@665 302 CoreAudioFileReader::CacheInTemporaryFile,
luisf@665 303 targetRate,
luisf@665 304 reporter);
luisf@665 305
luisf@665 306 if (!reader->isOK()) {
luisf@665 307 delete reader;
luisf@665 308 reader = 0;
luisf@665 309 }
luisf@665 310 }
luisf@665 311 #endif
luisf@665 312
Chris@386 313 if (reader) {
Chris@386 314 if (reader->isOK()) {
Chris@756 315 SVDEBUG << "AudioFileReaderFactory: Reader is OK" << endl;
Chris@386 316 return reader;
Chris@386 317 }
Chris@843 318 cerr << "AudioFileReaderFactory: Preferred reader for "
Chris@844 319 << "url \"" << source.getLocation()
Chris@386 320 << "\" (content type \""
Chris@686 321 << source.getContentType() << "\") failed";
Chris@386 322
Chris@386 323 if (reader->getError() != "") {
Chris@843 324 cerr << ": \"" << reader->getError() << "\"";
Chris@386 325 }
Chris@843 326 cerr << endl;
Chris@386 327 delete reader;
Chris@386 328 reader = 0;
Chris@386 329 }
Chris@386 330
Chris@843 331 cerr << "AudioFileReaderFactory: No reader" << endl;
Chris@386 332 return reader;
Chris@386 333 }
Chris@386 334