annotate data/fileio/AudioFileReaderFactory.cpp @ 1305:9f9f55a8af92 mp3-gapless

Add gapless flag to MP3FileReader, and implement trimming the delay samples from the start (padding is not yet trimmed from end)
author Chris Cannam
date Tue, 29 Nov 2016 11:35:56 +0000
parents 0a9193dc136b
children ff9697592bef
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@1279 90 SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << (targetRate == 0 ? " (use source rate)" : "") << endl;
Chris@386 91
Chris@667 92 if (!source.isOK()) {
Chris@1279 93 SVDEBUG << "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@1279 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@1277 114 if ((rec & StorageAdviser::UseMemory) ||
Chris@1277 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@1279 142 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
Chris@1161 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@1305 168 (source, decodeMode, cacheMode, MP3FileReader::Gapless,
Chris@1305 169 targetRate, normalised, reporter);
Chris@1097 170 CHECK(reader);
Chris@386 171 }
Chris@386 172 #endif
Chris@386 173
Chris@386 174 #ifdef HAVE_QUICKTIME
Chris@1097 175 if (!reader && QuickTimeFileReader::supports(source)) {
Chris@1097 176 reader = new QuickTimeFileReader
Chris@1097 177 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 178 CHECK(reader);
Chris@440 179 }
Chris@440 180 #endif
Chris@440 181
luisf@665 182 #ifdef HAVE_COREAUDIO
Chris@1097 183 if (!reader && CoreAudioFileReader::supports(source)) {
Chris@1097 184 reader = new CoreAudioFileReader
Chris@1097 185 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 186 CHECK(reader);
luisf@665 187 }
luisf@665 188 #endif
luisf@665 189
Chris@1097 190 if (reader) {
Chris@1097 191 // The happy case: a reader recognised the file extension &
Chris@1097 192 // succeeded in opening the file
Chris@1097 193 return reader;
Chris@1097 194 }
Chris@1097 195
Chris@440 196 // If none of the readers claimed to support this file extension,
Chris@440 197 // perhaps the extension is missing or misleading. Try again,
Chris@440 198 // ignoring it. We have to be confident that the reader won't
Chris@440 199 // open just any old text file or whatever and pretend it's
Chris@440 200 // succeeded
Chris@440 201
Chris@1097 202 reader = new WavFileReader(source);
Chris@440 203
Chris@1097 204 sv_samplerate_t fileRate = reader->getSampleRate();
Chris@440 205
Chris@1097 206 if (reader->isOK() &&
Chris@1097 207 (!reader->isQuicklySeekable() ||
Chris@1097 208 normalised ||
Chris@1101 209 (cacheMode == CodedAudioFileReader::CacheInMemory) ||
Chris@1097 210 (targetRate != 0 && fileRate != targetRate))) {
Chris@823 211
Chris@1279 212 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
Chris@440 213
Chris@1097 214 delete reader;
Chris@1097 215 reader = new DecodingWavFileReader
Chris@1097 216 (source,
Chris@1097 217 decodeMode, cacheMode,
Chris@1097 218 targetRate ? targetRate : fileRate,
Chris@1097 219 normalised,
Chris@1097 220 reporter);
Chris@1097 221 }
Chris@440 222
Chris@1097 223 CHECK(reader);
Chris@440 224
Chris@440 225 #ifdef HAVE_OGGZ
Chris@440 226 #ifdef HAVE_FISHSOUND
Chris@440 227 if (!reader) {
Chris@440 228 reader = new OggVorbisFileReader
Chris@1097 229 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 230 CHECK(reader);
Chris@440 231 }
Chris@440 232 #endif
Chris@440 233 #endif
Chris@440 234
Chris@440 235 #ifdef HAVE_MAD
Chris@440 236 if (!reader) {
Chris@440 237 reader = new MP3FileReader
Chris@1305 238 (source, decodeMode, cacheMode, MP3FileReader::Gapless,
Chris@1305 239 targetRate, normalised, reporter);
Chris@1097 240 CHECK(reader);
Chris@440 241 }
Chris@440 242 #endif
Chris@440 243
Chris@440 244 #ifdef HAVE_QUICKTIME
Chris@440 245 if (!reader) {
Chris@440 246 reader = new QuickTimeFileReader
Chris@1097 247 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 248 CHECK(reader);
Chris@386 249 }
Chris@386 250 #endif
Chris@386 251
luisf@665 252 #ifdef HAVE_COREAUDIO
luisf@665 253 if (!reader) {
luisf@665 254 reader = new CoreAudioFileReader
Chris@1097 255 (source, decodeMode, cacheMode, targetRate, normalised, reporter);
Chris@1097 256 CHECK(reader);
luisf@665 257 }
luisf@665 258 #endif
luisf@665 259
Chris@1097 260 if (!reader) {
Chris@1279 261 SVDEBUG << "AudioFileReaderFactory::Failed to create a reader for "
Chris@1279 262 << "url \"" << source.getLocation()
Chris@1279 263 << "\" (content type \""
Chris@1279 264 << source.getContentType() << "\")" << endl;
Chris@1097 265 return nullptr;
Chris@386 266 }
Chris@1097 267
Chris@386 268 return reader;
Chris@386 269 }
Chris@386 270