annotate data/fileio/AudioFileReaderFactory.cpp @ 1247:8f076d02569a piper

Make SVDEBUG always write to a log file -- formerly this was disabled in NDEBUG builds. I think there's little use to that, it just means that we keep adding more cerr debug output because we aren't getting the log we need. And SVDEBUG logging is not usually used in tight loops, I don't think the performance overhead is too serious. Also update the About box.
author Chris Cannam
date Thu, 03 Nov 2016 14:57:00 +0000
parents 6877f4200912
children 13701ab9d2c7
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@1098 24 #include "AudioFileSizeEstimator.h"
Chris@1098 25
Chris@1098 26 #include "base/StorageAdviser.h"
Chris@386 27
Chris@386 28 #include <QString>
Chris@386 29 #include <QFileInfo>
Chris@386 30 #include <iostream>
Chris@386 31
Chris@1161 32 //#define DEBUG_AUDIO_FILE_READER_FACTORY 1
Chris@1161 33
Chris@386 34 QString
Chris@386 35 AudioFileReaderFactory::getKnownExtensions()
Chris@386 36 {
Chris@386 37 std::set<QString> extensions;
Chris@386 38
Chris@386 39 WavFileReader::getSupportedExtensions(extensions);
Chris@386 40 #ifdef HAVE_MAD
Chris@386 41 MP3FileReader::getSupportedExtensions(extensions);
Chris@386 42 #endif
Chris@386 43 #ifdef HAVE_OGGZ
Chris@386 44 #ifdef HAVE_FISHSOUND
Chris@386 45 OggVorbisFileReader::getSupportedExtensions(extensions);
Chris@386 46 #endif
Chris@386 47 #endif
Chris@386 48 #ifdef HAVE_QUICKTIME
Chris@386 49 QuickTimeFileReader::getSupportedExtensions(extensions);
Chris@386 50 #endif
luisf@665 51 #ifdef HAVE_COREAUDIO
luisf@665 52 CoreAudioFileReader::getSupportedExtensions(extensions);
luisf@665 53 #endif
Chris@386 54
Chris@386 55 QString rv;
Chris@386 56 for (std::set<QString>::const_iterator i = extensions.begin();
Chris@386 57 i != extensions.end(); ++i) {
Chris@386 58 if (i != extensions.begin()) rv += " ";
Chris@386 59 rv += "*." + *i;
Chris@386 60 }
Chris@386 61
Chris@386 62 return rv;
Chris@386 63 }
Chris@386 64
Chris@386 65 AudioFileReader *
Chris@920 66 AudioFileReaderFactory::createReader(FileSource source,
Chris@1040 67 sv_samplerate_t targetRate,
Chris@920 68 bool normalised,
Chris@392 69 ProgressReporter *reporter)
Chris@386 70 {
Chris@920 71 return create(source, targetRate, normalised, false, reporter);
Chris@386 72 }
Chris@386 73
Chris@386 74 AudioFileReader *
Chris@920 75 AudioFileReaderFactory::createThreadingReader(FileSource source,
Chris@1040 76 sv_samplerate_t targetRate,
Chris@920 77 bool normalised,
Chris@392 78 ProgressReporter *reporter)
Chris@386 79 {
Chris@920 80 return create(source, targetRate, normalised, true, reporter);
Chris@386 81 }
Chris@386 82
Chris@386 83 AudioFileReader *
Chris@920 84 AudioFileReaderFactory::create(FileSource source,
Chris@1040 85 sv_samplerate_t targetRate,
Chris@920 86 bool normalised,
Chris@920 87 bool threading,
Chris@392 88 ProgressReporter *reporter)
Chris@386 89 {
Chris@386 90 QString err;
Chris@386 91
Chris@1161 92 #ifdef DEBUG_AUDIO_FILE_READER_FACTORY
Chris@1161 93 cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << endl;
Chris@1161 94 #endif
Chris@386 95
Chris@667 96 if (!source.isOK()) {
Chris@843 97 cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl;
Chris@667 98 return 0;
Chris@667 99 }
Chris@667 100
Chris@667 101 if (!source.isAvailable()) {
Chris@1161 102 cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl;
Chris@386 103 return 0;
Chris@386 104 }
Chris@386 105
Chris@386 106 AudioFileReader *reader = 0;
Chris@386 107
Chris@1098 108 sv_frame_t estimatedSamples =
Chris@1098 109 AudioFileSizeEstimator::estimate(source, targetRate);
Chris@1098 110
Chris@1097 111 CodedAudioFileReader::CacheMode cacheMode =
Chris@1097 112 CodedAudioFileReader::CacheInTemporaryFile;
Chris@1097 113
Chris@1098 114 if (estimatedSamples > 0) {
Chris@1098 115 size_t kb = (estimatedSamples * sizeof(float)) / 1024;
Chris@1098 116 StorageAdviser::Recommendation rec =
Chris@1098 117 StorageAdviser::recommend(StorageAdviser::SpeedCritical, kb, kb);
Chris@1098 118 if (rec == StorageAdviser::UseMemory ||
Chris@1098 119 rec == StorageAdviser::PreferMemory) {
Chris@1098 120 cacheMode = CodedAudioFileReader::CacheInMemory;
Chris@1098 121 }
Chris@1098 122 }
Chris@1098 123
Chris@1097 124 CodedAudioFileReader::DecodeMode decodeMode =
Chris@1097 125 (threading ?
Chris@1097 126 CodedAudioFileReader::DecodeThreaded :
Chris@1097 127 CodedAudioFileReader::DecodeAtOnce);
Chris@1097 128
Chris@386 129 // Try to construct a preferred reader based on the extension or
Chris@386 130 // MIME type.
Chris@386 131
Chris@1097 132 #define CHECK(reader) if (!reader->isOK()) { delete reader; reader = 0; }
Chris@1097 133
Chris@386 134 if (WavFileReader::supports(source)) {
Chris@386 135
Chris@386 136 reader = new WavFileReader(source);
Chris@386 137
Chris@1040 138 sv_samplerate_t fileRate = reader->getSampleRate();
Chris@386 139
Chris@823 140 if (reader->isOK() &&
Chris@823 141 (!reader->isQuicklySeekable() ||
Chris@920 142 normalised ||
Chris@1101 143 (cacheMode == CodedAudioFileReader::CacheInMemory) ||
Chris@823 144 (targetRate != 0 && fileRate != targetRate))) {
Chris@823 145
Chris@1161 146 #ifdef DEBUG_AUDIO_FILE_READER_FACTORY
Chris@1170 147 cerr << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
Chris@1161 148 #endif
Chris@1161 149
Chris@386 150 delete reader;
Chris@823 151 reader = new DecodingWavFileReader
Chris@386 152 (source,
Chris@1097 153 decodeMode, cacheMode,
Chris@823 154 targetRate ? targetRate : fileRate,
Chris@920 155 normalised,
Chris@392 156 reporter);
Chris@1097 157 CHECK(reader);
Chris@386 158 }
Chris@386 159 }
Chris@386 160
Chris@386 161 #ifdef HAVE_OGGZ
Chris@386 162 #ifdef HAVE_FISHSOUND
Chris@1097 163 if (!reader && OggVorbisFileReader::supports(source)) {
Chris@1097 164 reader = new OggVorbisFileReader
Chris@1097 165 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 166 CHECK(reader);
Chris@386 167 }
Chris@386 168 #endif
Chris@386 169 #endif
Chris@386 170
Chris@386 171 #ifdef HAVE_MAD
Chris@1097 172 if (!reader && MP3FileReader::supports(source)) {
Chris@1097 173 reader = new MP3FileReader
Chris@1097 174 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 175 CHECK(reader);
Chris@386 176 }
Chris@386 177 #endif
Chris@386 178
Chris@386 179 #ifdef HAVE_QUICKTIME
Chris@1097 180 if (!reader && QuickTimeFileReader::supports(source)) {
Chris@1097 181 reader = new QuickTimeFileReader
Chris@1097 182 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 183 CHECK(reader);
Chris@440 184 }
Chris@440 185 #endif
Chris@440 186
luisf@665 187 #ifdef HAVE_COREAUDIO
Chris@1097 188 if (!reader && CoreAudioFileReader::supports(source)) {
Chris@1097 189 reader = new CoreAudioFileReader
Chris@1097 190 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 191 CHECK(reader);
luisf@665 192 }
luisf@665 193 #endif
luisf@665 194
Chris@1097 195 if (reader) {
Chris@1097 196 // The happy case: a reader recognised the file extension &
Chris@1097 197 // succeeded in opening the file
Chris@1097 198 return reader;
Chris@1097 199 }
Chris@1097 200
Chris@440 201 // If none of the readers claimed to support this file extension,
Chris@440 202 // perhaps the extension is missing or misleading. Try again,
Chris@440 203 // ignoring it. We have to be confident that the reader won't
Chris@440 204 // open just any old text file or whatever and pretend it's
Chris@440 205 // succeeded
Chris@440 206
Chris@1097 207 reader = new WavFileReader(source);
Chris@440 208
Chris@1097 209 sv_samplerate_t fileRate = reader->getSampleRate();
Chris@440 210
Chris@1097 211 if (reader->isOK() &&
Chris@1097 212 (!reader->isQuicklySeekable() ||
Chris@1097 213 normalised ||
Chris@1101 214 (cacheMode == CodedAudioFileReader::CacheInMemory) ||
Chris@1097 215 (targetRate != 0 && fileRate != targetRate))) {
Chris@823 216
Chris@1161 217 #ifdef DEBUG_AUDIO_FILE_READER_FACTORY
Chris@1170 218 cerr << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
Chris@1161 219 #endif
Chris@440 220
Chris@1097 221 delete reader;
Chris@1097 222 reader = new DecodingWavFileReader
Chris@1097 223 (source,
Chris@1097 224 decodeMode, cacheMode,
Chris@1097 225 targetRate ? targetRate : fileRate,
Chris@1097 226 normalised,
Chris@1097 227 reporter);
Chris@1097 228 }
Chris@440 229
Chris@1097 230 CHECK(reader);
Chris@440 231
Chris@440 232 #ifdef HAVE_OGGZ
Chris@440 233 #ifdef HAVE_FISHSOUND
Chris@440 234 if (!reader) {
Chris@440 235 reader = new OggVorbisFileReader
Chris@1097 236 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 237 CHECK(reader);
Chris@440 238 }
Chris@440 239 #endif
Chris@440 240 #endif
Chris@440 241
Chris@440 242 #ifdef HAVE_MAD
Chris@440 243 if (!reader) {
Chris@440 244 reader = new MP3FileReader
Chris@1097 245 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 246 CHECK(reader);
Chris@440 247 }
Chris@440 248 #endif
Chris@440 249
Chris@440 250 #ifdef HAVE_QUICKTIME
Chris@440 251 if (!reader) {
Chris@440 252 reader = new QuickTimeFileReader
Chris@1097 253 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 254 CHECK(reader);
Chris@386 255 }
Chris@386 256 #endif
Chris@386 257
luisf@665 258 #ifdef HAVE_COREAUDIO
luisf@665 259 if (!reader) {
luisf@665 260 reader = new CoreAudioFileReader
Chris@1097 261 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 262 CHECK(reader);
luisf@665 263 }
luisf@665 264 #endif
luisf@665 265
Chris@1097 266 if (!reader) {
Chris@1097 267 cerr << "AudioFileReaderFactory::Failed to create a reader for "
Chris@1097 268 << "url \"" << source.getLocation()
Chris@1097 269 << "\" (content type \""
Chris@1097 270 << source.getContentType() << "\")" << endl;
Chris@1097 271 return nullptr;
Chris@386 272 }
Chris@1097 273
Chris@386 274 return reader;
Chris@386 275 }
Chris@386 276