annotate data/fileio/AudioFileReaderFactory.cpp @ 1346:75ad55315db4 3.0-integration

More work on getting tests (especially file encoding ones) running on Windows. Various problems here to do with interaction with test filenames in Hg repos
author Chris Cannam
date Fri, 06 Jan 2017 15:44:55 +0000
parents c0fece5e7755
children 1c9bbbb6116a
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"
luisf@665 22 #include "CoreAudioFileReader.h"
Chris@1098 23 #include "AudioFileSizeEstimator.h"
Chris@1098 24
Chris@1098 25 #include "base/StorageAdviser.h"
Chris@386 26
Chris@386 27 #include <QString>
Chris@386 28 #include <QFileInfo>
Chris@386 29 #include <iostream>
Chris@386 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
luisf@665 45 #ifdef HAVE_COREAUDIO
luisf@665 46 CoreAudioFileReader::getSupportedExtensions(extensions);
luisf@665 47 #endif
Chris@386 48
Chris@386 49 QString rv;
Chris@386 50 for (std::set<QString>::const_iterator i = extensions.begin();
Chris@386 51 i != extensions.end(); ++i) {
Chris@386 52 if (i != extensions.begin()) rv += " ";
Chris@386 53 rv += "*." + *i;
Chris@386 54 }
Chris@386 55
Chris@386 56 return rv;
Chris@386 57 }
Chris@386 58
Chris@386 59 AudioFileReader *
Chris@1313 60 AudioFileReaderFactory::createReader(FileSource source,
Chris@1313 61 Parameters params,
Chris@392 62 ProgressReporter *reporter)
Chris@386 63 {
Chris@386 64 QString err;
Chris@386 65
Chris@1342 66 SVDEBUG << "AudioFileReaderFactory: url \"" << source.getLocation() << "\": requested rate: " << params.targetRate << (params.targetRate == 0 ? " (use source rate)" : "") << endl;
Chris@1342 67 SVDEBUG << "AudioFileReaderFactory: local filename \"" << source.getLocalFilename() << "\", content type \"" << source.getContentType() << "\"" << endl;
Chris@386 68
Chris@667 69 if (!source.isOK()) {
Chris@1342 70 SVCERR << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl;
Chris@667 71 return 0;
Chris@667 72 }
Chris@667 73
Chris@667 74 if (!source.isAvailable()) {
Chris@1342 75 SVCERR << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl;
Chris@386 76 return 0;
Chris@386 77 }
Chris@386 78
Chris@386 79 AudioFileReader *reader = 0;
Chris@386 80
Chris@1313 81 sv_samplerate_t targetRate = params.targetRate;
Chris@1313 82 bool normalised = (params.normalisation == Normalisation::Peak);
Chris@1313 83
Chris@1098 84 sv_frame_t estimatedSamples =
Chris@1098 85 AudioFileSizeEstimator::estimate(source, targetRate);
Chris@1098 86
Chris@1097 87 CodedAudioFileReader::CacheMode cacheMode =
Chris@1097 88 CodedAudioFileReader::CacheInTemporaryFile;
Chris@1097 89
Chris@1098 90 if (estimatedSamples > 0) {
Chris@1098 91 size_t kb = (estimatedSamples * sizeof(float)) / 1024;
Chris@1342 92 SVDEBUG << "AudioFileReaderFactory: checking where to potentially cache "
Chris@1342 93 << kb << "K of sample data" << endl;
Chris@1098 94 StorageAdviser::Recommendation rec =
Chris@1098 95 StorageAdviser::recommend(StorageAdviser::SpeedCritical, kb, kb);
Chris@1277 96 if ((rec & StorageAdviser::UseMemory) ||
Chris@1277 97 (rec & StorageAdviser::PreferMemory)) {
Chris@1342 98 SVDEBUG << "AudioFileReaderFactory: cacheing (if at all) in memory" << endl;
Chris@1098 99 cacheMode = CodedAudioFileReader::CacheInMemory;
Chris@1342 100 } else {
Chris@1342 101 SVDEBUG << "AudioFileReaderFactory: cacheing (if at all) on disc" << endl;
Chris@1098 102 }
Chris@1098 103 }
Chris@1098 104
Chris@1097 105 CodedAudioFileReader::DecodeMode decodeMode =
Chris@1313 106 (params.threadingMode == ThreadingMode::Threaded ?
Chris@1097 107 CodedAudioFileReader::DecodeThreaded :
Chris@1097 108 CodedAudioFileReader::DecodeAtOnce);
Chris@386 109
Chris@1313 110 // We go through the set of supported readers at most twice: once
Chris@1313 111 // picking out only the readers that claim to support the given
Chris@1313 112 // file's extension or MIME type, and (if that fails) again
Chris@1313 113 // providing the file to every reader in turn regardless of
Chris@1313 114 // extension or type. (If none of the readers claim to support a
Chris@1313 115 // file, that may just mean its extension is missing or
Chris@1313 116 // misleading. We have to be confident that the reader won't open
Chris@1313 117 // just any old text file or whatever and pretend it's succeeded.)
Chris@1097 118
Chris@1313 119 for (int any = 0; any <= 1; ++any) {
Chris@386 120
Chris@1313 121 bool anyReader = (any > 0);
Chris@386 122
Chris@1342 123 if (!anyReader) {
Chris@1342 124 SVDEBUG << "AudioFileReaderFactory: Checking whether any reader officially handles this source" << endl;
Chris@1342 125 } else {
Chris@1342 126 SVDEBUG << "AudioFileReaderFactory: Source not officially handled by any reader, trying again with each reader in turn"
Chris@1342 127 << endl;
Chris@1342 128 }
Chris@1342 129
Chris@1313 130 if (anyReader || WavFileReader::supports(source)) {
Chris@386 131
Chris@1313 132 reader = new WavFileReader(source);
Chris@823 133
Chris@1313 134 sv_samplerate_t fileRate = reader->getSampleRate();
Chris@1313 135
Chris@1313 136 if (reader->isOK() &&
Chris@1313 137 (!reader->isQuicklySeekable() ||
Chris@1313 138 normalised ||
Chris@1313 139 (cacheMode == CodedAudioFileReader::CacheInMemory) ||
Chris@1313 140 (targetRate != 0 && fileRate != targetRate))) {
Chris@1313 141
Chris@1342 142 SVDEBUG << "AudioFileReaderFactory: WAV file reader rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
Chris@1161 143
Chris@1313 144 delete reader;
Chris@1313 145 reader = new DecodingWavFileReader
Chris@1313 146 (source,
Chris@1313 147 decodeMode, cacheMode,
Chris@1313 148 targetRate ? targetRate : fileRate,
Chris@1313 149 normalised,
Chris@1313 150 reporter);
Chris@1313 151 }
Chris@1313 152
Chris@1313 153 if (reader->isOK()) {
Chris@1342 154 SVDEBUG << "AudioFileReaderFactory: WAV file reader is OK, returning it" << endl;
Chris@1313 155 return reader;
Chris@1313 156 } else {
Chris@1313 157 delete reader;
Chris@1313 158 }
Chris@386 159 }
Chris@386 160
Chris@386 161 #ifdef HAVE_OGGZ
Chris@386 162 #ifdef HAVE_FISHSOUND
Chris@1313 163 if (anyReader || OggVorbisFileReader::supports(source)) {
Chris@1313 164
Chris@1313 165 reader = new OggVorbisFileReader
Chris@1313 166 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1313 167
Chris@1313 168 if (reader->isOK()) {
Chris@1342 169 SVDEBUG << "AudioFileReaderFactory: Ogg file reader is OK, returning it" << endl;
Chris@1313 170 return reader;
Chris@1313 171 } else {
Chris@1313 172 delete reader;
Chris@1313 173 }
Chris@1313 174 }
Chris@386 175 #endif
Chris@386 176 #endif
Chris@386 177
Chris@386 178 #ifdef HAVE_MAD
Chris@1313 179 if (anyReader || MP3FileReader::supports(source)) {
Chris@1313 180
Chris@1313 181 MP3FileReader::GaplessMode gapless =
Chris@1313 182 params.gaplessMode == GaplessMode::Gapless ?
Chris@1313 183 MP3FileReader::GaplessMode::Gapless :
Chris@1313 184 MP3FileReader::GaplessMode::Gappy;
Chris@1313 185
Chris@1313 186 reader = new MP3FileReader
Chris@1313 187 (source, decodeMode, cacheMode, gapless,
Chris@1313 188 targetRate, normalised, reporter);
Chris@1313 189
Chris@1313 190 if (reader->isOK()) {
Chris@1342 191 SVDEBUG << "AudioFileReaderFactory: MP3 file reader is OK, returning it" << endl;
Chris@1313 192 return reader;
Chris@1313 193 } else {
Chris@1313 194 delete reader;
Chris@1313 195 }
Chris@1313 196 }
Chris@386 197 #endif
Chris@386 198
luisf@665 199 #ifdef HAVE_COREAUDIO
Chris@1313 200 if (anyReader || CoreAudioFileReader::supports(source)) {
Chris@1313 201
Chris@1313 202 reader = new CoreAudioFileReader
Chris@1313 203 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1313 204
Chris@1313 205 if (reader->isOK()) {
Chris@1342 206 SVDEBUG << "AudioFileReaderFactory: CoreAudio reader is OK, returning it" << endl;
Chris@1313 207 return reader;
Chris@1313 208 } else {
Chris@1313 209 delete reader;
Chris@1313 210 }
Chris@1313 211 }
luisf@665 212 #endif
luisf@665 213
Chris@1097 214 }
Chris@1097 215
Chris@1342 216 SVCERR << "AudioFileReaderFactory::Failed to create a reader for "
Chris@1342 217 << "url \"" << source.getLocation()
Chris@1342 218 << "\" (local filename \"" << source.getLocalFilename()
Chris@1342 219 << "\", content type \""
Chris@1342 220 << source.getContentType() << "\")" << endl;
Chris@1313 221 return nullptr;
Chris@386 222 }
Chris@386 223