Chris@1098: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@1098: Chris@1098: /* Chris@1098: Sonic Visualiser Chris@1098: An audio file viewer and annotation editor. Chris@1098: Centre for Digital Music, Queen Mary, University of London. Chris@1098: Chris@1098: This program is free software; you can redistribute it and/or Chris@1098: modify it under the terms of the GNU General Public License as Chris@1098: published by the Free Software Foundation; either version 2 of the Chris@1098: License, or (at your option) any later version. See the file Chris@1098: COPYING included with this distribution for more information. Chris@1098: */ Chris@1098: Chris@1098: #include "AudioFileSizeEstimator.h" Chris@1098: Chris@1098: #include "WavFileReader.h" Chris@1098: Chris@1098: #include Chris@1098: Chris@1342: #include "base/Debug.h" Chris@1104: Chris@1098: sv_frame_t Chris@1098: AudioFileSizeEstimator::estimate(FileSource source, Chris@1341: sv_samplerate_t targetRate) Chris@1098: { Chris@1098: sv_frame_t estimate = 0; Chris@1098: Chris@1342: SVDEBUG << "AudioFileSizeEstimator: Sample count estimate requested for file \"" Chris@1342: << source.getLocalFilename() << "\"" << endl; Chris@1342: Chris@1098: // Most of our file readers don't know the sample count until Chris@1098: // after they've finished decoding. This is an exception: Chris@1098: Chris@1098: WavFileReader *reader = new WavFileReader(source); Chris@1098: if (reader->isOK() && Chris@1341: reader->getChannelCount() > 0 && Chris@1341: reader->getFrameCount() > 0) { Chris@1341: sv_frame_t samples = Chris@1341: reader->getFrameCount() * reader->getChannelCount(); Chris@1341: sv_samplerate_t rate = reader->getSampleRate(); Chris@1341: if (targetRate != 0.0 && targetRate != rate) { Chris@1341: samples = sv_frame_t(double(samples) * targetRate / rate); Chris@1341: } Chris@1342: SVDEBUG << "AudioFileSizeEstimator: WAV file reader accepts this file, reports " Chris@1342: << samples << " samples" << endl; Chris@1341: estimate = samples; Chris@1342: } else { Chris@1342: SVDEBUG << "AudioFileSizeEstimator: WAV file reader doesn't like this file, " Chris@1342: << "estimating from file size and extension instead" << endl; Chris@1098: } Chris@1098: Chris@1402: delete reader; Chris@1582: reader = nullptr; Chris@1402: Chris@1098: if (estimate == 0) { Chris@1098: Chris@1341: // The remainder just makes an estimate based on the file size Chris@1341: // and extension. We don't even know its sample rate at this Chris@1341: // point, so the following is a wild guess. Chris@1341: Chris@1341: double rateRatio = 1.0; Chris@1341: if (targetRate != 0.0) { Chris@1341: rateRatio = targetRate / 44100.0; Chris@1341: } Chris@1098: Chris@1341: QString extension = source.getExtension(); Chris@1098: Chris@1341: source.waitForData(); Chris@1341: if (!source.isOK()) return 0; Chris@1098: Chris@1341: sv_frame_t sz = 0; Chris@1342: Chris@1341: { Chris@1341: QFile f(source.getLocalFilename()); Chris@1341: if (f.open(QFile::ReadOnly)) { Chris@1342: SVDEBUG << "AudioFileSizeEstimator: opened file, size is " Chris@1342: << f.size() << endl; Chris@1341: sz = f.size(); Chris@1341: f.close(); Chris@1341: } Chris@1341: } Chris@1098: Chris@1341: if (extension == "ogg" || extension == "oga" || Chris@1341: extension == "m4a" || extension == "mp3" || Chris@1592: extension == "wma" || extension == "opus") { Chris@1098: Chris@1341: // Usually a lossy file. Compression ratios can vary Chris@1341: // dramatically, but don't usually exceed about 20x compared Chris@1341: // to 16-bit PCM (e.g. a 128kbps mp3 has 11x ratio over WAV at Chris@1341: // 44.1kHz). We can estimate the number of samples to be file Chris@1341: // size x 20, divided by 2 as we're comparing with 16-bit PCM. Chris@1098: Chris@1341: estimate = sv_frame_t(double(sz) * 10 * rateRatio); Chris@1341: } Chris@1098: Chris@1341: if (extension == "flac") { Chris@1341: Chris@1341: // FLAC usually takes up a bit more than half the space of Chris@1341: // 16-bit PCM. So the number of 16-bit samples is roughly the Chris@1341: // same as the file size in bytes. As above, let's be Chris@1341: // conservative. Chris@1098: Chris@1341: estimate = sv_frame_t(double(sz) * 1.2 * rateRatio); Chris@1341: } Chris@1098: Chris@1342: SVDEBUG << "AudioFileSizeEstimator: for extension \"" Chris@1342: << extension << "\", estimate = " << estimate << " samples" << endl; Chris@1098: } Chris@1098: Chris@1098: return estimate; Chris@1098: } Chris@1098: