annotate data/fileio/AudioFileReaderFactory.cpp @ 1008:d9e0e59a1581

When using an aggregate model to pass data to a transform, zero-pad the shorter input to the duration of the longer rather than truncating the longer. (This is better behaviour for e.g. MATCH, and in any case the code was previously truncating incorrectly and ending up with garbage data at the end.)
author Chris Cannam
date Fri, 14 Nov 2014 13:51:33 +0000
parents d03b3d956358
children a1cd5abcb38b
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@386 24
Chris@386 25 #include <QString>
Chris@386 26 #include <QFileInfo>
Chris@386 27 #include <iostream>
Chris@386 28
Chris@386 29 QString
Chris@386 30 AudioFileReaderFactory::getKnownExtensions()
Chris@386 31 {
Chris@386 32 std::set<QString> extensions;
Chris@386 33
Chris@386 34 WavFileReader::getSupportedExtensions(extensions);
Chris@386 35 #ifdef HAVE_MAD
Chris@386 36 MP3FileReader::getSupportedExtensions(extensions);
Chris@386 37 #endif
Chris@386 38 #ifdef HAVE_OGGZ
Chris@386 39 #ifdef HAVE_FISHSOUND
Chris@386 40 OggVorbisFileReader::getSupportedExtensions(extensions);
Chris@386 41 #endif
Chris@386 42 #endif
Chris@386 43 #ifdef HAVE_QUICKTIME
Chris@386 44 QuickTimeFileReader::getSupportedExtensions(extensions);
Chris@386 45 #endif
luisf@665 46 #ifdef HAVE_COREAUDIO
luisf@665 47 CoreAudioFileReader::getSupportedExtensions(extensions);
luisf@665 48 #endif
Chris@386 49
Chris@386 50 QString rv;
Chris@386 51 for (std::set<QString>::const_iterator i = extensions.begin();
Chris@386 52 i != extensions.end(); ++i) {
Chris@386 53 if (i != extensions.begin()) rv += " ";
Chris@386 54 rv += "*." + *i;
Chris@386 55 }
Chris@386 56
Chris@386 57 return rv;
Chris@386 58 }
Chris@386 59
Chris@386 60 AudioFileReader *
Chris@920 61 AudioFileReaderFactory::createReader(FileSource source,
Chris@933 62 int targetRate,
Chris@920 63 bool normalised,
Chris@392 64 ProgressReporter *reporter)
Chris@386 65 {
Chris@920 66 return create(source, targetRate, normalised, false, reporter);
Chris@386 67 }
Chris@386 68
Chris@386 69 AudioFileReader *
Chris@920 70 AudioFileReaderFactory::createThreadingReader(FileSource source,
Chris@933 71 int targetRate,
Chris@920 72 bool normalised,
Chris@392 73 ProgressReporter *reporter)
Chris@386 74 {
Chris@920 75 return create(source, targetRate, normalised, true, reporter);
Chris@386 76 }
Chris@386 77
Chris@386 78 AudioFileReader *
Chris@920 79 AudioFileReaderFactory::create(FileSource source,
Chris@933 80 int targetRate,
Chris@920 81 bool normalised,
Chris@920 82 bool threading,
Chris@392 83 ProgressReporter *reporter)
Chris@386 84 {
Chris@386 85 QString err;
Chris@386 86
Chris@742 87 SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << endl;
Chris@386 88
Chris@667 89 if (!source.isOK()) {
Chris@843 90 cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl;
Chris@667 91 return 0;
Chris@667 92 }
Chris@667 93
Chris@667 94 if (!source.isAvailable()) {
Chris@690 95 SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl;
Chris@386 96 return 0;
Chris@386 97 }
Chris@386 98
Chris@386 99 AudioFileReader *reader = 0;
Chris@386 100
Chris@386 101 // Try to construct a preferred reader based on the extension or
Chris@386 102 // MIME type.
Chris@386 103
Chris@386 104 if (WavFileReader::supports(source)) {
Chris@386 105
Chris@386 106 reader = new WavFileReader(source);
Chris@386 107
Chris@823 108 int fileRate = reader->getSampleRate();
Chris@386 109
Chris@823 110 if (reader->isOK() &&
Chris@823 111 (!reader->isQuicklySeekable() ||
Chris@920 112 normalised ||
Chris@823 113 (targetRate != 0 && fileRate != targetRate))) {
Chris@823 114
Chris@920 115 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
Chris@386 116
Chris@386 117 delete reader;
Chris@823 118 reader = new DecodingWavFileReader
Chris@386 119 (source,
Chris@386 120 threading ?
Chris@823 121 DecodingWavFileReader::ResampleThreaded :
Chris@823 122 DecodingWavFileReader::ResampleAtOnce,
Chris@823 123 DecodingWavFileReader::CacheInTemporaryFile,
Chris@823 124 targetRate ? targetRate : fileRate,
Chris@920 125 normalised,
Chris@392 126 reporter);
Chris@440 127 if (!reader->isOK()) {
Chris@440 128 delete reader;
Chris@440 129 reader = 0;
Chris@440 130 }
Chris@386 131 }
Chris@386 132 }
Chris@386 133
Chris@386 134 #ifdef HAVE_OGGZ
Chris@386 135 #ifdef HAVE_FISHSOUND
Chris@386 136 if (!reader) {
Chris@386 137 if (OggVorbisFileReader::supports(source)) {
Chris@386 138 reader = new OggVorbisFileReader
Chris@386 139 (source,
Chris@386 140 threading ?
Chris@386 141 OggVorbisFileReader::DecodeThreaded :
Chris@386 142 OggVorbisFileReader::DecodeAtOnce,
Chris@386 143 OggVorbisFileReader::CacheInTemporaryFile,
Chris@392 144 targetRate,
Chris@920 145 normalised,
Chris@392 146 reporter);
Chris@440 147 if (!reader->isOK()) {
Chris@440 148 delete reader;
Chris@440 149 reader = 0;
Chris@440 150 }
Chris@386 151 }
Chris@386 152 }
Chris@386 153 #endif
Chris@386 154 #endif
Chris@386 155
Chris@386 156 #ifdef HAVE_MAD
Chris@386 157 if (!reader) {
Chris@386 158 if (MP3FileReader::supports(source)) {
Chris@386 159 reader = new MP3FileReader
Chris@386 160 (source,
Chris@386 161 threading ?
Chris@386 162 MP3FileReader::DecodeThreaded :
Chris@386 163 MP3FileReader::DecodeAtOnce,
Chris@386 164 MP3FileReader::CacheInTemporaryFile,
Chris@392 165 targetRate,
Chris@920 166 normalised,
Chris@392 167 reporter);
Chris@440 168 if (!reader->isOK()) {
Chris@440 169 delete reader;
Chris@440 170 reader = 0;
Chris@440 171 }
Chris@386 172 }
Chris@386 173 }
Chris@386 174 #endif
Chris@386 175
Chris@386 176 #ifdef HAVE_QUICKTIME
Chris@386 177 if (!reader) {
Chris@386 178 if (QuickTimeFileReader::supports(source)) {
Chris@386 179 reader = new QuickTimeFileReader
Chris@386 180 (source,
Chris@386 181 threading ?
Chris@386 182 QuickTimeFileReader::DecodeThreaded :
Chris@386 183 QuickTimeFileReader::DecodeAtOnce,
Chris@386 184 QuickTimeFileReader::CacheInTemporaryFile,
Chris@392 185 targetRate,
Chris@920 186 normalised,
Chris@392 187 reporter);
Chris@440 188 if (!reader->isOK()) {
Chris@440 189 delete reader;
Chris@440 190 reader = 0;
Chris@440 191 }
Chris@440 192 }
Chris@440 193 }
Chris@440 194 #endif
Chris@440 195
luisf@665 196 #ifdef HAVE_COREAUDIO
luisf@665 197 if (!reader) {
luisf@665 198 if (CoreAudioFileReader::supports(source)) {
luisf@665 199 reader = new CoreAudioFileReader
luisf@665 200 (source,
luisf@665 201 threading ?
luisf@665 202 CoreAudioFileReader::DecodeThreaded :
luisf@665 203 CoreAudioFileReader::DecodeAtOnce,
luisf@665 204 CoreAudioFileReader::CacheInTemporaryFile,
luisf@665 205 targetRate,
Chris@920 206 normalised,
luisf@665 207 reporter);
luisf@665 208 if (!reader->isOK()) {
luisf@665 209 delete reader;
luisf@665 210 reader = 0;
luisf@665 211 }
luisf@665 212 }
luisf@665 213 }
luisf@665 214 #endif
luisf@665 215
luisf@665 216
Chris@440 217 // If none of the readers claimed to support this file extension,
Chris@440 218 // perhaps the extension is missing or misleading. Try again,
Chris@440 219 // ignoring it. We have to be confident that the reader won't
Chris@440 220 // open just any old text file or whatever and pretend it's
Chris@440 221 // succeeded
Chris@440 222
Chris@440 223 if (!reader) {
Chris@440 224
Chris@440 225 reader = new WavFileReader(source);
Chris@440 226
Chris@823 227 int fileRate = reader->getSampleRate();
Chris@440 228
Chris@823 229 if (reader->isOK() &&
Chris@823 230 (!reader->isQuicklySeekable() ||
Chris@920 231 normalised ||
Chris@823 232 (targetRate != 0 && fileRate != targetRate))) {
Chris@823 233
Chris@920 234 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
Chris@440 235
Chris@440 236 delete reader;
Chris@823 237 reader = new DecodingWavFileReader
Chris@440 238 (source,
Chris@440 239 threading ?
Chris@823 240 DecodingWavFileReader::ResampleThreaded :
Chris@823 241 DecodingWavFileReader::ResampleAtOnce,
Chris@823 242 DecodingWavFileReader::CacheInTemporaryFile,
Chris@823 243 targetRate ? targetRate : fileRate,
Chris@920 244 normalised,
Chris@440 245 reporter);
Chris@440 246 }
Chris@440 247
Chris@440 248 if (!reader->isOK()) {
Chris@440 249 delete reader;
Chris@440 250 reader = 0;
Chris@440 251 }
Chris@440 252 }
Chris@440 253
Chris@440 254 #ifdef HAVE_OGGZ
Chris@440 255 #ifdef HAVE_FISHSOUND
Chris@440 256 if (!reader) {
Chris@440 257 reader = new OggVorbisFileReader
Chris@440 258 (source,
Chris@440 259 threading ?
Chris@440 260 OggVorbisFileReader::DecodeThreaded :
Chris@440 261 OggVorbisFileReader::DecodeAtOnce,
Chris@440 262 OggVorbisFileReader::CacheInTemporaryFile,
Chris@440 263 targetRate,
Chris@440 264 reporter);
Chris@440 265
Chris@440 266 if (!reader->isOK()) {
Chris@440 267 delete reader;
Chris@440 268 reader = 0;
Chris@440 269 }
Chris@440 270 }
Chris@440 271 #endif
Chris@440 272 #endif
Chris@440 273
Chris@440 274 #ifdef HAVE_MAD
Chris@440 275 if (!reader) {
Chris@440 276 reader = new MP3FileReader
Chris@440 277 (source,
Chris@440 278 threading ?
Chris@440 279 MP3FileReader::DecodeThreaded :
Chris@440 280 MP3FileReader::DecodeAtOnce,
Chris@440 281 MP3FileReader::CacheInTemporaryFile,
Chris@440 282 targetRate,
Chris@440 283 reporter);
Chris@440 284
Chris@440 285 if (!reader->isOK()) {
Chris@440 286 delete reader;
Chris@440 287 reader = 0;
Chris@440 288 }
Chris@440 289 }
Chris@440 290 #endif
Chris@440 291
Chris@440 292 #ifdef HAVE_QUICKTIME
Chris@440 293 if (!reader) {
Chris@440 294 reader = new QuickTimeFileReader
Chris@440 295 (source,
Chris@440 296 threading ?
Chris@440 297 QuickTimeFileReader::DecodeThreaded :
Chris@440 298 QuickTimeFileReader::DecodeAtOnce,
Chris@440 299 QuickTimeFileReader::CacheInTemporaryFile,
Chris@440 300 targetRate,
Chris@440 301 reporter);
Chris@440 302
Chris@440 303 if (!reader->isOK()) {
Chris@440 304 delete reader;
Chris@440 305 reader = 0;
Chris@386 306 }
Chris@386 307 }
Chris@386 308 #endif
Chris@386 309
luisf@665 310 #ifdef HAVE_COREAUDIO
luisf@665 311 if (!reader) {
luisf@665 312 reader = new CoreAudioFileReader
luisf@665 313 (source,
luisf@665 314 threading ?
luisf@665 315 CoreAudioFileReader::DecodeThreaded :
luisf@665 316 CoreAudioFileReader::DecodeAtOnce,
luisf@665 317 CoreAudioFileReader::CacheInTemporaryFile,
luisf@665 318 targetRate,
luisf@665 319 reporter);
luisf@665 320
luisf@665 321 if (!reader->isOK()) {
luisf@665 322 delete reader;
luisf@665 323 reader = 0;
luisf@665 324 }
luisf@665 325 }
luisf@665 326 #endif
luisf@665 327
Chris@386 328 if (reader) {
Chris@386 329 if (reader->isOK()) {
Chris@756 330 SVDEBUG << "AudioFileReaderFactory: Reader is OK" << endl;
Chris@386 331 return reader;
Chris@386 332 }
Chris@843 333 cerr << "AudioFileReaderFactory: Preferred reader for "
Chris@844 334 << "url \"" << source.getLocation()
Chris@386 335 << "\" (content type \""
Chris@686 336 << source.getContentType() << "\") failed";
Chris@386 337
Chris@386 338 if (reader->getError() != "") {
Chris@843 339 cerr << ": \"" << reader->getError() << "\"";
Chris@386 340 }
Chris@843 341 cerr << endl;
Chris@386 342 delete reader;
Chris@386 343 reader = 0;
Chris@386 344 }
Chris@386 345
Chris@843 346 cerr << "AudioFileReaderFactory: No reader" << endl;
Chris@386 347 return reader;
Chris@386 348 }
Chris@386 349