AudioFileSizeEstimator.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version. See the file
12  COPYING included with this distribution for more information.
13 */
14 
15 #include "AudioFileSizeEstimator.h"
16 
17 #include "WavFileReader.h"
18 
19 #include <QFile>
20 
21 #include "base/Debug.h"
22 
25  sv_samplerate_t targetRate)
26 {
27  sv_frame_t estimate = 0;
28 
29  SVDEBUG << "AudioFileSizeEstimator: Sample count estimate requested for file \""
30  << source.getLocalFilename() << "\"" << endl;
31 
32  // Most of our file readers don't know the sample count until
33  // after they've finished decoding. This is an exception:
34 
35  WavFileReader *reader = new WavFileReader(source);
36  if (reader->isOK() &&
37  reader->getChannelCount() > 0 &&
38  reader->getFrameCount() > 0) {
39  sv_frame_t samples =
40  reader->getFrameCount() * reader->getChannelCount();
41  sv_samplerate_t rate = reader->getSampleRate();
42  if (targetRate != 0.0 && targetRate != rate) {
43  samples = sv_frame_t(double(samples) * targetRate / rate);
44  }
45  SVDEBUG << "AudioFileSizeEstimator: WAV file reader accepts this file, reports "
46  << samples << " samples" << endl;
47  estimate = samples;
48  } else {
49  SVDEBUG << "AudioFileSizeEstimator: WAV file reader doesn't like this file, "
50  << "estimating from file size and extension instead" << endl;
51  }
52 
53  delete reader;
54  reader = nullptr;
55 
56  if (estimate == 0) {
57 
58  // The remainder just makes an estimate based on the file size
59  // and extension. We don't even know its sample rate at this
60  // point, so the following is a wild guess.
61 
62  double rateRatio = 1.0;
63  if (targetRate != 0.0) {
64  rateRatio = targetRate / 44100.0;
65  }
66 
67  QString extension = source.getExtension();
68 
69  source.waitForData();
70  if (!source.isOK()) return 0;
71 
72  sv_frame_t sz = 0;
73 
74  {
75  QFile f(source.getLocalFilename());
76  if (f.open(QFile::ReadOnly)) {
77  SVDEBUG << "AudioFileSizeEstimator: opened file, size is "
78  << f.size() << endl;
79  sz = f.size();
80  f.close();
81  }
82  }
83 
84  if (extension == "ogg" || extension == "oga" ||
85  extension == "m4a" || extension == "mp3" ||
86  extension == "wma" || extension == "opus") {
87 
88  // Usually a lossy file. Compression ratios can vary
89  // dramatically, but don't usually exceed about 20x compared
90  // to 16-bit PCM (e.g. a 128kbps mp3 has 11x ratio over WAV at
91  // 44.1kHz). We can estimate the number of samples to be file
92  // size x 20, divided by 2 as we're comparing with 16-bit PCM.
93 
94  estimate = sv_frame_t(double(sz) * 10 * rateRatio);
95  }
96 
97  if (extension == "flac") {
98 
99  // FLAC usually takes up a bit more than half the space of
100  // 16-bit PCM. So the number of 16-bit samples is roughly the
101  // same as the file size in bytes. As above, let's be
102  // conservative.
103 
104  estimate = sv_frame_t(double(sz) * 1.2 * rateRatio);
105  }
106 
107  SVDEBUG << "AudioFileSizeEstimator: for extension \""
108  << extension << "\", estimate = " << estimate << " samples" << endl;
109  }
110 
111  return estimate;
112 }
113 
double sv_samplerate_t
Sample rate.
Definition: BaseTypes.h:51
int64_t sv_frame_t
Frame index, the unit of our time axis.
Definition: BaseTypes.h:31
Reader for audio files using libsndfile.
Definition: WavFileReader.h:41
QString getLocalFilename() const
Return the name of the local file this FileSource refers to.
Definition: FileSource.cpp:622
void waitForData()
Block on a sub-event-loop until the whole of the data has been retrieved (if it is remote)...
Definition: FileSource.cpp:570
FileSource is a class used to refer to the contents of a file that may be either local or at a remote...
Definition: FileSource.h:59
#define SVDEBUG
Definition: Debug.h:106
bool isOK() const
Return true if the file was opened successfully and no error has subsequently occurred.
static sv_frame_t estimate(FileSource source, sv_samplerate_t targetRate=0)
Return an estimate of the number of samples (across all channels) in the given audio file...
QString getExtension() const
Return the file extension for this file, if any.
Definition: FileSource.cpp:640
sv_frame_t getFrameCount() const
Return the number of audio sample frames (i.e.
sv_samplerate_t getSampleRate() const
Return the samplerate at which the file is being read.
int getChannelCount() const
Return the number of channels in the file.
bool isOK() const
Return true if the FileSource object is valid and neither error nor cancellation occurred while retri...
Definition: FileSource.cpp:586