annotate data/fileio/AudioFileReaderFactory.cpp @ 684:bcca512445f3

Provide option for WavFileWriter to write directly to target file, rather than always using a temporary; make use of it in WritableWaveFileModel so we can read from target file without having to close it first
author Chris Cannam
date Wed, 11 May 2011 11:04:35 +0100
parents 1c8898816fd0
children b4a8d8221eaf
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@386 19 #include "ResamplingWavFileReader.h"
Chris@386 20 #include "OggVorbisFileReader.h"
Chris@386 21 #include "MP3FileReader.h"
Chris@386 22 #include "QuickTimeFileReader.h"
Chris@386 23
Chris@386 24 #include <QString>
Chris@386 25 #include <QFileInfo>
Chris@386 26 #include <iostream>
Chris@386 27
Chris@386 28 QString
Chris@386 29 AudioFileReaderFactory::getKnownExtensions()
Chris@386 30 {
Chris@386 31 std::set<QString> extensions;
Chris@386 32
Chris@386 33 WavFileReader::getSupportedExtensions(extensions);
Chris@386 34 #ifdef HAVE_MAD
Chris@386 35 MP3FileReader::getSupportedExtensions(extensions);
Chris@386 36 #endif
Chris@386 37 #ifdef HAVE_OGGZ
Chris@386 38 #ifdef HAVE_FISHSOUND
Chris@386 39 OggVorbisFileReader::getSupportedExtensions(extensions);
Chris@386 40 #endif
Chris@386 41 #endif
Chris@386 42 #ifdef HAVE_QUICKTIME
Chris@386 43 QuickTimeFileReader::getSupportedExtensions(extensions);
Chris@386 44 #endif
Chris@386 45
Chris@386 46 QString rv;
Chris@386 47 for (std::set<QString>::const_iterator i = extensions.begin();
Chris@386 48 i != extensions.end(); ++i) {
Chris@386 49 if (i != extensions.begin()) rv += " ";
Chris@386 50 rv += "*." + *i;
Chris@386 51 }
Chris@386 52
Chris@386 53 return rv;
Chris@386 54 }
Chris@386 55
Chris@386 56 AudioFileReader *
Chris@392 57 AudioFileReaderFactory::createReader(FileSource source, size_t targetRate,
Chris@392 58 ProgressReporter *reporter)
Chris@386 59 {
Chris@392 60 return create(source, targetRate, false, reporter);
Chris@386 61 }
Chris@386 62
Chris@386 63 AudioFileReader *
Chris@392 64 AudioFileReaderFactory::createThreadingReader(FileSource source, size_t targetRate,
Chris@392 65 ProgressReporter *reporter)
Chris@386 66 {
Chris@392 67 return create(source, targetRate, true, reporter);
Chris@386 68 }
Chris@386 69
Chris@386 70 AudioFileReader *
Chris@392 71 AudioFileReaderFactory::create(FileSource source, size_t targetRate, bool threading,
Chris@392 72 ProgressReporter *reporter)
Chris@386 73 {
Chris@386 74 QString err;
Chris@386 75
Chris@386 76 // std::cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation().toStdString() << "\"): Requested rate: " << targetRate << std::endl;
Chris@386 77
Chris@667 78 if (!source.isOK()) {
Chris@667 79 std::cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation().toStdString() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString().toStdString() << std::endl;
Chris@667 80 return 0;
Chris@667 81 }
Chris@667 82
Chris@667 83 if (!source.isAvailable()) {
Chris@667 84 std::cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation().toStdString() << "\": Source not found" << std::endl;
Chris@386 85 return 0;
Chris@386 86 }
Chris@386 87
Chris@386 88 AudioFileReader *reader = 0;
Chris@386 89
Chris@386 90 // Try to construct a preferred reader based on the extension or
Chris@386 91 // MIME type.
Chris@386 92
Chris@386 93 if (WavFileReader::supports(source)) {
Chris@386 94
Chris@386 95 reader = new WavFileReader(source);
Chris@386 96
Chris@386 97 if (targetRate != 0 &&
Chris@386 98 reader->isOK() &&
Chris@386 99 reader->getSampleRate() != targetRate) {
Chris@386 100
Chris@386 101 std::cerr << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", creating resampling reader" << std::endl;
Chris@386 102
Chris@386 103 delete reader;
Chris@386 104 reader = new ResamplingWavFileReader
Chris@386 105 (source,
Chris@386 106 threading ?
Chris@386 107 ResamplingWavFileReader::ResampleThreaded :
Chris@386 108 ResamplingWavFileReader::ResampleAtOnce,
Chris@386 109 ResamplingWavFileReader::CacheInTemporaryFile,
Chris@392 110 targetRate,
Chris@392 111 reporter);
Chris@440 112 if (!reader->isOK()) {
Chris@440 113 delete reader;
Chris@440 114 reader = 0;
Chris@440 115 }
Chris@386 116 }
Chris@386 117 }
Chris@386 118
Chris@386 119 #ifdef HAVE_OGGZ
Chris@386 120 #ifdef HAVE_FISHSOUND
Chris@386 121 if (!reader) {
Chris@386 122 if (OggVorbisFileReader::supports(source)) {
Chris@386 123 reader = new OggVorbisFileReader
Chris@386 124 (source,
Chris@386 125 threading ?
Chris@386 126 OggVorbisFileReader::DecodeThreaded :
Chris@386 127 OggVorbisFileReader::DecodeAtOnce,
Chris@386 128 OggVorbisFileReader::CacheInTemporaryFile,
Chris@392 129 targetRate,
Chris@392 130 reporter);
Chris@440 131 if (!reader->isOK()) {
Chris@440 132 delete reader;
Chris@440 133 reader = 0;
Chris@440 134 }
Chris@386 135 }
Chris@386 136 }
Chris@386 137 #endif
Chris@386 138 #endif
Chris@386 139
Chris@386 140 #ifdef HAVE_MAD
Chris@386 141 if (!reader) {
Chris@386 142 if (MP3FileReader::supports(source)) {
Chris@386 143 reader = new MP3FileReader
Chris@386 144 (source,
Chris@386 145 threading ?
Chris@386 146 MP3FileReader::DecodeThreaded :
Chris@386 147 MP3FileReader::DecodeAtOnce,
Chris@386 148 MP3FileReader::CacheInTemporaryFile,
Chris@392 149 targetRate,
Chris@392 150 reporter);
Chris@440 151 if (!reader->isOK()) {
Chris@440 152 delete reader;
Chris@440 153 reader = 0;
Chris@440 154 }
Chris@386 155 }
Chris@386 156 }
Chris@386 157 #endif
Chris@386 158
Chris@386 159 #ifdef HAVE_QUICKTIME
Chris@386 160 if (!reader) {
Chris@386 161 if (QuickTimeFileReader::supports(source)) {
Chris@386 162 reader = new QuickTimeFileReader
Chris@386 163 (source,
Chris@386 164 threading ?
Chris@386 165 QuickTimeFileReader::DecodeThreaded :
Chris@386 166 QuickTimeFileReader::DecodeAtOnce,
Chris@386 167 QuickTimeFileReader::CacheInTemporaryFile,
Chris@392 168 targetRate,
Chris@392 169 reporter);
Chris@440 170 if (!reader->isOK()) {
Chris@440 171 delete reader;
Chris@440 172 reader = 0;
Chris@440 173 }
Chris@440 174 }
Chris@440 175 }
Chris@440 176 #endif
Chris@440 177
Chris@440 178 // If none of the readers claimed to support this file extension,
Chris@440 179 // perhaps the extension is missing or misleading. Try again,
Chris@440 180 // ignoring it. We have to be confident that the reader won't
Chris@440 181 // open just any old text file or whatever and pretend it's
Chris@440 182 // succeeded
Chris@440 183
Chris@440 184 if (!reader) {
Chris@440 185
Chris@440 186 reader = new WavFileReader(source);
Chris@440 187
Chris@440 188 if (targetRate != 0 &&
Chris@440 189 reader->isOK() &&
Chris@440 190 reader->getSampleRate() != targetRate) {
Chris@440 191
Chris@440 192 std::cerr << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", creating resampling reader" << std::endl;
Chris@440 193
Chris@440 194 delete reader;
Chris@440 195 reader = new ResamplingWavFileReader
Chris@440 196 (source,
Chris@440 197 threading ?
Chris@440 198 ResamplingWavFileReader::ResampleThreaded :
Chris@440 199 ResamplingWavFileReader::ResampleAtOnce,
Chris@440 200 ResamplingWavFileReader::CacheInTemporaryFile,
Chris@440 201 targetRate,
Chris@440 202 reporter);
Chris@440 203 }
Chris@440 204
Chris@440 205 if (!reader->isOK()) {
Chris@440 206 delete reader;
Chris@440 207 reader = 0;
Chris@440 208 }
Chris@440 209 }
Chris@440 210
Chris@440 211 #ifdef HAVE_OGGZ
Chris@440 212 #ifdef HAVE_FISHSOUND
Chris@440 213 if (!reader) {
Chris@440 214 reader = new OggVorbisFileReader
Chris@440 215 (source,
Chris@440 216 threading ?
Chris@440 217 OggVorbisFileReader::DecodeThreaded :
Chris@440 218 OggVorbisFileReader::DecodeAtOnce,
Chris@440 219 OggVorbisFileReader::CacheInTemporaryFile,
Chris@440 220 targetRate,
Chris@440 221 reporter);
Chris@440 222
Chris@440 223 if (!reader->isOK()) {
Chris@440 224 delete reader;
Chris@440 225 reader = 0;
Chris@440 226 }
Chris@440 227 }
Chris@440 228 #endif
Chris@440 229 #endif
Chris@440 230
Chris@440 231 #ifdef HAVE_MAD
Chris@440 232 if (!reader) {
Chris@440 233 reader = new MP3FileReader
Chris@440 234 (source,
Chris@440 235 threading ?
Chris@440 236 MP3FileReader::DecodeThreaded :
Chris@440 237 MP3FileReader::DecodeAtOnce,
Chris@440 238 MP3FileReader::CacheInTemporaryFile,
Chris@440 239 targetRate,
Chris@440 240 reporter);
Chris@440 241
Chris@440 242 if (!reader->isOK()) {
Chris@440 243 delete reader;
Chris@440 244 reader = 0;
Chris@440 245 }
Chris@440 246 }
Chris@440 247 #endif
Chris@440 248
Chris@440 249 #ifdef HAVE_QUICKTIME
Chris@440 250 if (!reader) {
Chris@440 251 reader = new QuickTimeFileReader
Chris@440 252 (source,
Chris@440 253 threading ?
Chris@440 254 QuickTimeFileReader::DecodeThreaded :
Chris@440 255 QuickTimeFileReader::DecodeAtOnce,
Chris@440 256 QuickTimeFileReader::CacheInTemporaryFile,
Chris@440 257 targetRate,
Chris@440 258 reporter);
Chris@440 259
Chris@440 260 if (!reader->isOK()) {
Chris@440 261 delete reader;
Chris@440 262 reader = 0;
Chris@386 263 }
Chris@386 264 }
Chris@386 265 #endif
Chris@386 266
Chris@386 267 if (reader) {
Chris@386 268 if (reader->isOK()) {
Chris@386 269 // std::cerr << "AudioFileReaderFactory: Reader is OK" << std::endl;
Chris@386 270 return reader;
Chris@386 271 }
Chris@386 272 std::cerr << "AudioFileReaderFactory: Preferred reader for "
Chris@386 273 << "url \"" << source.getLocation().toStdString()
Chris@386 274 << "\" (content type \""
Chris@386 275 << source.getContentType().toStdString() << "\") failed";
Chris@386 276
Chris@386 277 if (reader->getError() != "") {
Chris@386 278 std::cerr << ": \"" << reader->getError().toStdString() << "\"";
Chris@386 279 }
Chris@386 280 std::cerr << std::endl;
Chris@386 281 delete reader;
Chris@386 282 reader = 0;
Chris@386 283 }
Chris@386 284
Chris@386 285 std::cerr << "AudioFileReaderFactory: No reader" << std::endl;
Chris@386 286 return reader;
Chris@386 287 }
Chris@386 288