changeset 1307:c84629395040 mp3-gapless

Handle trimming the padding from end as well
author Chris Cannam
date Tue, 29 Nov 2016 13:34:51 +0000
parents b325e91505b5
children 80c77916fe85
files data/fileio/CodedAudioFileReader.cpp data/fileio/CodedAudioFileReader.h data/fileio/MP3FileReader.cpp
diffstat 3 files changed, 48 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/data/fileio/CodedAudioFileReader.cpp	Tue Nov 29 12:06:49 2016 +0000
+++ b/data/fileio/CodedAudioFileReader.cpp	Tue Nov 29 13:34:51 2016 +0000
@@ -41,7 +41,7 @@
     m_cacheFileReader(0),
     m_cacheWriteBuffer(0),
     m_cacheWriteBufferIndex(0),
-    m_cacheWriteBufferSize(16384),
+    m_cacheWriteBufferSize(65536),
     m_resampler(0),
     m_resampleBuffer(0),
     m_fileFrameCount(0),
@@ -96,7 +96,7 @@
 }
 
 void
-CodedAudioFileReader::setSamplesToTrim(sv_frame_t fromStart, sv_frame_t fromEnd)
+CodedAudioFileReader::setFramesToTrim(sv_frame_t fromStart, sv_frame_t fromEnd)
 {
     m_trimFromStart = fromStart;
     m_trimFromEnd = fromEnd;
@@ -127,6 +127,11 @@
 
     SVDEBUG << "CodedAudioFileReader::initialiseDecodeCache: file rate = " << m_fileRate << endl;
 
+    if (m_channelCount == 0) {
+        SVCERR << "CodedAudioFileReader::initialiseDecodeCache: No channel count set!" << endl;
+        throw std::logic_error("No channel count set");
+    }
+    
     if (m_fileRate == 0) {
         SVDEBUG << "CodedAudioFileReader::initialiseDecodeCache: ERROR: File sample rate unknown (bug in subclass implementation?)" << endl;
         throw FileOperationFailed("(coded file)", "File sample rate unknown (bug in subclass implementation?)");
@@ -221,6 +226,11 @@
         m_data.clear();
     }
 
+    if (m_trimFromEnd >= (m_cacheWriteBufferSize * m_channelCount)) {
+        SVCERR << "WARNING: CodedAudioFileReader::setSamplesToTrim: Can't handle trimming more frames from end (" << m_trimFromEnd << ") than can be stored in cache-write buffer (" << (m_cacheWriteBufferSize * m_channelCount) << "), won't trim anything from the end after all";
+        m_trimFromEnd = 0;
+    }
+
     m_initialised = true;
 }
 
@@ -351,12 +361,35 @@
     if (final ||
         (m_cacheWriteBufferIndex ==
          m_cacheWriteBufferSize * m_channelCount)) {
+
+        if (m_trimFromEnd > 0) {
         
-        pushBuffer(m_cacheWriteBuffer,
-                   m_cacheWriteBufferIndex / m_channelCount,
-                   final);
-        
-        m_cacheWriteBufferIndex = 0;
+            sv_frame_t framesToPush =
+                (m_cacheWriteBufferIndex / m_channelCount) - m_trimFromEnd;
+
+            if (framesToPush <= 0 && !final) {
+                // This won't do, the buffer is full so we have to push
+                // something. Should have checked for this earlier
+                throw std::logic_error("Buffer full but nothing to push");
+            }
+
+            pushBuffer(m_cacheWriteBuffer, framesToPush, final);
+            
+            m_cacheWriteBufferIndex -= framesToPush * m_channelCount;
+
+            for (sv_frame_t i = 0; i < m_cacheWriteBufferIndex; ++i) {
+                m_cacheWriteBuffer[i] =
+                    m_cacheWriteBuffer[framesToPush * m_channelCount + i];
+            }
+
+        } else {
+
+            pushBuffer(m_cacheWriteBuffer,
+                       m_cacheWriteBufferIndex / m_channelCount,
+                       final);
+
+            m_cacheWriteBufferIndex = 0;
+        }
 
         if (m_cacheFileReader) {
             m_cacheFileReader->updateFrameCount();
@@ -466,7 +499,7 @@
 
         sv_frame_t padSamples = padFrames * m_channelCount;
 
-        SVDEBUG << "pushBufferResampling: frameCount = " << m_frameCount << ", equivFileFrames = " << double(m_frameCount) / ratio << ", m_fileFrameCount = " << m_fileFrameCount << ", padFrames = " << padFrames << ", padSamples = " << padSamples << endl;
+        SVDEBUG << "CodedAudioFileReader::pushBufferResampling: frameCount = " << m_frameCount << ", equivFileFrames = " << double(m_frameCount) / ratio << ", m_fileFrameCount = " << m_fileFrameCount << ", padFrames = " << padFrames << ", padSamples = " << padSamples << endl;
 
         float *padding = new float[padSamples];
         for (sv_frame_t i = 0; i < padSamples; ++i) padding[i] = 0.f;
--- a/data/fileio/CodedAudioFileReader.h	Tue Nov 29 12:06:49 2016 +0000
+++ b/data/fileio/CodedAudioFileReader.h	Tue Nov 29 13:34:51 2016 +0000
@@ -63,7 +63,7 @@
     void initialiseDecodeCache(); // samplerate, channels must have been set
 
     // compensation for encoder delays:
-    void setSamplesToTrim(sv_frame_t fromStart, sv_frame_t fromEnd);
+    void setFramesToTrim(sv_frame_t fromStart, sv_frame_t fromEnd);
     
     // may throw InsufficientDiscSpace:
     void addSamplesToDecodeCache(float **samples, sv_frame_t nframes);
@@ -102,7 +102,7 @@
     SNDFILE *m_cacheFileWritePtr;
     WavFileReader *m_cacheFileReader;
     float *m_cacheWriteBuffer;
-    sv_frame_t m_cacheWriteBufferIndex;
+    sv_frame_t m_cacheWriteBufferIndex; // samples
     sv_frame_t m_cacheWriteBufferSize; // frames
 
     Resampler *m_resampler;
--- a/data/fileio/MP3FileReader.cpp	Tue Nov 29 12:06:49 2016 +0000
+++ b/data/fileio/MP3FileReader.cpp	Tue Nov 29 13:34:51 2016 +0000
@@ -72,7 +72,7 @@
     m_reporter = reporter;
 
     if (m_gaplessMode == Gapless) {
-        CodedAudioFileReader::setSamplesToTrim(DEFAULT_DECODER_DELAY, 0);
+        CodedAudioFileReader::setFramesToTrim(DEFAULT_DECODER_DELAY, 0);
     }
     
     struct stat stat;
@@ -375,7 +375,7 @@
     return data->reader->filter(stream, frame);
 }
 
-static string toMagic(uint32_t fourcc)
+static string toMagic(unsigned long fourcc)
 {
     string magic("....");
     for (int i = 0; i < 4; ++i) {
@@ -437,8 +437,8 @@
                 (void)mad_bit_read(&ptr, 8);
             }
 
-            uint32_t delay = mad_bit_read(&ptr, 12);
-            uint32_t padding = mad_bit_read(&ptr, 12);
+            auto delay = mad_bit_read(&ptr, 12);
+            auto padding = mad_bit_read(&ptr, 12);
 
             sv_frame_t delayToDrop = DEFAULT_DECODER_DELAY + delay;
             sv_frame_t paddingToDrop = padding - DEFAULT_DECODER_DELAY;
@@ -451,7 +451,7 @@
                     << " samples from start and " << paddingToDrop
                     << " from end" << endl;
 
-            CodedAudioFileReader::setSamplesToTrim(delayToDrop, paddingToDrop);
+            CodedAudioFileReader::setFramesToTrim(delayToDrop, paddingToDrop);
             
         } else {
             SVDEBUG << "MP3FileReader: Xing frame has no LAME metadata" << endl;