diff data/fileio/AudioFileReaderFactory.cpp @ 1126:39019ce29178 tony-2.0-integration

Merge through to branch for Tony 2.0
author Chris Cannam
date Thu, 20 Aug 2015 14:54:21 +0100
parents cd156ede1395
children 6877f4200912
line wrap: on
line diff
--- a/data/fileio/AudioFileReaderFactory.cpp	Fri Aug 14 18:16:14 2015 +0100
+++ b/data/fileio/AudioFileReaderFactory.cpp	Thu Aug 20 14:54:21 2015 +0100
@@ -21,6 +21,9 @@
 #include "MP3FileReader.h"
 #include "QuickTimeFileReader.h"
 #include "CoreAudioFileReader.h"
+#include "AudioFileSizeEstimator.h"
+
+#include "base/StorageAdviser.h"
 
 #include <QString>
 #include <QFileInfo>
@@ -98,9 +101,32 @@
 
     AudioFileReader *reader = 0;
 
+    sv_frame_t estimatedSamples = 
+        AudioFileSizeEstimator::estimate(source, targetRate);
+    
+    CodedAudioFileReader::CacheMode cacheMode =
+        CodedAudioFileReader::CacheInTemporaryFile;
+
+    if (estimatedSamples > 0) {
+        size_t kb = (estimatedSamples * sizeof(float)) / 1024;
+        StorageAdviser::Recommendation rec =
+            StorageAdviser::recommend(StorageAdviser::SpeedCritical, kb, kb);
+        if (rec == StorageAdviser::UseMemory ||
+            rec == StorageAdviser::PreferMemory) {
+            cacheMode = CodedAudioFileReader::CacheInMemory;
+        }
+    }
+    
+    CodedAudioFileReader::DecodeMode decodeMode =
+        (threading ?
+         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; }
+
     if (WavFileReader::supports(source)) {
 
         reader = new WavFileReader(source);
@@ -110,163 +136,97 @@
         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() << ", creating decoding reader" << endl;
+            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,
-                 threading ?
-                 DecodingWavFileReader::ResampleThreaded :
-                 DecodingWavFileReader::ResampleAtOnce,
-                 DecodingWavFileReader::CacheInTemporaryFile,
+                 decodeMode, cacheMode,
                  targetRate ? targetRate : fileRate,
                  normalised,
                  reporter);
-            if (!reader->isOK()) {
-                delete reader;
-                reader = 0;
-            }
+            CHECK(reader);
         }
     }
     
 #ifdef HAVE_OGGZ
 #ifdef HAVE_FISHSOUND
-    if (!reader) {
-        if (OggVorbisFileReader::supports(source)) {
-            reader = new OggVorbisFileReader
-                (source,
-                 threading ?
-                 OggVorbisFileReader::DecodeThreaded :
-                 OggVorbisFileReader::DecodeAtOnce,
-                 OggVorbisFileReader::CacheInTemporaryFile,
-                 targetRate,
-                 normalised,
-                 reporter);
-            if (!reader->isOK()) {
-                delete reader;
-                reader = 0;
-            }
-        }
+    if (!reader && OggVorbisFileReader::supports(source)) {
+        reader = new OggVorbisFileReader
+            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
+        CHECK(reader);
     }
 #endif
 #endif
 
 #ifdef HAVE_MAD
-    if (!reader) {
-        if (MP3FileReader::supports(source)) {
-            reader = new MP3FileReader
-                (source,
-                 threading ?
-                 MP3FileReader::DecodeThreaded :
-                 MP3FileReader::DecodeAtOnce,
-                 MP3FileReader::CacheInTemporaryFile,
-                 targetRate,
-                 normalised,
-                 reporter);
-            if (!reader->isOK()) {
-                delete reader;
-                reader = 0;
-            }
-        }
+    if (!reader && MP3FileReader::supports(source)) {
+        reader = new MP3FileReader
+            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
+        CHECK(reader);
     }
 #endif
 
 #ifdef HAVE_QUICKTIME
-    if (!reader) {
-        if (QuickTimeFileReader::supports(source)) {
-            reader = new QuickTimeFileReader
-                (source,
-                 threading ?
-                 QuickTimeFileReader::DecodeThreaded : 
-                 QuickTimeFileReader::DecodeAtOnce,
-                 QuickTimeFileReader::CacheInTemporaryFile,
-                 targetRate,
-                 normalised,
-                 reporter);
-            if (!reader->isOK()) {
-                delete reader;
-                reader = 0;
-            }
-        }
+    if (!reader && QuickTimeFileReader::supports(source)) {
+        reader = new QuickTimeFileReader
+            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
+        CHECK(reader);
     }
 #endif
 
 #ifdef HAVE_COREAUDIO
-    if (!reader) {
-        if (CoreAudioFileReader::supports(source)) {
-            reader = new CoreAudioFileReader
-                (source,
-                 threading ?
-                 CoreAudioFileReader::DecodeThreaded :
-                 CoreAudioFileReader::DecodeAtOnce,
-                 CoreAudioFileReader::CacheInTemporaryFile,
-                 targetRate,
-                 normalised,
-                 reporter);
-            if (!reader->isOK()) {
-                delete reader;
-                reader = 0;
-            }
-        }
+    if (!reader && CoreAudioFileReader::supports(source)) {
+        reader = new CoreAudioFileReader
+            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
+        CHECK(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
 
-    if (!reader) {
+    reader = new WavFileReader(source);
 
-        reader = new WavFileReader(source);
+    sv_samplerate_t fileRate = reader->getSampleRate();
 
-        sv_samplerate_t fileRate = reader->getSampleRate();
+    if (reader->isOK() &&
+        (!reader->isQuicklySeekable() ||
+         normalised ||
+         (cacheMode == CodedAudioFileReader::CacheInMemory) ||
+         (targetRate != 0 && fileRate != targetRate))) {
 
-        if (reader->isOK() &&
-            (!reader->isQuicklySeekable() ||
-             normalised ||
-             (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;
 
-            SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
+        delete reader;
+        reader = new DecodingWavFileReader
+            (source,
+             decodeMode, cacheMode,
+             targetRate ? targetRate : fileRate,
+             normalised,
+             reporter);
+    }
 
-            delete reader;
-            reader = new DecodingWavFileReader
-                (source,
-                 threading ?
-                 DecodingWavFileReader::ResampleThreaded :
-                 DecodingWavFileReader::ResampleAtOnce,
-                 DecodingWavFileReader::CacheInTemporaryFile,
-                 targetRate ? targetRate : fileRate,
-                 normalised,
-                 reporter);
-        }
-
-        if (!reader->isOK()) {
-            delete reader;
-            reader = 0;
-        }
-    }
+    CHECK(reader);
     
 #ifdef HAVE_OGGZ
 #ifdef HAVE_FISHSOUND
     if (!reader) {
         reader = new OggVorbisFileReader
-            (source,
-             threading ?
-             OggVorbisFileReader::DecodeThreaded :
-             OggVorbisFileReader::DecodeAtOnce,
-             OggVorbisFileReader::CacheInTemporaryFile,
-             targetRate,
-             reporter);
-
-        if (!reader->isOK()) {
-            delete reader;
-            reader = 0;
-        }
+            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
+        CHECK(reader);
     }
 #endif
 #endif
@@ -274,76 +234,35 @@
 #ifdef HAVE_MAD
     if (!reader) {
         reader = new MP3FileReader
-            (source,
-             threading ?
-             MP3FileReader::DecodeThreaded :
-             MP3FileReader::DecodeAtOnce,
-             MP3FileReader::CacheInTemporaryFile,
-             targetRate,
-             reporter);
-
-        if (!reader->isOK()) {
-            delete reader;
-            reader = 0;
-        }
+            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
+        CHECK(reader);
     }
 #endif
 
 #ifdef HAVE_QUICKTIME
     if (!reader) {
         reader = new QuickTimeFileReader
-            (source,
-             threading ?
-             QuickTimeFileReader::DecodeThreaded : 
-             QuickTimeFileReader::DecodeAtOnce,
-             QuickTimeFileReader::CacheInTemporaryFile,
-             targetRate,
-             reporter);
-
-        if (!reader->isOK()) {
-            delete reader;
-            reader = 0;
-        }
+            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
+        CHECK(reader);
     }
 #endif
 
 #ifdef HAVE_COREAUDIO
     if (!reader) {
         reader = new CoreAudioFileReader
-            (source,
-             threading ?
-             CoreAudioFileReader::DecodeThreaded :
-             CoreAudioFileReader::DecodeAtOnce,
-             CoreAudioFileReader::CacheInTemporaryFile,
-             targetRate,
-             reporter);
-
-        if (!reader->isOK()) {
-            delete reader;
-            reader = 0;
-        }
+            (source, decodeMode, cacheMode, targetRate, normalised, reporter);
+        CHECK(reader);
     }
 #endif
 
-    if (reader) {
-        if (reader->isOK()) {
-            SVDEBUG << "AudioFileReaderFactory: Reader is OK" << endl;
-            return reader;
-        }
-        cerr << "AudioFileReaderFactory: Preferred reader for "
-                  << "url \"" << source.getLocation()
-                  << "\" (content type \""
-                  << source.getContentType() << "\") failed";
-
-        if (reader->getError() != "") {
-            cerr << ": \"" << reader->getError() << "\"";
-        }
-        cerr << endl;
-        delete reader;
-        reader = 0;
+    if (!reader) {
+        cerr << "AudioFileReaderFactory::Failed to create a reader for "
+             << "url \"" << source.getLocation()
+             << "\" (content type \""
+             << source.getContentType() << "\")" << endl;
+        return nullptr;
     }
-
-    cerr << "AudioFileReaderFactory: No reader" << endl;
+    
     return reader;
 }