Added TagLib (with AUTORS and COPYING files)
[someplayer] / src / taglib / mpeg / mpegheader.cpp
1 /***************************************************************************
2     copyright            : (C) 2002 - 2008 by Scott Wheeler
3     email                : wheeler@kde.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
19  *   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 <bitset>
27
28 #include <tbytevector.h>
29 #include <tstring.h>
30 #include <tdebug.h>
31
32 #include "mpegheader.h"
33
34 using namespace TagLib;
35
36 class MPEG::Header::HeaderPrivate : public RefCounter
37 {
38 public:
39   HeaderPrivate() :
40     isValid(false),
41     version(Version1),
42     layer(0),
43     protectionEnabled(false),
44     sampleRate(0),
45     isPadded(false),
46     channelMode(Stereo),
47     isCopyrighted(false),
48     isOriginal(false),
49     frameLength(0),
50     samplesPerFrame(0) {}
51
52   bool isValid;
53   Version version;
54   int layer;
55   bool protectionEnabled;
56   int bitrate;
57   int sampleRate;
58   bool isPadded;
59   ChannelMode channelMode;
60   bool isCopyrighted;
61   bool isOriginal;
62   int frameLength;
63   int samplesPerFrame;
64 };
65
66 ////////////////////////////////////////////////////////////////////////////////
67 // public members
68 ////////////////////////////////////////////////////////////////////////////////
69
70 MPEG::Header::Header(const ByteVector &data)
71 {
72   d = new HeaderPrivate;
73   parse(data);
74 }
75
76 MPEG::Header::Header(const Header &h) : d(h.d)
77 {
78   d->ref();
79 }
80
81 MPEG::Header::~Header()
82 {
83   if (d->deref())
84     delete d;
85 }
86
87 bool MPEG::Header::isValid() const
88 {
89   return d->isValid;
90 }
91
92 MPEG::Header::Version MPEG::Header::version() const
93 {
94   return d->version;
95 }
96
97 int MPEG::Header::layer() const
98 {
99   return d->layer;
100 }
101
102 bool MPEG::Header::protectionEnabled() const
103 {
104   return d->protectionEnabled;
105 }
106
107 int MPEG::Header::bitrate() const
108 {
109   return d->bitrate;
110 }
111
112 int MPEG::Header::sampleRate() const
113 {
114   return d->sampleRate;
115 }
116
117 bool MPEG::Header::isPadded() const
118 {
119   return d->isPadded;
120 }
121
122 MPEG::Header::ChannelMode MPEG::Header::channelMode() const
123 {
124   return d->channelMode;
125 }
126
127 bool MPEG::Header::isCopyrighted() const
128 {
129   return d->isCopyrighted;
130 }
131
132 bool MPEG::Header::isOriginal() const
133 {
134   return d->isOriginal;
135 }
136
137 int MPEG::Header::frameLength() const
138 {
139   return d->frameLength;
140 }
141
142 int MPEG::Header::samplesPerFrame() const
143 {
144   return d->samplesPerFrame;
145 }
146
147 MPEG::Header &MPEG::Header::operator=(const Header &h)
148 {
149   if(&h == this)
150     return *this;
151
152   if(d->deref())
153     delete d;
154
155   d = h.d;
156   d->ref();
157   return *this;
158 }
159
160 ////////////////////////////////////////////////////////////////////////////////
161 // private members
162 ////////////////////////////////////////////////////////////////////////////////
163
164 void MPEG::Header::parse(const ByteVector &data)
165 {
166   if(data.size() < 4 || uchar(data[0]) != 0xff) {
167     debug("MPEG::Header::parse() -- First byte did not match MPEG synch.");
168     return;
169   }
170
171   std::bitset<32> flags(data.toUInt());
172
173   // Check for the second byte's part of the MPEG synch
174
175   if(!flags[23] || !flags[22] || !flags[21]) {
176     debug("MPEG::Header::parse() -- Second byte did not match MPEG synch.");
177     return;
178   }
179
180   // Set the MPEG version
181
182   if(!flags[20] && !flags[19])
183     d->version = Version2_5;
184   else if(flags[20] && !flags[19])
185     d->version = Version2;
186   else if(flags[20] && flags[19])
187     d->version = Version1;
188
189   // Set the MPEG layer
190
191   if(!flags[18] && flags[17])
192     d->layer = 3;
193   else if(flags[18] && !flags[17])
194     d->layer = 2;
195   else if(flags[18] && flags[17])
196     d->layer = 1;
197
198   d->protectionEnabled = !flags[16];
199
200   // Set the bitrate
201
202   static const int bitrates[2][3][16] = {
203     { // Version 1
204       { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 }, // layer 1
205       { 0, 32, 48, 56, 64,  80,  96,  112, 128, 160, 192, 224, 256, 320, 384, 0 }, // layer 2
206       { 0, 32, 40, 48, 56,  64,  80,  96,  112, 128, 160, 192, 224, 256, 320, 0 }  // layer 3
207     },
208     { // Version 2 or 2.5
209       { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 }, // layer 1
210       { 0, 8,  16, 24, 32, 40, 48, 56,  64,  80,  96,  112, 128, 144, 160, 0 }, // layer 2
211       { 0, 8,  16, 24, 32, 40, 48, 56,  64,  80,  96,  112, 128, 144, 160, 0 }  // layer 3
212     }
213   };
214
215   const int versionIndex = d->version == Version1 ? 0 : 1;
216   const int layerIndex = d->layer > 0 ? d->layer - 1 : 0;
217
218   // The bitrate index is encoded as the first 4 bits of the 3rd byte,
219   // i.e. 1111xxxx
220
221   int i = uchar(data[2]) >> 4;
222
223   d->bitrate = bitrates[versionIndex][layerIndex][i];
224
225   // Set the sample rate
226
227   static const int sampleRates[3][4] = {
228     { 44100, 48000, 32000, 0 }, // Version 1
229     { 22050, 24000, 16000, 0 }, // Version 2
230     { 11025, 12000, 8000,  0 }  // Version 2.5
231   };
232
233   // The sample rate index is encoded as two bits in the 3nd byte, i.e. xxxx11xx
234
235   i = uchar(data[2]) >> 2 & 0x03;
236
237   d->sampleRate = sampleRates[d->version][i];
238
239   if(d->sampleRate == 0) {
240     debug("MPEG::Header::parse() -- Invalid sample rate.");
241     return;
242   }
243
244   // The channel mode is encoded as a 2 bit value at the end of the 3nd byte,
245   // i.e. xxxxxx11
246
247   d->channelMode = ChannelMode((uchar(data[3]) & 0xC0) >> 6);
248
249   // TODO: Add mode extension for completeness
250
251   d->isOriginal = flags[2];
252   d->isCopyrighted = flags[3];
253   d->isPadded = flags[9];
254
255   // Calculate the frame length
256
257   if(d->layer == 1)
258     d->frameLength = 24000 * 2 * d->bitrate / d->sampleRate + int(d->isPadded);
259   else
260     d->frameLength = 72000 * d->bitrate / d->sampleRate + int(d->isPadded);
261
262   // Samples per frame
263
264   static const int samplesPerFrame[3][2] = {
265     // MPEG1, 2/2.5
266     {  384,   384 }, // Layer I
267     { 1152,  1152 }, // Layer II
268     { 1152,   576 }  // Layer III
269   };
270
271   d->samplesPerFrame = samplesPerFrame[layerIndex][versionIndex];
272
273   // Now that we're done parsing, set this to be a valid frame.
274
275   d->isValid = true;
276 }