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