annotate data/fileio/AudioFileReaderFactory.cpp @ 1277:13701ab9d2c7 3.0-integration

Actually use the StorageAdviser output properly
author Chris Cannam
date Tue, 22 Nov 2016 16:40:14 +0000
parents 6877f4200912
children 0a9193dc136b
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@1277 118 if ((rec & StorageAdviser::UseMemory) ||
Chris@1277 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