aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Wheeler <scott@directededge.com>2019-09-12 07:15:39 +0200
committerScott Wheeler <scott@directededge.com>2019-09-12 07:15:39 +0200
commit866802b0071c41a03ea387dd828cee98b6c5bd80 (patch)
treeca9f86044a9d58c6ef5820aa97232e0ac9cb15c9
parent088e063bbb9df4aec4f9e74f88f7a71ead9c2119 (diff)
The only non-pure-formatting changes are: - Switch from `if(foo != NULL)` to `if(foo)` - Switch from C arrays to std::array This also moves a file-static function into the anonymous namespace This style of formatting update would need to be done on the other files as well before this branch is merged back to master.
-rw-r--r--taglib/dsdiff/dsdifffile.cpp136
1 files changed, 93 insertions, 43 deletions
diff --git a/taglib/dsdiff/dsdifffile.cpp b/taglib/dsdiff/dsdifffile.cpp
index fa993ce5..55fbe54e 100644
--- a/taglib/dsdiff/dsdifffile.cpp
+++ b/taglib/dsdiff/dsdifffile.cpp
@@ -33,6 +33,8 @@
#include "tagunion.h"
#include "dsdifffile.h"
+#include <array>
+
using namespace TagLib;
namespace
@@ -57,6 +59,19 @@ namespace
return -1;
}
+ bool isValidChunkID(const ByteVector &name)
+ {
+ if(name.size() != 4)
+ return false;
+
+ for(int i = 0; i < 4; i++) {
+ if(name[i] < 32 || name[i] > 127)
+ return false;
+ }
+
+ return true;
+ }
+
enum {
ID3v2Index = 0,
DIINIndex = 1
@@ -71,14 +86,14 @@ class DSDIFF::File::FilePrivate
{
public:
FilePrivate() :
- endianness(BigEndian),
- size(0),
- isID3InPropChunk(false),
- duplicateID3V2chunkIndex(-1),
- properties(0),
- id3v2TagChunkID("ID3 "),
- hasID3v2(false),
- hasDiin(false)
+ endianness(BigEndian),
+ size(0),
+ isID3InPropChunk(false),
+ duplicateID3V2chunkIndex(-1),
+ properties(0),
+ id3v2TagChunkID("ID3 "),
+ hasID3v2(false),
+ hasDiin(false)
{
childChunkIndex[ID3v2Index] = -1;
childChunkIndex[DIINIndex] = -1;
@@ -94,11 +109,17 @@ public:
unsigned long long size;
ByteVector format;
ChunkList chunks;
- ChunkList childChunks[2];
- int childChunkIndex[2];
- bool isID3InPropChunk; // Two possibilities can be found: ID3V2 chunk inside PROP chunk or at root level
- int duplicateID3V2chunkIndex; // 2 ID3 chunks are present. This is then the index of the one in
- // PROP chunk that will be removed upon next save to remove duplicates.
+ std::array<ChunkList, 2> childChunks;
+ std::array<int, 2> childChunkIndex;
+ /*
+ * Two possibilities can be found: ID3V2 chunk inside PROP chunk or at root level
+ */
+ bool isID3InPropChunk;
+ /*
+ * ID3 chunks are present. This is then the index of the one in PROP chunk that
+ * will be removed upon next save to remove duplicates.
+ */
+ int duplicateID3V2chunkIndex;
Properties *properties;
@@ -222,11 +243,12 @@ bool DSDIFF::File::save(TagTypes tags, StripTags strip, ID3v2::Version version)
File::strip(static_cast<TagTypes>(AllTags & ~tags));
// First: save ID3V2 chunk
+
ID3v2::Tag *id3v2Tag = d->tag.access<ID3v2::Tag>(ID3v2Index, false);
if(tags & ID3v2 && id3v2Tag) {
if(d->isID3InPropChunk) {
- if(id3v2Tag != NULL && !id3v2Tag->isEmpty()) {
+ if(id3v2Tag && !id3v2Tag->isEmpty()) {
setChildChunkData(d->id3v2TagChunkID, id3v2Tag->render(version), PROPChunk);
d->hasID3v2 = true;
}
@@ -237,7 +259,7 @@ bool DSDIFF::File::save(TagTypes tags, StripTags strip, ID3v2::Version version)
}
}
else {
- if(id3v2Tag != NULL && !id3v2Tag->isEmpty()) {
+ if(id3v2Tag && !id3v2Tag->isEmpty()) {
setRootChunkData(d->id3v2TagChunkID, id3v2Tag->render(version));
d->hasID3v2 = true;
}
@@ -250,6 +272,7 @@ bool DSDIFF::File::save(TagTypes tags, StripTags strip, ID3v2::Version version)
}
// Second: save the DIIN chunk
+
DSDIFF::DIIN::Tag *diinTag = d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false);
if(tags & DIIN && diinTag) {
@@ -338,10 +361,12 @@ void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
// Non null data: update chunk
// First we update the global size
+
d->size += ((data.size() + 1) & ~1) - (d->chunks[i].size + d->chunks[i].padding);
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
// Now update the specific chunk
+
writeChunk(d->chunks[i].name,
data,
d->chunks[i].offset - 12,
@@ -351,6 +376,7 @@ void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
d->chunks[i].padding = (data.size() & 0x01) ? 1 : 0;
// Finally update the internal offsets
+
updateRootChunksStructure(i + 1);
}
@@ -401,16 +427,20 @@ void DSDIFF::File::removeChildChunk(unsigned int i, unsigned int childChunkNum)
unsigned long long removedChunkTotalSize = childChunks[i].size + childChunks[i].padding + 12;
d->size -= removedChunkTotalSize;
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
+
// Update child chunk size
+
d->chunks[d->childChunkIndex[childChunkNum]].size -= removedChunkTotalSize;
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
d->endianness == BigEndian),
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
// Remove the chunk
+
removeBlock(childChunks[i].offset - 12, removedChunkTotalSize);
// Update the internal offsets
// For child chunks
+
if((i + 1) < childChunks.size()) {
childChunks[i + 1].offset = childChunks[i].offset;
i++;
@@ -420,6 +450,7 @@ void DSDIFF::File::removeChildChunk(unsigned int i, unsigned int childChunkNum)
}
// And for root chunks
+
for(i = d->childChunkIndex[childChunkNum] + 1; i < d->chunks.size(); i++)
d->chunks[i].offset = d->chunks[i - 1].offset + 12
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
@@ -440,16 +471,21 @@ void DSDIFF::File::setChildChunkData(unsigned int i,
// Non null data: update chunk
// First we update the global size
+
d->size += ((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding);
+
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
+
// And the PROP chunk size
- d->chunks[d->childChunkIndex[childChunkNum]].size += ((data.size() + 1) & ~1)
- - (childChunks[i].size + childChunks[i].padding);
+
+ d->chunks[d->childChunkIndex[childChunkNum]].size +=
+ ((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding);
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
d->endianness == BigEndian),
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
// Now update the specific chunk
+
writeChunk(childChunks[i].name,
data,
childChunks[i].offset - 12,
@@ -487,17 +523,22 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
}
// Do not attempt to remove a non existing chunk
+
if(data.isEmpty())
return;
// Couldn't find an existing chunk, so let's create a new one.
+
unsigned int i = childChunks.size() - 1;
unsigned long offset = childChunks[i].offset + childChunks[i].size + childChunks[i].padding;
// First we update the global size
+
d->size += (offset & 1) + ((data.size() + 1) & ~1) + 12;
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
+
// And the child chunk size
+
d->chunks[d->childChunkIndex[childChunkNum]].size += (offset & 1)
+ ((data.size() + 1) & ~1) + 12;
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
@@ -505,6 +546,7 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
// Now add the chunk to the file
+
unsigned long long nextRootChunkIdx = length();
if((d->childChunkIndex[childChunkNum] + 1) < static_cast<int>(d->chunks.size()))
nextRootChunkIdx = d->chunks[d->childChunkIndex[childChunkNum] + 1].offset - 12;
@@ -514,6 +556,7 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
(offset & 1) ? 1 : 0);
// For root chunks
+
updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1);
Chunk64 chunk;
@@ -525,19 +568,6 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
childChunks.push_back(chunk);
}
-static bool isValidChunkID(const ByteVector &name)
-{
- if(name.size() != 4)
- return false;
-
- for(int i = 0; i < 4; i++) {
- if(name[i] < 32 || name[i] > 127)
- return false;
- }
-
- return true;
-}
-
void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
{
for(unsigned int i = startingChunk; i < d->chunks.size(); i++)
@@ -545,6 +575,7 @@ void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
// Update childchunks structure as well
+
if(d->childChunkIndex[PROPChunk] >= static_cast<int>(startingChunk)) {
ChunkList &childChunksToUpdate = d->childChunks[PROPChunk];
if(childChunksToUpdate.size() > 0) {
@@ -553,6 +584,7 @@ void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
+ childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
}
+
}
if(d->childChunkIndex[DIINChunk] >= static_cast<int>(startingChunk)) {
ChunkList &childChunksToUpdate = d->childChunks[DIINChunk];
@@ -574,6 +606,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
d->format = readBlock(4);
// + 12: chunk header at least, fix for additional junk bytes
+
while(tell() + 12 <= length()) {
ByteVector chunkName = readBlock(4);
unsigned long long chunkSize = readBlock(8).toLongLong(bigEndian);
@@ -584,7 +617,8 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
break;
}
- if(static_cast<unsigned long long>(tell()) + chunkSize > static_cast<unsigned long long>(length())) {
+ if(static_cast<unsigned long long>(tell()) + chunkSize >
+ static_cast<unsigned long long>(length())) {
debug("DSDIFF::File::read() -- Chunk '" + chunkName
+ "' has invalid size (larger than the file size)");
setValid(false);
@@ -599,6 +633,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
seek(chunk.size, Current);
// Check padding
+
chunk.padding = 0;
long uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
@@ -612,10 +647,14 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
d->chunks.push_back(chunk);
}
- unsigned long long lengthDSDSamplesTimeChannels = 0; // For DSD uncompressed
- unsigned long long audioDataSizeinBytes = 0; // For computing bitrate
- unsigned long dstNumFrames = 0; // For DST compressed frames
- unsigned short dstFrameRate = 0; // For DST compressed frames
+ // For DSD uncompressed
+ unsigned long long lengthDSDSamplesTimeChannels = 0;
+ // For computing bitrate
+ unsigned long long audioDataSizeinBytes = 0;
+ // For DST compressed frames
+ unsigned long dstNumFrames = 0;
+ // For DST compressed frames
+ unsigned short dstFrameRate = 0;
for(unsigned int i = 0; i < d->chunks.size(); i++) {
if(d->chunks[i].name == "DSD ") {
@@ -650,7 +689,8 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
// Found the DST frame information chunk
dstNumFrames = readBlock(4).toUInt(bigEndian);
dstFrameRate = readBlock(2).toUShort(bigEndian);
- break; // Found the wanted one, no need to look at the others
+ // Found the wanted one, no need to look at the others
+ break;
}
seek(dstChunkSize, Current);
@@ -669,7 +709,8 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
d->childChunkIndex[PROPChunk] = i;
// Now decodes the chunks inside the PROP chunk
long long propChunkEnd = d->chunks[i].offset + d->chunks[i].size;
- seek(d->chunks[i].offset + 4); // +4 to remove the 'SND ' marker at beginning of 'PROP' chunk
+ // +4 to remove the 'SND ' marker at beginning of 'PROP' chunk
+ seek(d->chunks[i].offset + 4);
while(tell() + 12 <= propChunkEnd) {
ByteVector propChunkName = readBlock(4);
long long propChunkSize = readBlock(8).toLongLong(bigEndian);
@@ -711,7 +752,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
else if(d->chunks[i].name == "DIIN") {
d->childChunkIndex[DIINChunk] = i;
d->hasDiin = true;
+
// Now decode the chunks inside the DIIN chunk
+
long long diinChunkEnd = d->chunks[i].offset + d->chunks[i].size;
seek(d->chunks[i].offset);
@@ -740,8 +783,10 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
seek(chunk.size, Current);
// Check padding
+
chunk.padding = 0;
long uPosNotPadded = tell();
+
if((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
@@ -776,10 +821,12 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
unsigned short channels=0;
for(unsigned int i = 0; i < d->childChunks[PROPChunk].size(); i++) {
- if(d->childChunks[PROPChunk][i].name == "ID3 " || d->childChunks[PROPChunk][i].name == "id3 ") {
+ if(d->childChunks[PROPChunk][i].name == "ID3 " ||
+ d->childChunks[PROPChunk][i].name == "id3 ") {
if(d->hasID3v2) {
d->duplicateID3V2chunkIndex = i;
- continue; // ID3V2 tag has already been found at root level
+ // ID3V2 tag has already been found at root level
+ continue;
}
d->id3v2TagChunkID = d->childChunks[PROPChunk][i].name;
d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->childChunks[PROPChunk][i].offset));
@@ -799,6 +846,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
}
// Read title & artist from DIIN chunk
+
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, true);
if(d->hasDiin) {
@@ -826,8 +874,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
if(lengthDSDSamplesTimeChannels == 0) {
// DST compressed signal : need to compute length of DSD uncompressed frames
if(dstFrameRate > 0)
- lengthDSDSamplesTimeChannels = (unsigned long long)dstNumFrames
- * (unsigned long long)sampleRate / (unsigned long long)dstFrameRate;
+ lengthDSDSamplesTimeChannels = (unsigned long long) dstNumFrames *
+ (unsigned long long) sampleRate /
+ (unsigned long long) dstFrameRate;
else
lengthDSDSamplesTimeChannels = 0;
}
@@ -838,7 +887,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
}
int bitrate = 0;
if(lengthDSDSamplesTimeChannels > 0)
- bitrate = (audioDataSizeinBytes*8*sampleRate) / lengthDSDSamplesTimeChannels / 1000;
+ bitrate = (audioDataSizeinBytes * 8 * sampleRate) / lengthDSDSamplesTimeChannels / 1000;
d->properties = new Properties(sampleRate,
channels,
@@ -849,7 +898,8 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
if(!ID3v2Tag()) {
d->tag.access<ID3v2::Tag>(ID3v2Index, true);
- d->isID3InPropChunk = false; // By default, ID3 chunk is at root level
+ // By default, ID3 chunk is at root level
+ d->isID3InPropChunk = false;
d->hasID3v2 = false;
}
}