1 /***************************************************************************
2 copyright : (C) 2014 by Peking Duck Labs
3 email : pekingducklabs@gmail.com
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
22 #include <cstdint>
23
24 #include <bitset>
25
26 // Kid3: Remove taglib/ from includes
27 #include <tbytevector.h>
28 #include <tstring.h>
29 #include <trefcounter.h>
30 // Kid3: Use debug() instead of std::cerr
31 #include <tdebug.h>
32
33 #include "dsfheader.h"
34
35 class DSFHeader::HeaderPrivate : public TagLib::RefCounter
36 {
37 public:
HeaderPrivate()38 HeaderPrivate()
39 : isValid(false),
40 version(Version1),
41 sampleCount(0),
42 channelType(Stereo),
43 channelNum(2),
44 sampleRate(0),
45 bitsPerSample(0),
46 ID3v2Offset(0),
47 fileSize(0)
48 {}
49
50 bool isValid;
51 Version version; // format version
52 uint64_t sampleCount;
53 ChannelType channelType;
54 unsigned short channelNum;
55 unsigned int sampleRate;
56 unsigned short bitsPerSample;
57 uint64_t ID3v2Offset;
58 uint64_t fileSize;
59 };
60
61 ////////////////////////////////////////////////////////////////////////////////
62 // public members
63 ////////////////////////////////////////////////////////////////////////////////
64
DSFHeader(const TagLib::ByteVector & data)65 DSFHeader::DSFHeader(const TagLib::ByteVector &data)
66 {
67 d = new HeaderPrivate;
68 parse(data);
69 }
70
DSFHeader(const DSFHeader & h)71 DSFHeader::DSFHeader(const DSFHeader &h) : d(h.d)
72 {
73 d->ref();
74 }
75
~DSFHeader()76 DSFHeader::~DSFHeader()
77 {
78 if (d->deref())
79 delete d;
80 }
81
isValid() const82 bool DSFHeader::isValid() const
83 {
84 return d->isValid;
85 }
86
version() const87 DSFHeader::Version DSFHeader::version() const
88 {
89 return d->version;
90 }
91
sampleRate() const92 unsigned int DSFHeader::sampleRate() const
93 {
94 return d->sampleRate;
95 }
96
channelType() const97 DSFHeader::ChannelType DSFHeader::channelType() const
98 {
99 return d->channelType;
100 }
101
channelNum() const102 unsigned short DSFHeader::channelNum() const
103 {
104 return d->channelNum;
105 }
106
sampleCount() const107 uint64_t DSFHeader::sampleCount() const
108 {
109 return d->sampleCount;
110 }
111
ID3v2Offset() const112 uint64_t DSFHeader::ID3v2Offset() const
113 {
114 return d->ID3v2Offset;
115 }
116
fileSize() const117 uint64_t DSFHeader::fileSize() const
118 {
119 return d->fileSize;
120 }
121
bitsPerSample() const122 unsigned short DSFHeader::bitsPerSample() const
123 {
124 return d->bitsPerSample;
125 }
126
operator =(const DSFHeader & h)127 DSFHeader &DSFHeader::operator=(const DSFHeader &h)
128 {
129 if(&h == this)
130 return *this;
131
132 if(d->deref())
133 delete d;
134
135 d = h.d;
136 d->ref();
137 return *this;
138 }
139
140 ////////////////////////////////////////////////////////////////////////////////
141 // private members
142 ////////////////////////////////////////////////////////////////////////////////
143
parse(const TagLib::ByteVector & data)144 void DSFHeader::parse(const TagLib::ByteVector &data)
145 {
146 if (data.size() < DSD_HEADER_SIZE + FMT_HEADER_SIZE) {
147 debug("DSFHeader::parse(): header size incorrect");
148 return;
149 }
150
151 const char *hdr = data.data();
152 size_t offset = 0;
153
154 //
155 // ******** DSD chunk header ********
156 // DSD header chunk should start with "DSD ".
157 //
158 if (hdr[0] != 'D' || hdr[1] != 'S' || hdr[2] != 'D' || hdr[3] != ' ')
159 {
160 debug("DSD::Header::parse(): DSD header's first 4 bytes != 'DSD '");
161 return;
162 }
163 offset += 4;
164
165 // The next 8 bytes contain the size of DSD header
166 // (numerical data is stored in little endian)
167 if (data.toLongLong(offset, false) != DSD_HEADER_SIZE)
168 {
169 debug("DSD::Header::parse(): DSD header size is incorrect");
170 return;
171 }
172 offset += LONG_INT_SIZE;
173
174 // The next 8 bytes contains the file size
175 d->fileSize = bytesToUInt64(&hdr[0], offset);
176 offset += LONG_INT_SIZE;
177
178 // The next 8 bytes contains the offset to id3v2 tag (0 if not exists)
179 d->ID3v2Offset = bytesToUInt64(&hdr[0], offset);
180 offset += LONG_INT_SIZE;
181
182 //
183 // ********* FMT chunk ********
184 //
185 // FMT header chunk should start with "fmt ".
186 //
187 if (hdr[offset] != 'f' || hdr[offset + 1] != 'm' ||
188 hdr[offset + 2] != 't' || hdr[offset + 3] != ' ')
189 {
190 debug("DSD::Header::parse(): FMT header's first 4 bytes != 'fmt '");
191 return;
192 }
193 offset += 4;
194
195 // The next 8 bytes contain the size of FMT header, which should be 52
196 if (data.toLongLong(offset, false) != FMT_HEADER_SIZE)
197 {
198 debug("DSD::Header::parse(): FMT header size is incorrect");
199 return;
200 }
201 offset += LONG_INT_SIZE;
202
203 // Format version
204 // There's only version 1 for now...
205 unsigned int ver = data.toUInt(offset, false);
206 if (ver != 1) {
207 debug("DSD::Header::parse(): format version != 1");
208 return;
209 }
210 d->version = static_cast<Version>(ver);
211 offset += INT_SIZE;
212
213 // Format ID
214 if (data.toUInt(offset, false) != 0) {
215 debug("DSD::Header::parse(): format ID != 0");
216 return;
217 }
218 offset += INT_SIZE;
219
220 // Channel Type
221 unsigned int ct = data.toUInt(offset, false);
222 if (ct < 1 || ct > 7) {
223 debug("DSD::Header::parse(): channel type out of range");
224 return;
225 }
226 d->channelType = static_cast<ChannelType>(ct);
227 offset += INT_SIZE;
228
229 // Channel Num
230 d->channelNum = data.toUInt(offset, false);
231 // Kid3: Removed check "d->channelNum < MinType || ", is always false.
232 if (d->channelNum > MaxType) {
233 debug("DSD::Header::parse(): channel num out of range");
234 return;
235 }
236 offset += INT_SIZE;
237
238 // Sampling frequency
239 d->sampleRate = data.toUInt(offset, false);
240 if (d->sampleRate != 2822400 && d->sampleRate != 5644800) {
241 debug("DSD::Header::parse(): invalid sampling frequency");
242 }
243 offset += INT_SIZE;
244
245 // Bits per sample
246 d->bitsPerSample = data.toUInt(offset, false);
247 if (d->bitsPerSample != 1 && d->bitsPerSample != 8) {
248 debug("DSD::Header::parse(): bits per sample invalid");
249 return;
250 }
251 offset += INT_SIZE;
252
253 // Sample count
254 d->sampleCount = bytesToUInt64(&hdr[0], offset);
255 offset += LONG_INT_SIZE;
256
257 // Block size per channel
258 if (data.toUInt(offset, false) != 4096) {
259 debug("DSD::Header::parse(): block size != 4096");
260 return;
261 }
262 //offset += 4;
263
264 // Reserved
265 // offset += 4;
266
267 d->isValid = true;
268 }
269