annotate data/fileio/AudioFileReaderFactory.cpp @ 1161:5b463c7727e5

Use float format for cached files in CodedAudioFileReader, to preserve internal representation (see comment)
author Chris Cannam
date Wed, 24 Feb 2016 10:28:47 +0000
parents a1cd5abcb38b
children 6877f4200912
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@1161 29 //#define DEBUG_AUDIO_FILE_READER_FACTORY 1
Chris@1161 30
Chris@386 31 QString
Chris@386 32 AudioFileReaderFactory::getKnownExtensions()
Chris@386 33 {
Chris@386 34 std::set<QString> extensions;
Chris@386 35
Chris@386 36 WavFileReader::getSupportedExtensions(extensions);
Chris@386 37 #ifdef HAVE_MAD
Chris@386 38 MP3FileReader::getSupportedExtensions(extensions);
Chris@386 39 #endif
Chris@386 40 #ifdef HAVE_OGGZ
Chris@386 41 #ifdef HAVE_FISHSOUND
Chris@386 42 OggVorbisFileReader::getSupportedExtensions(extensions);
Chris@386 43 #endif
Chris@386 44 #endif
Chris@386 45 #ifdef HAVE_QUICKTIME
Chris@386 46 QuickTimeFileReader::getSupportedExtensions(extensions);
Chris@386 47 #endif
luisf@665 48 #ifdef HAVE_COREAUDIO
luisf@665 49 CoreAudioFileReader::getSupportedExtensions(extensions);
luisf@665 50 #endif
Chris@386 51
Chris@386 52 QString rv;
Chris@386 53 for (std::set<QString>::const_iterator i = extensions.begin();
Chris@386 54 i != extensions.end(); ++i) {
Chris@386 55 if (i != extensions.begin()) rv += " ";
Chris@386 56 rv += "*." + *i;
Chris@386 57 }
Chris@386 58
Chris@386 59 return rv;
Chris@386 60 }
Chris@386 61
Chris@386 62 AudioFileReader *
Chris@920 63 AudioFileReaderFactory::createReader(FileSource source,
Chris@1040 64 sv_samplerate_t targetRate,
Chris@920 65 bool normalised,
Chris@392 66 ProgressReporter *reporter)
Chris@386 67 {
Chris@920 68 return create(source, targetRate, normalised, false, reporter);
Chris@386 69 }
Chris@386 70
Chris@386 71 AudioFileReader *
Chris@920 72 AudioFileReaderFactory::createThreadingReader(FileSource source,
Chris@1040 73 sv_samplerate_t targetRate,
Chris@920 74 bool normalised,
Chris@392 75 ProgressReporter *reporter)
Chris@386 76 {
Chris@920 77 return create(source, targetRate, normalised, true, reporter);
Chris@386 78 }
Chris@386 79
Chris@386 80 AudioFileReader *
Chris@920 81 AudioFileReaderFactory::create(FileSource source,
Chris@1040 82 sv_samplerate_t targetRate,
Chris@920 83 bool normalised,
Chris@920 84 bool threading,
Chris@392 85 ProgressReporter *reporter)
Chris@386 86 {
Chris@386 87 QString err;
Chris@386 88
Chris@1161 89 #ifdef DEBUG_AUDIO_FILE_READER_FACTORY
Chris@1161 90 cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << endl;
Chris@1161 91 #endif
Chris@386 92
Chris@667 93 if (!source.isOK()) {
Chris@843 94 cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl;
Chris@667 95 return 0;
Chris@667 96 }
Chris@667 97
Chris@667 98 if (!source.isAvailable()) {
Chris@1161 99 cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl;
Chris@386 100 return 0;
Chris@386 101 }
Chris@386 102
Chris@386 103 AudioFileReader *reader = 0;
Chris@386 104
Chris@386 105 // Try to construct a preferred reader based on the extension or
Chris@386 106 // MIME type.
Chris@386 107
Chris@386 108 if (WavFileReader::supports(source)) {
Chris@386 109
Chris@386 110 reader = new WavFileReader(source);
Chris@386 111
Chris@1040 112 sv_samplerate_t fileRate = reader->getSampleRate();
Chris@386 113
Chris@823 114 if (reader->isOK() &&
Chris@823 115 (!reader->isQuicklySeekable() ||
Chris@920 116 normalised ||
Chris@823 117 (targetRate != 0 && fileRate != targetRate))) {
Chris@823 118
Chris@1161 119 #ifdef DEBUG_AUDIO_FILE_READER_FACTORY
Chris@1161 120 cerr << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
Chris@1161 121 #endif
Chris@1161 122
Chris@386 123 delete reader;
Chris@823 124 reader = new DecodingWavFileReader
Chris@386 125 (source,
Chris@386 126 threading ?
Chris@823 127 DecodingWavFileReader::ResampleThreaded :
Chris@823 128 DecodingWavFileReader::ResampleAtOnce,
Chris@823 129 DecodingWavFileReader::CacheInTemporaryFile,
Chris@823 130 targetRate ? targetRate : fileRate,
Chris@920 131 normalised,
Chris@392 132 reporter);
Chris@440 133 if (!reader->isOK()) {
Chris@440 134 delete reader;
Chris@440 135 reader = 0;
Chris@440 136 }
Chris@386 137 }
Chris@386 138 }
Chris@386 139
Chris@386 140 #ifdef HAVE_OGGZ
Chris@386 141 #ifdef HAVE_FISHSOUND
Chris@386 142 if (!reader) {
Chris@386 143 if (OggVorbisFileReader::supports(source)) {
Chris@386 144 reader = new OggVorbisFileReader
Chris@386 145 (source,
Chris@386 146 threading ?
Chris@386 147 OggVorbisFileReader::DecodeThreaded :
Chris@386 148 OggVorbisFileReader::DecodeAtOnce,
Chris@386 149 OggVorbisFileReader::CacheInTemporaryFile,
Chris@392 150 targetRate,
Chris@920 151 normalised,
Chris@392 152 reporter);
Chris@440 153 if (!reader->isOK()) {
Chris@440 154 delete reader;
Chris@440 155 reader = 0;
Chris@440 156 }
Chris@386 157 }
Chris@386 158 }
Chris@386 159 #endif
Chris@386 160 #endif
Chris@386 161
Chris@386 162 #ifdef HAVE_MAD
Chris@386 163 if (!reader) {
Chris@386 164 if (MP3FileReader::supports(source)) {
Chris@386 165 reader = new MP3FileReader
Chris@386 166 (source,
Chris@386 167 threading ?
Chris@386 168 MP3FileReader::DecodeThreaded :
Chris@386 169 MP3FileReader::DecodeAtOnce,
Chris@386 170 MP3FileReader::CacheInTemporaryFile,
Chris@392 171 targetRate,
Chris@920 172 normalised,
Chris@392 173 reporter);
Chris@440 174 if (!reader->isOK()) {
Chris@440 175 delete reader;
Chris@440 176 reader = 0;
Chris@440 177 }
Chris@386 178 }
Chris@386 179 }
Chris@386 180 #endif
Chris@386 181
Chris@386 182 #ifdef HAVE_QUICKTIME
Chris@386 183 if (!reader) {
Chris@386 184 if (QuickTimeFileReader::supports(source)) {
Chris@386 185 reader = new QuickTimeFileReader
Chris@386 186 (source,
Chris@386 187 threading ?
Chris@386 188 QuickTimeFileReader::DecodeThreaded :
Chris@386 189 QuickTimeFileReader::DecodeAtOnce,
Chris@386 190 QuickTimeFileReader::CacheInTemporaryFile,
Chris@392 191 targetRate,
Chris@920 192 normalised,
Chris@392 193 reporter);
Chris@440 194 if (!reader->isOK()) {
Chris@440 195 delete reader;
Chris@440 196 reader = 0;
Chris@440 197 }
Chris@440 198 }
Chris@440 199 }
Chris@440 200 #endif
Chris@440 201
luisf@665 202 #ifdef HAVE_COREAUDIO
luisf@665 203 if (!reader) {
luisf@665 204 if (CoreAudioFileReader::supports(source)) {
luisf@665 205 reader = new CoreAudioFileReader
luisf@665 206 (source,
luisf@665 207 threading ?
luisf@665 208 CoreAudioFileReader::DecodeThreaded :
luisf@665 209 CoreAudioFileReader::DecodeAtOnce,
luisf@665 210 CoreAudioFileReader::CacheInTemporaryFile,
luisf@665 211 targetRate,
Chris@920 212 normalised,
luisf@665 213 reporter);
luisf@665 214 if (!reader->isOK()) {
luisf@665 215 delete reader;
luisf@665 216 reader = 0;
luisf@665 217 }
luisf@665 218 }
luisf@665 219 }
luisf@665 220 #endif
luisf@665 221
luisf@665 222
Chris@440 223 // If none of the readers claimed to support this file extension,
Chris@440 224 // perhaps the extension is missing or misleading. Try again,
Chris@440 225 // ignoring it. We have to be confident that the reader won't
Chris@440 226 // open just any old text file or whatever and pretend it's
Chris@440 227 // succeeded
Chris@440 228
Chris@440 229 if (!reader) {
Chris@440 230
Chris@440 231 reader = new WavFileReader(source);
Chris@440 232
Chris@1040 233 sv_samplerate_t fileRate = reader->getSampleRate();
Chris@440 234
Chris@823 235 if (reader->isOK() &&
Chris@823 236 (!reader->isQuicklySeekable() ||
Chris@920 237 normalised ||
Chris@823 238 (targetRate != 0 && fileRate != targetRate))) {
Chris@823 239
Chris@1161 240 #ifdef DEBUG_AUDIO_FILE_READER_FACTORY
Chris@1161 241 cerr << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
Chris@1161 242 #endif
Chris@440 243
Chris@440 244 delete reader;
Chris@823 245 reader = new DecodingWavFileReader
Chris@440 246 (source,
Chris@440 247 threading ?
Chris@823 248 DecodingWavFileReader::ResampleThreaded :
Chris@823 249 DecodingWavFileReader::ResampleAtOnce,
Chris@823 250 DecodingWavFileReader::CacheInTemporaryFile,
Chris@823 251 targetRate ? targetRate : fileRate,
Chris@920 252 normalised,
Chris@440 253 reporter);
Chris@440 254 }
Chris@440 255
Chris@440 256 if (!reader->isOK()) {
Chris@440 257 delete reader;
Chris@440 258 reader = 0;
Chris@440 259 }
Chris@440 260 }
Chris@440 261
Chris@440 262 #ifdef HAVE_OGGZ
Chris@440 263 #ifdef HAVE_FISHSOUND
Chris@440 264 if (!reader) {
Chris@440 265 reader = new OggVorbisFileReader
Chris@440 266 (source,
Chris@440 267 threading ?
Chris@440 268 OggVorbisFileReader::DecodeThreaded :
Chris@440 269 OggVorbisFileReader::DecodeAtOnce,
Chris@440 270 OggVorbisFileReader::CacheInTemporaryFile,
Chris@440 271 targetRate,
Chris@440 272 reporter);
Chris@440 273
Chris@440 274 if (!reader->isOK()) {
Chris@440 275 delete reader;
Chris@440 276 reader = 0;
Chris@440 277 }
Chris@440 278 }
Chris@440 279 #endif
Chris@440 280 #endif
Chris@440 281
Chris@440 282 #ifdef HAVE_MAD
Chris@440 283 if (!reader) {
Chris@440 284 reader = new MP3FileReader
Chris@440 285 (source,
Chris@440 286 threading ?
Chris@440 287 MP3FileReader::DecodeThreaded :
Chris@440 288 MP3FileReader::DecodeAtOnce,
Chris@440 289 MP3FileReader::CacheInTemporaryFile,
Chris@440 290 targetRate,
Chris@440 291 reporter);
Chris@440 292
Chris@440 293 if (!reader->isOK()) {
Chris@440 294 delete reader;
Chris@440 295 reader = 0;
Chris@440 296 }
Chris@440 297 }
Chris@440 298 #endif
Chris@440 299
Chris@440 300 #ifdef HAVE_QUICKTIME
Chris@440 301 if (!reader) {
Chris@440 302 reader = new QuickTimeFileReader
Chris@440 303 (source,
Chris@440 304 threading ?
Chris@440 305 QuickTimeFileReader::DecodeThreaded :
Chris@440 306 QuickTimeFileReader::DecodeAtOnce,
Chris@440 307 QuickTimeFileReader::CacheInTemporaryFile,
Chris@440 308 targetRate,
Chris@440 309 reporter);
Chris@440 310
Chris@440 311 if (!reader->isOK()) {
Chris@440 312 delete reader;
Chris@440 313 reader = 0;
Chris@386 314 }
Chris@386 315 }
Chris@386 316 #endif
Chris@386 317
luisf@665 318 #ifdef HAVE_COREAUDIO
luisf@665 319 if (!reader) {
luisf@665 320 reader = new CoreAudioFileReader
luisf@665 321 (source,
luisf@665 322 threading ?
luisf@665 323 CoreAudioFileReader::DecodeThreaded :
luisf@665 324 CoreAudioFileReader::DecodeAtOnce,
luisf@665 325 CoreAudioFileReader::CacheInTemporaryFile,
luisf@665 326 targetRate,
luisf@665 327 reporter);
luisf@665 328
luisf@665 329 if (!reader->isOK()) {
luisf@665 330 delete reader;
luisf@665 331 reader = 0;
luisf@665 332 }
luisf@665 333 }
luisf@665 334 #endif
luisf@665 335
Chris@386 336 if (reader) {
Chris@386 337 if (reader->isOK()) {
Chris@1161 338 #ifdef DEBUG_AUDIO_FILE_READER_FACTORY
Chris@1161 339 cerr << "AudioFileReaderFactory: Reader is OK" << endl;
Chris@1161 340 #endif
Chris@386 341 return reader;
Chris@386 342 }
Chris@843 343 cerr << "AudioFileReaderFactory: Preferred reader for "
Chris@844 344 << "url \"" << source.getLocation()
Chris@386 345 << "\" (content type \""
Chris@686 346 << source.getContentType() << "\") failed";
Chris@386 347
Chris@386 348 if (reader->getError() != "") {
Chris@843 349 cerr << ": \"" << reader->getError() << "\"";
Chris@386 350 }
Chris@843 351 cerr << endl;
Chris@386 352 delete reader;
Chris@386 353 reader = 0;
Chris@386 354 }
Chris@386 355
Chris@843 356 cerr << "AudioFileReaderFactory: No reader" << endl;
Chris@386 357 return reader;
Chris@386 358 }
Chris@386 359