diff 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
line wrap: on
line diff
--- a/data/fileio/AudioFileReaderFactory.cpp	Tue Nov 29 17:09:07 2016 +0000
+++ b/data/fileio/AudioFileReaderFactory.cpp	Thu Dec 01 17:45:40 2016 +0000
@@ -61,33 +61,13 @@
 }
 
 AudioFileReader *
-AudioFileReaderFactory::createReader(FileSource source, 
-                                     sv_samplerate_t targetRate,
-                                     bool normalised,
+AudioFileReaderFactory::createReader(FileSource source,
+                                     Parameters params,
                                      ProgressReporter *reporter)
 {
-    return create(source, targetRate, normalised, false, reporter);
-}
-
-AudioFileReader *
-AudioFileReaderFactory::createThreadingReader(FileSource source, 
-                                              sv_samplerate_t targetRate,
-                                              bool normalised,
-                                              ProgressReporter *reporter)
-{
-    return create(source, targetRate, normalised, true, reporter);
-}
-
-AudioFileReader *
-AudioFileReaderFactory::create(FileSource source, 
-                               sv_samplerate_t targetRate, 
-                               bool normalised,
-                               bool threading,
-                               ProgressReporter *reporter)
-{
     QString err;
 
-    SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << (targetRate == 0 ? " (use source rate)" : "") << endl;
+    SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << params.targetRate << (params.targetRate == 0 ? " (use source rate)" : "") << endl;
 
     if (!source.isOK()) {
         SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl;
@@ -101,6 +81,9 @@
 
     AudioFileReader *reader = 0;
 
+    sv_samplerate_t targetRate = params.targetRate;
+    bool normalised = (params.normalisation == Normalisation::Peak);
+  
     sv_frame_t estimatedSamples = 
         AudioFileSizeEstimator::estimate(source, targetRate);
     
@@ -118,153 +101,123 @@
     }
     
     CodedAudioFileReader::DecodeMode decodeMode =
-        (threading ?
+        (params.threadingMode == ThreadingMode::Threaded ?
          CodedAudioFileReader::DecodeThreaded :
          CodedAudioFileReader::DecodeAtOnce);
-    
-    // Try to construct a preferred reader based on the extension or
-    // MIME type.
 
-#define CHECK(reader) if (!reader->isOK()) { delete reader; reader = 0; }
+    // We go through the set of supported readers at most twice: once
+    // picking out only the readers that claim to support the given
+    // file's extension or MIME type, and (if that fails) again
+    // providing the file to every reader in turn regardless of
+    // extension or type. (If none of the readers claim to support a
+    // file, that may just mean its extension is missing or
+    // misleading. We have to be confident that the reader won't open
+    // just any old text file or whatever and pretend it's succeeded.)
 
-    if (WavFileReader::supports(source)) {
+    for (int any = 0; any <= 1; ++any) {
 
-        reader = new WavFileReader(source);
+        bool anyReader = (any > 0);
 
-        sv_samplerate_t fileRate = reader->getSampleRate();
+        if (anyReader || WavFileReader::supports(source)) {
 
-        if (reader->isOK() &&
-            (!reader->isQuicklySeekable() ||
-             normalised ||
-             (cacheMode == CodedAudioFileReader::CacheInMemory) ||
-             (targetRate != 0 && fileRate != targetRate))) {
+            reader = new WavFileReader(source);
 
-            SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
+            sv_samplerate_t fileRate = reader->getSampleRate();
+
+            if (reader->isOK() &&
+                (!reader->isQuicklySeekable() ||
+                 normalised ||
+                 (cacheMode == CodedAudioFileReader::CacheInMemory) ||
+                 (targetRate != 0 && fileRate != targetRate))) {
+
+                SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
             
-            delete reader;
-            reader = new DecodingWavFileReader
-                (source,
-                 decodeMode, cacheMode,
-                 targetRate ? targetRate : fileRate,
-                 normalised,
-                 reporter);
-            CHECK(reader);
+                delete reader;
+                reader = new DecodingWavFileReader
+                    (source,
+                     decodeMode, cacheMode,
+                     targetRate ? targetRate : fileRate,
+                     normalised,
+                     reporter);
+            }
+
+            if (reader->isOK()) {
+                return reader;
+            } else {
+                delete reader;
+            }
         }
-    }
     
 #ifdef HAVE_OGGZ
 #ifdef HAVE_FISHSOUND
-    if (!reader && OggVorbisFileReader::supports(source)) {
-        reader = new OggVorbisFileReader
-            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
-        CHECK(reader);
-    }
+        if (anyReader || OggVorbisFileReader::supports(source)) {
+
+            reader = new OggVorbisFileReader
+                (source, decodeMode, cacheMode, targetRate, normalised, reporter);
+
+            if (reader->isOK()) {
+                return reader;
+            } else {
+                delete reader;
+            }
+        }
 #endif
 #endif
 
 #ifdef HAVE_MAD
-    if (!reader && MP3FileReader::supports(source)) {
-        reader = new MP3FileReader
-            (source, decodeMode, cacheMode, MP3FileReader::Gapless,
-             targetRate, normalised, reporter);
-        CHECK(reader);
-    }
+        if (anyReader || MP3FileReader::supports(source)) {
+
+            MP3FileReader::GaplessMode gapless =
+                params.gaplessMode == GaplessMode::Gapless ?
+                MP3FileReader::GaplessMode::Gapless :
+                MP3FileReader::GaplessMode::Gappy;
+            
+            reader = new MP3FileReader
+                (source, decodeMode, cacheMode, gapless,
+                 targetRate, normalised, reporter);
+
+            if (reader->isOK()) {
+                return reader;
+            } else {
+                delete reader;
+            }
+        }
 #endif
 
 #ifdef HAVE_QUICKTIME
-    if (!reader && QuickTimeFileReader::supports(source)) {
-        reader = new QuickTimeFileReader
-            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
-        CHECK(reader);
-    }
+        if (anyReader || QuickTimeFileReader::supports(source)) {
+
+            reader = new QuickTimeFileReader
+                (source, decodeMode, cacheMode, targetRate, normalised, reporter);
+
+            if (reader->isOK()) {
+                return reader;
+            } else {
+                delete reader;
+            }
+        }
 #endif
 
 #ifdef HAVE_COREAUDIO
-    if (!reader && CoreAudioFileReader::supports(source)) {
-        reader = new CoreAudioFileReader
-            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
-        CHECK(reader);
-    }
+        if (anyReader || CoreAudioFileReader::supports(source)) {
+
+            reader = new CoreAudioFileReader
+                (source, decodeMode, cacheMode, targetRate, normalised, reporter);
+
+            if (reader->isOK()) {
+                return reader;
+            } else {
+                delete reader;
+            }
+        }
 #endif
 
-    if (reader) {
-        // The happy case: a reader recognised the file extension &
-        // succeeded in opening the file
-        return reader;
     }
     
-    // If none of the readers claimed to support this file extension,
-    // perhaps the extension is missing or misleading.  Try again,
-    // ignoring it.  We have to be confident that the reader won't
-    // open just any old text file or whatever and pretend it's
-    // succeeded
-
-    reader = new WavFileReader(source);
-
-    sv_samplerate_t fileRate = reader->getSampleRate();
-
-    if (reader->isOK() &&
-        (!reader->isQuicklySeekable() ||
-         normalised ||
-         (cacheMode == CodedAudioFileReader::CacheInMemory) ||
-         (targetRate != 0 && fileRate != targetRate))) {
-
-        SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
-
-        delete reader;
-        reader = new DecodingWavFileReader
-            (source,
-             decodeMode, cacheMode,
-             targetRate ? targetRate : fileRate,
-             normalised,
-             reporter);
-    }
-
-    CHECK(reader);
-    
-#ifdef HAVE_OGGZ
-#ifdef HAVE_FISHSOUND
-    if (!reader) {
-        reader = new OggVorbisFileReader
-            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
-        CHECK(reader);
-    }
-#endif
-#endif
-
-#ifdef HAVE_MAD
-    if (!reader) {
-        reader = new MP3FileReader
-            (source, decodeMode, cacheMode, MP3FileReader::Gapless,
-             targetRate, normalised, reporter);
-        CHECK(reader);
-    }
-#endif
-
-#ifdef HAVE_QUICKTIME
-    if (!reader) {
-        reader = new QuickTimeFileReader
-            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
-        CHECK(reader);
-    }
-#endif
-
-#ifdef HAVE_COREAUDIO
-    if (!reader) {
-        reader = new CoreAudioFileReader
-            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
-        CHECK(reader);
-    }
-#endif
-
-    if (!reader) {
-        SVDEBUG << "AudioFileReaderFactory::Failed to create a reader for "
-                << "url \"" << source.getLocation()
-                << "\" (content type \""
-                << source.getContentType() << "\")" << endl;
-        return nullptr;
-    }
-    
-    return reader;
+    SVDEBUG << "AudioFileReaderFactory::Failed to create a reader for "
+            << "url \"" << source.getLocation()
+            << "\" (content type \""
+            << source.getContentType() << "\")" << endl;
+    return nullptr;
 }