Added TagLib (with AUTORS and COPYING files)
[someplayer] / src / taglib / mpc / mpcproperties.cpp
1 /***************************************************************************
2     copyright            : (C) 2004 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., 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 <tstring.h>
27 #include <tdebug.h>
28 #include <bitset>
29
30 #include "mpcproperties.h"
31 #include "mpcfile.h"
32
33 using namespace TagLib;
34
35 class MPC::Properties::PropertiesPrivate
36 {
37 public:
38   PropertiesPrivate(const ByteVector &d, long length, ReadStyle s) :
39     data(d),
40     streamLength(length),
41     style(s),
42     version(0),
43     length(0),
44     bitrate(0),
45     sampleRate(0),
46     channels(0) {}
47
48   ByteVector data;
49   long streamLength;
50   ReadStyle style;
51   int version;
52   int length;
53   int bitrate;
54   int sampleRate;
55   int channels;
56 };
57
58 ////////////////////////////////////////////////////////////////////////////////
59 // public members
60 ////////////////////////////////////////////////////////////////////////////////
61
62 MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style)
63 {
64   d = new PropertiesPrivate(data, streamLength, style);
65   read();
66 }
67
68 MPC::Properties::~Properties()
69 {
70   delete d;
71 }
72
73 int MPC::Properties::length() const
74 {
75   return d->length;
76 }
77
78 int MPC::Properties::bitrate() const
79 {
80   return d->bitrate;
81 }
82
83 int MPC::Properties::sampleRate() const
84 {
85   return d->sampleRate;
86 }
87
88 int MPC::Properties::channels() const
89 {
90   return d->channels;
91 }
92
93 int MPC::Properties::mpcVersion() const
94 {
95   return d->version;
96 }
97
98 ////////////////////////////////////////////////////////////////////////////////
99 // private members
100 ////////////////////////////////////////////////////////////////////////////////
101
102 static const unsigned short sftable [4] = { 44100, 48000, 37800, 32000 };
103
104 void MPC::Properties::read()
105 {
106   if(!d->data.startsWith("MP+"))
107     return;
108
109   d->version = d->data[3] & 15;
110
111   unsigned int frames;
112
113   if(d->version >= 7) {
114     frames = d->data.mid(4, 4).toUInt(false);
115
116     std::bitset<32> flags = d->data.mid(8, 4).toUInt(false);
117     d->sampleRate = sftable[flags[17] * 2 + flags[16]];
118     d->channels = 2;
119   }
120   else {
121     uint headerData = d->data.mid(0, 4).toUInt(false);
122
123     d->bitrate = (headerData >> 23) & 0x01ff;
124     d->version = (headerData >> 11) & 0x03ff;
125     d->sampleRate = 44100;
126     d->channels = 2;
127
128     if(d->version >= 5)
129       frames = d->data.mid(4, 4).toUInt(false);
130     else
131       frames = d->data.mid(6, 2).toUInt(false);
132   }
133
134   uint samples = frames * 1152 - 576;
135
136   d->length = d->sampleRate > 0 ? (samples + (d->sampleRate / 2)) / d->sampleRate : 0;
137
138   if(!d->bitrate)
139     d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0;
140 }