annotate data/fileio/AudioFileReaderFactory.cpp @ 1101:cd156ede1395 simple-fft-model

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