1 /***************************************************************************
2     copyright            : (C) 2003 by Allan Sandfeld Jensen
3     email                : kde@carewolf.org
4  ***************************************************************************/
5 
6 /***************************************************************************
7  *   This library is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU Lesser General Public License version   *
9  *   2.1 as published by the Free Software Foundation.                     *
10  *                                                                         *
11  *   This library is distributed in the hope that it will be useful, but   *
12  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
14  *   Lesser General Public License for more details.                       *
15  *                                                                         *
16  *   You should have received a copy of the GNU Lesser General Public      *
17  *   License along with this library; if not, write to the Free Software   *
18  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
19  *   02110-1301  USA                                                       *
20  *                                                                         *
21  *   Alternatively, this file is available under the Mozilla Public        *
22  *   License Version 1.1.  You may obtain a copy of the License at         *
23  *   http://www.mozilla.org/MPL/                                           *
24  ***************************************************************************/
25 
26 #include <tstring.h>
27 #include <tdebug.h>
28 
29 #include "flacproperties.h"
30 #include "flacfile.h"
31 
32 using namespace TagLib;
33 
34 class FLAC::Properties::PropertiesPrivate
35 {
36 public:
PropertiesPrivate()37   PropertiesPrivate() :
38     length(0),
39     bitrate(0),
40     sampleRate(0),
41     bitsPerSample(0),
42     channels(0),
43     sampleFrames(0) {}
44 
45   int length;
46   int bitrate;
47   int sampleRate;
48   int bitsPerSample;
49   int channels;
50   unsigned long long sampleFrames;
51   ByteVector signature;
52 };
53 
54 ////////////////////////////////////////////////////////////////////////////////
55 // public members
56 ////////////////////////////////////////////////////////////////////////////////
57 
Properties(ByteVector data,long streamLength,ReadStyle style)58 FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) :
59   AudioProperties(style),
60   d(new PropertiesPrivate())
61 {
62   read(data, streamLength);
63 }
64 
Properties(File *,ReadStyle style)65 FLAC::Properties::Properties(File *, ReadStyle style) :
66   AudioProperties(style),
67   d(new PropertiesPrivate())
68 {
69   debug("FLAC::Properties::Properties() - This constructor is no longer used.");
70 }
71 
~Properties()72 FLAC::Properties::~Properties()
73 {
74   delete d;
75 }
76 
length() const77 int FLAC::Properties::length() const
78 {
79   return lengthInSeconds();
80 }
81 
lengthInSeconds() const82 int FLAC::Properties::lengthInSeconds() const
83 {
84   return d->length / 1000;
85 }
86 
lengthInMilliseconds() const87 int FLAC::Properties::lengthInMilliseconds() const
88 {
89   return d->length;
90 }
91 
bitrate() const92 int FLAC::Properties::bitrate() const
93 {
94   return d->bitrate;
95 }
96 
sampleRate() const97 int FLAC::Properties::sampleRate() const
98 {
99   return d->sampleRate;
100 }
101 
bitsPerSample() const102 int FLAC::Properties::bitsPerSample() const
103 {
104   return d->bitsPerSample;
105 }
106 
sampleWidth() const107 int FLAC::Properties::sampleWidth() const
108 {
109   return bitsPerSample();
110 }
111 
channels() const112 int FLAC::Properties::channels() const
113 {
114   return d->channels;
115 }
116 
sampleFrames() const117 unsigned long long FLAC::Properties::sampleFrames() const
118 {
119   return d->sampleFrames;
120 }
121 
signature() const122 ByteVector FLAC::Properties::signature() const
123 {
124   return d->signature;
125 }
126 
127 ////////////////////////////////////////////////////////////////////////////////
128 // private members
129 ////////////////////////////////////////////////////////////////////////////////
130 
read(const ByteVector & data,long streamLength)131 void FLAC::Properties::read(const ByteVector &data, long streamLength)
132 {
133   if(data.size() < 18) {
134     debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes.");
135     return;
136   }
137 
138   unsigned int pos = 0;
139 
140   // Minimum block size (in samples)
141   pos += 2;
142 
143   // Maximum block size (in samples)
144   pos += 2;
145 
146   // Minimum frame size (in bytes)
147   pos += 3;
148 
149   // Maximum frame size (in bytes)
150   pos += 3;
151 
152   const unsigned int flags = data.toUInt(pos, true);
153   pos += 4;
154 
155   d->sampleRate    = flags >> 12;
156   d->channels      = ((flags >> 9) &  7) + 1;
157   d->bitsPerSample = ((flags >> 4) & 31) + 1;
158 
159   // The last 4 bits are the most significant 4 bits for the 36 bit
160   // stream length in samples. (Audio files measured in days)
161 
162   const unsigned long long hi = flags & 0xf;
163   const unsigned long long lo = data.toUInt(pos, true);
164   pos += 4;
165 
166   d->sampleFrames = (hi << 32) | lo;
167 
168   if(d->sampleFrames > 0 && d->sampleRate > 0) {
169     const double length = d->sampleFrames * 1000.0 / d->sampleRate;
170     d->length  = static_cast<int>(length + 0.5);
171     d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
172   }
173 
174   if(data.size() >= pos + 16)
175     d->signature = data.mid(pos, 16);
176 }
177