[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    kdesupport/taglib
From:       Lukáš Lalinský <lalinsky () gmail ! com>
Date:       2010-11-27 20:58:57
Message-ID: 20101127205857.DEB93AC8A3 () svn ! kde ! org
[Download RAW message or body]

SVN commit 1201476 by lalinsky:

Fix reading of WavPack streams without a length information in the header

When the WavPack's total_samples header fiels contains -1, try to find
the final block and get the number of samples from there as
block_index + block_samples.

BUG:258016


 M  +2 -0      NEWS  
 M  +1 -2      taglib/wavpack/wavpackfile.cpp  
 M  +50 -1     taglib/wavpack/wavpackproperties.cpp  
 M  +10 -0     taglib/wavpack/wavpackproperties.h  
 M  +2 -0      tests/CMakeLists.txt  
 M  +4 -2      tests/Makefile.am  
 AM            tests/data/no_length.wv  
 A             tests/test_wavpack.cpp   [License: UNKNOWN]


--- trunk/kdesupport/taglib/NEWS #1201475:1201476
@@ -8,6 +8,8 @@
  * Exposed FLAC MD5 signature of the uncompressed audio stream via
    FLAC::Properties::signature(). (BUG:160172)
  * Added function ByteVector::toHex() for hex-encoding of byte vectors.
+ * WavPack reader now tries to get the audio length by finding the final
+   block, if the header doesn't have the information. (BUG:258016)
 
 TagLib 1.6.3 (Apr 17, 2010)
 ===========================
--- trunk/kdesupport/taglib/taglib/wavpack/wavpackfile.cpp #1201475:1201476
@@ -230,8 +230,7 @@
 
   if(readProperties) {
     seek(0);
-    d->properties = new Properties(readBlock(WavPack::HeaderSize),
-                                   length() - d->APESize);
+    d->properties = new Properties(this, length() - d->APESize);
   }
 }
 
--- trunk/kdesupport/taglib/taglib/wavpack/wavpackproperties.cpp #1201475:1201476
@@ -48,7 +48,8 @@
     sampleRate(0),
     channels(0),
     version(0),
-    bitsPerSample(0) {}
+    bitsPerSample(0),
+    file(0) {}
 
   ByteVector data;
   long streamLength;
@@ -59,6 +60,7 @@
   int channels;
   int version;
   int bitsPerSample;
+  File *file;
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -71,6 +73,14 @@
   read();
 }
 
+WavPack::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style)
+{
+  ByteVector data = file->readBlock(32);
+  d = new PropertiesPrivate(data, streamLength, style);
+  d->file = file;
+  read();
+}
+
 WavPack::Properties::~Properties()
 {
   delete d;
@@ -122,12 +132,19 @@
 #define SRATE_LSB       23
 #define SRATE_MASK      (0xfL << SRATE_LSB)
 
+#define MIN_STREAM_VERS     0x402
+#define MAX_STREAM_VERS     0x410
+
+#define FINAL_BLOCK     0x1000
+
 void WavPack::Properties::read()
 {
   if(!d->data.startsWith("wvpk"))
     return;
 
   d->version = d->data.mid(8, 2).toShort(false);
+  if(d->version < MIN_STREAM_VERS || d->version > MAX_STREAM_VERS)
+    return;
 
   unsigned int flags = d->data.mid(24, 4).toUInt(false);
   d->bitsPerSample = ((flags & BYTES_STORED) + 1) * 8 -
@@ -137,10 +154,42 @@
 
   unsigned int samples = d->data.mid(12, 4).toUInt(false);
   if (samples == ~0u) {
+    if(d->file && d->style != Fast) {
+      samples = seekFinalIndex(); 
+    }
+    else {
     samples = 0;
   }
+  }
   d->length = d->sampleRate > 0 ? (samples + (d->sampleRate / 2)) / d->sampleRate : 0;
 
   d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0;
 }
 
+unsigned int WavPack::Properties::seekFinalIndex()
+{
+  ByteVector blockID("wvpk", 4);
+
+  long offset = d->streamLength;
+  while(offset > 0) {
+    offset = d->file->rfind(blockID, offset);
+    if(offset == -1)
+      return 0;
+    d->file->seek(offset);
+    ByteVector data = d->file->readBlock(32);
+    if(data.size() != 32)
+      return 0;
+    int version = data.mid(8, 2).toShort(false);
+    if(version < MIN_STREAM_VERS || version > MAX_STREAM_VERS)
+      continue;
+    unsigned int flags = data.mid(24, 4).toUInt(false);
+    if(!(flags & FINAL_BLOCK))
+      return 0;
+    unsigned int blockIndex = data.mid(16, 4).toUInt(false);
+    unsigned int blockSamples = data.mid(20, 4).toUInt(false);
+    return blockIndex + blockSamples;
+  }
+
+  return 0;
+}
+
--- trunk/kdesupport/taglib/taglib/wavpack/wavpackproperties.h #1201475:1201476
@@ -54,10 +54,19 @@
       /*!
        * Create an instance of WavPack::Properties with the data read from the
        * ByteVector \a data.
+       *
+       * \deprecated This constructor will be dropped in favor of the one below
+       * in a future version.
        */
       Properties(const ByteVector &data, long streamLength, ReadStyle style = Average);
 
       /*!
+       * Create an instance of WavPack::Properties.
+       */
+      // BIC: merge with the above constructor
+      Properties(File *file, long streamLength, ReadStyle style = Average);
+
+      /*!
        * Destroys this WavPack::Properties instance.
        */
       virtual ~Properties();
@@ -84,6 +93,7 @@
       Properties &operator=(const Properties &);
 
       void read();
+      unsigned int seekFinalIndex();
 
       class PropertiesPrivate;
       PropertiesPrivate *d;
--- trunk/kdesupport/taglib/tests/CMakeLists.txt #1201475:1201476
@@ -18,6 +18,7 @@
   ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/vorbis
   ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/flac
   ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/flac
+  ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/wavpack
 )
 
 SET(test_runner_SRCS
@@ -42,6 +43,7 @@
   test_ape.cpp
   test_apetag.cpp
   test_wav.cpp
+  test_wavpack.cpp
 )
 IF(WITH_MP4)
    SET(test_runner_SRCS ${test_runner_SRCS}
--- trunk/kdesupport/taglib/tests/Makefile.am #1201475:1201476
@@ -12,7 +12,8 @@
         -I$(top_srcdir)/taglib/flac \
         -I$(top_srcdir)/taglib/riff \
         -I$(top_srcdir)/taglib/riff/aiff \
-        -I$(top_srcdir)/taglib/mpeg/id3v2/frames
+        -I$(top_srcdir)/taglib/mpeg/id3v2/frames \
+        -I$(top_srcdir)/taglib/wavpack
 
 test_runner_SOURCES = \
 	main.cpp \
@@ -32,7 +33,8 @@
 	test_aiff.cpp \
 	test_ogg.cpp \
 	test_oggflac.cpp \
-	test_flac.cpp
+	test_flac.cpp \
+	test_wavpack.cpp
 
 if build_tests
 TESTS = test_runner
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic