annotate data/fileio/AudioFileReaderFactory.cpp @ 1313:ff9697592bef 3.0-integration

Add gapless preference to prefs dialog; much work on audio read tests
author Chris Cannam
date Thu, 01 Dec 2016 17:45:40 +0000
parents 9f9f55a8af92
children 7d24f92158a7
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@1313 64 AudioFileReaderFactory::createReader(FileSource source,
Chris@1313 65 Parameters params,
Chris@392 66 ProgressReporter *reporter)
Chris@386 67 {
Chris@386 68 QString err;
Chris@386 69
Chris@1313 70 SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << params.targetRate << (params.targetRate == 0 ? " (use source rate)" : "") << endl;
Chris@386 71
Chris@667 72 if (!source.isOK()) {
Chris@1279 73 SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl;
Chris@667 74 return 0;
Chris@667 75 }
Chris@667 76
Chris@667 77 if (!source.isAvailable()) {
Chris@1279 78 SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl;
Chris@386 79 return 0;
Chris@386 80 }
Chris@386 81
Chris@386 82 AudioFileReader *reader = 0;
Chris@386 83
Chris@1313 84 sv_samplerate_t targetRate = params.targetRate;
Chris@1313 85 bool normalised = (params.normalisation == Normalisation::Peak);
Chris@1313 86
Chris@1098 87 sv_frame_t estimatedSamples =
Chris@1098 88 AudioFileSizeEstimator::estimate(source, targetRate);
Chris@1098 89
Chris@1097 90 CodedAudioFileReader::CacheMode cacheMode =
Chris@1097 91 CodedAudioFileReader::CacheInTemporaryFile;
Chris@1097 92
Chris@1098 93 if (estimatedSamples > 0) {
Chris@1098 94 size_t kb = (estimatedSamples * sizeof(float)) / 1024;
Chris@1098 95 StorageAdviser::Recommendation rec =
Chris@1098 96 StorageAdviser::recommend(StorageAdviser::SpeedCritical, kb, kb);
Chris@1277 97 if ((rec & StorageAdviser::UseMemory) ||
Chris@1277 98 (rec & StorageAdviser::PreferMemory)) {
Chris@1098 99 cacheMode = CodedAudioFileReader::CacheInMemory;
Chris@1098 100 }
Chris@1098 101 }
Chris@1098 102
Chris@1097 103 CodedAudioFileReader::DecodeMode decodeMode =
Chris@1313 104 (params.threadingMode == ThreadingMode::Threaded ?
Chris@1097 105 CodedAudioFileReader::DecodeThreaded :
Chris@1097 106 CodedAudioFileReader::DecodeAtOnce);
Chris@386 107
Chris@1313 108 // We go through the set of supported readers at most twice: once
Chris@1313 109 // picking out only the readers that claim to support the given
Chris@1313 110 // file's extension or MIME type, and (if that fails) again
Chris@1313 111 // providing the file to every reader in turn regardless of
Chris@1313 112 // extension or type. (If none of the readers claim to support a
Chris@1313 113 // file, that may just mean its extension is missing or
Chris@1313 114 // misleading. We have to be confident that the reader won't open
Chris@1313 115 // just any old text file or whatever and pretend it's succeeded.)
Chris@1097 116
Chris@1313 117 for (int any = 0; any <= 1; ++any) {
Chris@386 118
Chris@1313 119 bool anyReader = (any > 0);
Chris@386 120
Chris@1313 121 if (anyReader || WavFileReader::supports(source)) {
Chris@386 122
Chris@1313 123 reader = new WavFileReader(source);
Chris@823 124
Chris@1313 125 sv_samplerate_t fileRate = reader->getSampleRate();
Chris@1313 126
Chris@1313 127 if (reader->isOK() &&
Chris@1313 128 (!reader->isQuicklySeekable() ||
Chris@1313 129 normalised ||
Chris@1313 130 (cacheMode == CodedAudioFileReader::CacheInMemory) ||
Chris@1313 131 (targetRate != 0 && fileRate != targetRate))) {
Chris@1313 132
Chris@1313 133 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
Chris@1161 134
Chris@1313 135 delete reader;
Chris@1313 136 reader = new DecodingWavFileReader
Chris@1313 137 (source,
Chris@1313 138 decodeMode, cacheMode,
Chris@1313 139 targetRate ? targetRate : fileRate,
Chris@1313 140 normalised,
Chris@1313 141 reporter);
Chris@1313 142 }
Chris@1313 143
Chris@1313 144 if (reader->isOK()) {
Chris@1313 145 return reader;
Chris@1313 146 } else {
Chris@1313 147 delete reader;
Chris@1313 148 }
Chris@386 149 }
Chris@386 150
Chris@386 151 #ifdef HAVE_OGGZ
Chris@386 152 #ifdef HAVE_FISHSOUND
Chris@1313 153 if (anyReader || OggVorbisFileReader::supports(source)) {
Chris@1313 154
Chris@1313 155 reader = new OggVorbisFileReader
Chris@1313 156 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1313 157
Chris@1313 158 if (reader->isOK()) {
Chris@1313 159 return reader;
Chris@1313 160 } else {
Chris@1313 161 delete reader;
Chris@1313 162 }
Chris@1313 163 }
Chris@386 164 #endif
Chris@386 165 #endif
Chris@386 166
Chris@386 167 #ifdef HAVE_MAD
Chris@1313 168 if (anyReader || MP3FileReader::supports(source)) {
Chris@1313 169
Chris@1313 170 MP3FileReader::GaplessMode gapless =
Chris@1313 171 params.gaplessMode == GaplessMode::Gapless ?
Chris@1313 172 MP3FileReader::GaplessMode::Gapless :
Chris@1313 173 MP3FileReader::GaplessMode::Gappy;
Chris@1313 174
Chris@1313 175 reader = new MP3FileReader
Chris@1313 176 (source, decodeMode, cacheMode, gapless,
Chris@1313 177 targetRate, normalised, reporter);
Chris@1313 178
Chris@1313 179 if (reader->isOK()) {
Chris@1313 180 return reader;
Chris@1313 181 } else {
Chris@1313 182 delete reader;
Chris@1313 183 }
Chris@1313 184 }
Chris@386 185 #endif
Chris@386 186
Chris@386 187 #ifdef HAVE_QUICKTIME
Chris@1313 188 if (anyReader || QuickTimeFileReader::supports(source)) {
Chris@1313 189
Chris@1313 190 reader = new QuickTimeFileReader
Chris@1313 191 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1313 192
Chris@1313 193 if (reader->isOK()) {
Chris@1313 194 return reader;
Chris@1313 195 } else {
Chris@1313 196 delete reader;
Chris@1313 197 }
Chris@1313 198 }
Chris@440 199 #endif
Chris@440 200
luisf@665 201 #ifdef HAVE_COREAUDIO
Chris@1313 202 if (anyReader || CoreAudioFileReader::supports(source)) {
Chris@1313 203
Chris@1313 204 reader = new CoreAudioFileReader
Chris@1313 205 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1313 206
Chris@1313 207 if (reader->isOK()) {
Chris@1313 208 return reader;
Chris@1313 209 } else {
Chris@1313 210 delete reader;
Chris@1313 211 }
Chris@1313 212 }
luisf@665 213 #endif
luisf@665 214
Chris@1097 215 }
Chris@1097 216
Chris@1313 217 SVDEBUG << "AudioFileReaderFactory::Failed to create a reader for "
Chris@1313 218 << "url \"" << source.getLocation()
Chris@1313 219 << "\" (content type \""
Chris@1313 220 << source.getContentType() << "\")" << endl;
Chris@1313 221 return nullptr;
Chris@386 222 }
Chris@386 223