changeset 1592:f8e3dcbafb4d bqaudiostream

Implement title/maker in wav readers; extra handling of supported-ness for file types
author Chris Cannam
date Mon, 21 Jan 2019 13:16:17 +0000
parents 6e68bd92ee21
children d3f068153546
files data/fileio/AudioFileReader.h data/fileio/AudioFileReaderFactory.cpp data/fileio/AudioFileReaderFactory.h data/fileio/AudioFileSizeEstimator.cpp data/fileio/DecodingWavFileReader.cpp data/fileio/DecodingWavFileReader.h data/fileio/WavFileReader.cpp data/fileio/WavFileReader.h data/fileio/test/EncodingTest.h
diffstat 9 files changed, 110 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/data/fileio/AudioFileReader.h	Mon Jan 21 11:45:51 2019 +0000
+++ b/data/fileio/AudioFileReader.h	Mon Jan 21 13:16:17 2019 +0000
@@ -79,14 +79,14 @@
      * may be implemented by subclasses that support file tagging.
      * This is not the same thing as the file name.
      */
-    virtual QString getTitle() const { return ""; }
+    virtual QString getTitle() const = 0;
 
     /**
      * Return the "maker" of the work in the audio file, if known.
      * This could represent almost anything (band, composer,
      * conductor, artist etc).
      */
-    virtual QString getMaker() const { return ""; }
+    virtual QString getMaker() const = 0;
 
     /**
      * Return the local file path of the audio data. This is the
--- a/data/fileio/AudioFileReaderFactory.cpp	Mon Jan 21 11:45:51 2019 +0000
+++ b/data/fileio/AudioFileReaderFactory.cpp	Mon Jan 21 13:16:17 2019 +0000
@@ -50,6 +50,23 @@
     return rv;
 }
 
+bool
+AudioFileReaderFactory::isSupported(FileSource source)
+{
+#ifdef HAVE_MAD
+    if (MP3FileReader::supports(source)) {
+        return true;
+    }
+#endif
+    if (WavFileReader::supports(source)) {
+        return true;
+    }
+    if (BQAFileReader::supports(source)) {
+        return true;
+    }
+    return false;
+}
+
 AudioFileReader *
 AudioFileReaderFactory::createReader(FileSource source,
                                      Parameters params,
@@ -122,40 +139,34 @@
         }
 
 #ifdef HAVE_MAD
-        if (anyReader || MP3FileReader::supports(source)) {
+        // Having said we'll try any reader on the second pass, we
+        // actually don't want to try the mp3 reader for anything not
+        // identified as an mp3 - it can't identify files by header,
+        // it'll try to read any data and then fail with
+        // synchronisation errors - causing misleading and potentially
+        // alarming warning messages at the least
+        if (!anyReader) {
+            if (MP3FileReader::supports(source)) {
 
-            MP3FileReader::GaplessMode gapless =
-                params.gaplessMode == GaplessMode::Gapless ?
-                MP3FileReader::GaplessMode::Gapless :
-                MP3FileReader::GaplessMode::Gappy;
+                MP3FileReader::GaplessMode gapless =
+                    params.gaplessMode == GaplessMode::Gapless ?
+                    MP3FileReader::GaplessMode::Gapless :
+                    MP3FileReader::GaplessMode::Gappy;
             
-            reader = new MP3FileReader
-                (source, decodeMode, cacheMode, gapless,
-                 targetRate, normalised, reporter);
+                reader = new MP3FileReader
+                    (source, decodeMode, cacheMode, gapless,
+                     targetRate, normalised, reporter);
 
-            if (reader->isOK()) {
-                SVDEBUG << "AudioFileReaderFactory: MP3 file reader is OK, returning it" << endl;
-                return reader;
-            } else {
-                delete reader;
+                if (reader->isOK()) {
+                    SVDEBUG << "AudioFileReaderFactory: MP3 file reader is OK, returning it" << endl;
+                    return reader;
+                } else {
+                    delete reader;
+                }
             }
         }
 #endif
 
-        if (anyReader || BQAFileReader::supports(source)) {
-
-            reader = new BQAFileReader
-                (source, decodeMode, cacheMode, 
-                 targetRate, normalised, reporter);
-
-            if (reader->isOK()) {
-                SVDEBUG << "AudioFileReaderFactory: BQA reader is OK, returning it" << endl;
-                return reader;
-            } else {
-                delete reader;
-            }
-        }
-
         if (anyReader || WavFileReader::supports(source)) {
 
             reader = new WavFileReader(source);
@@ -186,6 +197,20 @@
                 delete reader;
             }
         }
+    
+        if (anyReader || BQAFileReader::supports(source)) {
+
+            reader = new BQAFileReader
+                (source, decodeMode, cacheMode, 
+                 targetRate, normalised, reporter);
+
+            if (reader->isOK()) {
+                SVDEBUG << "AudioFileReaderFactory: BQA reader is OK, returning it" << endl;
+                return reader;
+            } else {
+                delete reader;
+            }
+        }
     }
     
     SVCERR << "AudioFileReaderFactory::Failed to create a reader for "
--- a/data/fileio/AudioFileReaderFactory.h	Mon Jan 21 11:45:51 2019 +0000
+++ b/data/fileio/AudioFileReaderFactory.h	Mon Jan 21 13:16:17 2019 +0000
@@ -141,6 +141,15 @@
     static AudioFileReader *createReader(FileSource source,
                                          Parameters parameters,
                                          ProgressReporter *reporter = 0);
+
+    /**
+     * Return true if the given source has a file extension that
+     * indicates a supported file type. This does not necessarily mean
+     * that it can be opened; conversely it may theoretically be
+     * possible to open some files without supported extensions,
+     * depending on the readers available.
+     */
+    static bool isSupported(FileSource source);
 };
 
 #endif
--- a/data/fileio/AudioFileSizeEstimator.cpp	Mon Jan 21 11:45:51 2019 +0000
+++ b/data/fileio/AudioFileSizeEstimator.cpp	Mon Jan 21 13:16:17 2019 +0000
@@ -83,7 +83,7 @@
 
         if (extension == "ogg" || extension == "oga" ||
             extension == "m4a" || extension == "mp3" ||
-            extension == "wma") {
+            extension == "wma" || extension == "opus") {
 
             // Usually a lossy file. Compression ratios can vary
             // dramatically, but don't usually exceed about 20x compared
--- a/data/fileio/DecodingWavFileReader.cpp	Mon Jan 21 11:45:51 2019 +0000
+++ b/data/fileio/DecodingWavFileReader.cpp	Mon Jan 21 13:16:17 2019 +0000
@@ -58,6 +58,9 @@
     m_channelCount = m_original->getChannelCount();
     m_fileRate = m_original->getSampleRate();
 
+    m_title = m_original->getTitle();
+    m_maker = m_original->getMaker();
+
     initialiseDecodeCache();
 
     if (decodeMode == DecodeAtOnce) {
--- a/data/fileio/DecodingWavFileReader.h	Mon Jan 21 11:45:51 2019 +0000
+++ b/data/fileio/DecodingWavFileReader.h	Mon Jan 21 13:16:17 2019 +0000
@@ -37,6 +37,9 @@
                           ProgressReporter *reporter = 0);
     virtual ~DecodingWavFileReader();
 
+    QString getTitle() const override { return m_title; }
+    QString getMaker() const override { return m_maker; }
+    
     virtual QString getError() const { return m_error; }
     virtual QString getLocation() const { return m_source.getLocation(); }
     static void getSupportedExtensions(std::set<QString> &extensions);
@@ -55,6 +58,8 @@
 
 protected:
     FileSource m_source;
+    QString m_title;
+    QString m_maker;
     QString m_path;
     QString m_error;
     bool m_cancelled;
--- a/data/fileio/WavFileReader.cpp	Mon Jan 21 11:45:51 2019 +0000
+++ b/data/fileio/WavFileReader.cpp	Mon Jan 21 13:16:17 2019 +0000
@@ -95,6 +95,15 @@
         if (m_normalisation != Normalisation::None && !m_updating) {
             m_max = getMax();
         }
+        
+        const char *str = sf_get_string(m_file, SF_STR_TITLE);
+        if (str) {
+            m_title = str;
+        }
+        str = sf_get_string(m_file, SF_STR_ARTIST);
+        if (str) {
+            m_maker = str;
+        }
     }
 
     SVDEBUG << "WavFileReader: Filename " << m_path << ", frame count " << m_frameCount << ", channel count " << m_channelCount << ", sample rate " << m_sampleRate << ", format " << m_fileInfo.format << ", seekable " << m_fileInfo.seekable << " adjusted to " << m_seekable << ", normalisation " << int(m_normalisation) << endl;
--- a/data/fileio/WavFileReader.h	Mon Jan 21 11:45:51 2019 +0000
+++ b/data/fileio/WavFileReader.h	Mon Jan 21 13:16:17 2019 +0000
@@ -51,6 +51,9 @@
     virtual QString getLocation() const { return m_source.getLocation(); }
     virtual QString getError() const { return m_error; }
 
+    QString getTitle() const override { return m_title; }
+    QString getMaker() const override { return m_maker; }
+    
     virtual QString getLocalFilename() const { return m_path; }
     
     virtual bool isQuicklySeekable() const { return m_seekable; }
@@ -81,6 +84,8 @@
     FileSource m_source;
     QString m_path;
     QString m_error;
+    QString m_title;
+    QString m_maker;
 
     bool m_seekable;
 
--- a/data/fileio/test/EncodingTest.h	Mon Jan 21 11:45:51 2019 +0000
+++ b/data/fileio/test/EncodingTest.h	Mon Jan 21 13:16:17 2019 +0000
@@ -101,6 +101,15 @@
         
         QFETCH(QString, audiofile);
 
+        if (!AudioFileReaderFactory::isSupported(encodingDir + "/" +
+                                                 audiofile)) {
+#if ( QT_VERSION >= 0x050000 )
+            QSKIP("Known unsupported file, skipping");
+#else
+            QSKIP("Known unsupported file, skipping", SkipSingle);
+#endif
+        }            
+        
         AudioFileReaderFactory::Parameters params;
         AudioFileReader *reader =
             AudioFileReaderFactory::createReader
@@ -128,7 +137,13 @@
             AudioFileReaderFactory::createReader
             (encodingDir + "/" + audiofile, params);
 
-        QVERIFY(reader != nullptr);
+        if (!reader) {
+#if ( QT_VERSION >= 0x050000 )
+            QSKIP("Unsupported file, skipping");
+#else
+            QSKIP("Unsupported file, skipping", SkipSingle);
+#endif
+        }
 
         QStringList fileAndExt = audiofile.split(".");
         QString file = fileAndExt[0];
@@ -225,7 +240,14 @@
         AudioFileReader *reader =
             AudioFileReaderFactory::createReader
             (encodingDir + "/" + audiofile, params);
-        QVERIFY(reader != nullptr);
+        
+        if (!reader) {
+#if ( QT_VERSION >= 0x050000 )
+            QSKIP("Unsupported file, skipping");
+#else
+            QSKIP("Unsupported file, skipping", SkipSingle);
+#endif
+        }
 
         QString title = reader->getTitle();
         QVERIFY(title != QString());