annotate data/fileio/AudioFileReaderFactory.cpp @ 1098:329ddaf7415d simple-fft-model

Store temporary audio files in memory if we have plenty of it
author Chris Cannam
date Mon, 15 Jun 2015 14:35:37 +0100
parents abc309f507ae
children cd156ede1395
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@823 139 (targetRate != 0 && fileRate != targetRate))) {
Chris@823 140
Chris@920 141 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
Chris@386 142
Chris@386 143 delete reader;
Chris@823 144 reader = new DecodingWavFileReader
Chris@386 145 (source,
Chris@1097 146 decodeMode, cacheMode,
Chris@823 147 targetRate ? targetRate : fileRate,
Chris@920 148 normalised,
Chris@392 149 reporter);
Chris@1097 150 CHECK(reader);
Chris@386 151 }
Chris@386 152 }
Chris@386 153
Chris@386 154 #ifdef HAVE_OGGZ
Chris@386 155 #ifdef HAVE_FISHSOUND
Chris@1097 156 if (!reader && OggVorbisFileReader::supports(source)) {
Chris@1097 157 reader = new OggVorbisFileReader
Chris@1097 158 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 159 CHECK(reader);
Chris@386 160 }
Chris@386 161 #endif
Chris@386 162 #endif
Chris@386 163
Chris@386 164 #ifdef HAVE_MAD
Chris@1097 165 if (!reader && MP3FileReader::supports(source)) {
Chris@1097 166 reader = new MP3FileReader
Chris@1097 167 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 168 CHECK(reader);
Chris@386 169 }
Chris@386 170 #endif
Chris@386 171
Chris@386 172 #ifdef HAVE_QUICKTIME
Chris@1097 173 if (!reader && QuickTimeFileReader::supports(source)) {
Chris@1097 174 reader = new QuickTimeFileReader
Chris@1097 175 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 176 CHECK(reader);
Chris@440 177 }
Chris@440 178 #endif
Chris@440 179
luisf@665 180 #ifdef HAVE_COREAUDIO
Chris@1097 181 if (!reader && CoreAudioFileReader::supports(source)) {
Chris@1097 182 reader = new CoreAudioFileReader
Chris@1097 183 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 184 CHECK(reader);
luisf@665 185 }
luisf@665 186 #endif
luisf@665 187
Chris@1097 188 if (reader) {
Chris@1097 189 // The happy case: a reader recognised the file extension &
Chris@1097 190 // succeeded in opening the file
Chris@1097 191 return reader;
Chris@1097 192 }
Chris@1097 193
Chris@440 194 // If none of the readers claimed to support this file extension,
Chris@440 195 // perhaps the extension is missing or misleading. Try again,
Chris@440 196 // ignoring it. We have to be confident that the reader won't
Chris@440 197 // open just any old text file or whatever and pretend it's
Chris@440 198 // succeeded
Chris@440 199
Chris@1097 200 reader = new WavFileReader(source);
Chris@440 201
Chris@1097 202 sv_samplerate_t fileRate = reader->getSampleRate();
Chris@440 203
Chris@1097 204 if (reader->isOK() &&
Chris@1097 205 (!reader->isQuicklySeekable() ||
Chris@1097 206 normalised ||
Chris@1097 207 (targetRate != 0 && fileRate != targetRate))) {
Chris@440 208
Chris@1097 209 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
Chris@823 210
Chris@1097 211 delete reader;
Chris@1097 212 reader = new DecodingWavFileReader
Chris@1097 213 (source,
Chris@1097 214 decodeMode, cacheMode,
Chris@1097 215 targetRate ? targetRate : fileRate,
Chris@1097 216 normalised,
Chris@1097 217 reporter);
Chris@1097 218 }
Chris@440 219
Chris@1097 220 CHECK(reader);
Chris@440 221
Chris@440 222 #ifdef HAVE_OGGZ
Chris@440 223 #ifdef HAVE_FISHSOUND
Chris@440 224 if (!reader) {
Chris@440 225 reader = new OggVorbisFileReader
Chris@1097 226 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 227 CHECK(reader);
Chris@440 228 }
Chris@440 229 #endif
Chris@440 230 #endif
Chris@440 231
Chris@440 232 #ifdef HAVE_MAD
Chris@440 233 if (!reader) {
Chris@440 234 reader = new MP3FileReader
Chris@1097 235 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 236 CHECK(reader);
Chris@440 237 }
Chris@440 238 #endif
Chris@440 239
Chris@440 240 #ifdef HAVE_QUICKTIME
Chris@440 241 if (!reader) {
Chris@440 242 reader = new QuickTimeFileReader
Chris@1097 243 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 244 CHECK(reader);
Chris@386 245 }
Chris@386 246 #endif
Chris@386 247
luisf@665 248 #ifdef HAVE_COREAUDIO
luisf@665 249 if (!reader) {
luisf@665 250 reader = new CoreAudioFileReader
Chris@1097 251 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 252 CHECK(reader);
luisf@665 253 }
luisf@665 254 #endif
luisf@665 255
Chris@1097 256 if (!reader) {
Chris@1097 257 cerr << "AudioFileReaderFactory::Failed to create a reader for "
Chris@1097 258 << "url \"" << source.getLocation()
Chris@1097 259 << "\" (content type \""
Chris@1097 260 << source.getContentType() << "\")" << endl;
Chris@1097 261 return nullptr;
Chris@386 262 }
Chris@1097 263
Chris@386 264 return reader;
Chris@386 265 }
Chris@386 266