diff data/fileio/AudioFileSizeEstimator.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 393134235fa0
children 513e4d67d8df
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/fileio/AudioFileSizeEstimator.cpp	Thu Aug 20 14:54:21 2015 +0100
@@ -0,0 +1,108 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#include "AudioFileSizeEstimator.h"
+
+#include "WavFileReader.h"
+
+#include <QFile>
+
+//#define DEBUG_AUDIO_FILE_SIZE_ESTIMATOR 1
+
+sv_frame_t
+AudioFileSizeEstimator::estimate(FileSource source,
+				 sv_samplerate_t targetRate)
+{
+    sv_frame_t estimate = 0;
+    
+    // Most of our file readers don't know the sample count until
+    // after they've finished decoding. This is an exception:
+
+    WavFileReader *reader = new WavFileReader(source);
+    if (reader->isOK() &&
+	reader->getChannelCount() > 0 &&
+	reader->getFrameCount() > 0) {
+	sv_frame_t samples =
+	    reader->getFrameCount() * reader->getChannelCount();
+	sv_samplerate_t rate = reader->getSampleRate();
+	if (targetRate != 0.0 && targetRate != rate) {
+	    samples = sv_frame_t(double(samples) * targetRate / rate);
+	}
+	delete reader;
+	estimate = samples;
+    }
+
+    if (estimate == 0) {
+
+	// The remainder just makes an estimate based on the file size
+	// and extension. We don't even know its sample rate at this
+	// point, so the following is a wild guess.
+	
+	double rateRatio = 1.0;
+	if (targetRate != 0.0) {
+	    rateRatio = targetRate / 44100.0;
+	}
+    
+	QString extension = source.getExtension();
+
+	source.waitForData();
+	if (!source.isOK()) return 0;
+
+	sv_frame_t sz = 0;
+	{
+	    QFile f(source.getLocalFilename());
+	    if (f.open(QFile::ReadOnly)) {
+#ifdef DEBUG_AUDIO_FILE_SIZE_ESTIMATOR
+		cerr << "opened file, size is "  << f.size() << endl;
+#endif
+		sz = f.size();
+		f.close();
+	    }
+	}
+
+	if (extension == "ogg" || extension == "oga" ||
+	    extension == "m4a" || extension == "mp3" ||
+	    extension == "wma") {
+
+	    // Usually a lossy file. Compression ratios can vary
+	    // dramatically, but don't usually exceed about 20x compared
+	    // to 16-bit PCM (e.g. a 128kbps mp3 has 11x ratio over WAV at
+	    // 44.1kHz). We can estimate the number of samples to be file
+	    // size x 20, divided by 2 as we're comparing with 16-bit PCM.
+
+	    estimate = sv_frame_t(double(sz) * 10 * rateRatio);
+	}
+
+	if (extension == "flac") {
+	
+	    // FLAC usually takes up a bit more than half the space of
+	    // 16-bit PCM. So the number of 16-bit samples is roughly the
+	    // same as the file size in bytes. As above, let's be
+	    // conservative.
+
+	    estimate = sv_frame_t(double(sz) * 1.2 * rateRatio);
+	}
+
+#ifdef DEBUG_AUDIO_FILE_SIZE_ESTIMATOR
+	cerr << "AudioFileSizeEstimator: for extension " << extension << ", estimate = " << estimate << endl;
+#endif
+    }
+
+#ifdef DEBUG_AUDIO_FILE_SIZE_ESTIMATOR
+    cerr << "estimate = " << estimate << endl;
+#endif
+    
+    return estimate;
+}
+