Merge pull request #421 from TsudaKageyu/fix-wav-strip

Fixed a bug on stripping tags when saving .WAV files.
This commit is contained in:
Lukáš Lalinský 2014-08-20 10:12:43 +02:00
commit d5e3d6ea7c
4 changed files with 129 additions and 26 deletions

View File

@ -219,22 +219,24 @@ void RIFF::File::removeChunk(uint i)
{
if(i >= d->chunks.size())
return;
removeBlock(d->chunks[i].offset - 8, d->chunks[i].size + 8);
d->chunks.erase(d->chunks.begin() + i);
std::vector<Chunk>::iterator it = d->chunks.begin();
std::advance(it, i);
const uint removeSize = it->size + it->padding + 8;
removeBlock(it->offset - 8, removeSize);
it = d->chunks.erase(it);
for(; it != d->chunks.end(); ++it)
it->offset -= removeSize;
}
void RIFF::File::removeChunk(const ByteVector &name)
{
std::vector<Chunk> newChunks;
for(size_t i = 0; i < d->chunks.size(); ++i) {
for(int i = d->chunks.size() - 1; i >= 0; --i) {
if(d->chunks[i].name == name)
removeBlock(d->chunks[i].offset - 8, d->chunks[i].size + 8);
else
newChunks.push_back(d->chunks[i]);
removeChunk(i);
}
d->chunks.swap(newChunks);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -147,24 +147,20 @@ bool RIFF::WAV::File::save(TagTypes tags, bool stripOthers, int id3v2Version)
strip(static_cast<TagTypes>(AllTags & ~tags));
ID3v2::Tag *id3v2tag = d->tag.access<ID3v2::Tag>(ID3v2Index, false);
if(!id3v2tag->isEmpty()) {
if(tags & ID3v2) {
setChunkData(d->tagChunkID, id3v2tag->render(id3v2Version));
d->hasID3v2 = true;
}
if((tags & ID3v2) && !id3v2tag->isEmpty()) {
setChunkData(d->tagChunkID, id3v2tag->render(id3v2Version));
d->hasID3v2 = true;
}
Info::Tag *infotag = d->tag.access<Info::Tag>(InfoIndex, false);
if(!infotag->isEmpty()) {
if(tags & Info) {
int chunkId = findInfoTagChunk();
if(chunkId != -1)
setChunkData(chunkId, infotag->render());
else
setChunkData("LIST", infotag->render(), true);
if((tags & Info) && !infotag->isEmpty()) {
int chunkId = findInfoTagChunk();
if(chunkId != -1)
setChunkData(chunkId, infotag->render());
else
setChunkData("LIST", infotag->render(), true);
d->hasInfo = true;
}
d->hasInfo = true;
}
return true;
@ -222,13 +218,17 @@ void RIFF::WAV::File::read(bool readProperties, Properties::ReadStyle properties
void RIFF::WAV::File::strip(TagTypes tags)
{
if(tags & ID3v2)
if(tags & ID3v2) {
removeChunk(d->tagChunkID);
d->hasID3v2 = false;
}
if(tags & Info){
TagLib::uint chunkId = findInfoTagChunk();
if(chunkId != TagLib::uint(-1))
if(chunkId != TagLib::uint(-1)) {
removeChunk(chunkId);
d->hasInfo = false;
}
}
}

View File

@ -20,12 +20,17 @@ public:
TagLib::uint chunkDataSize(TagLib::uint i) { return RIFF::File::chunkDataSize(i); };
ByteVector chunkName(TagLib::uint i) { return RIFF::File::chunkName(i); };
ByteVector chunkData(TagLib::uint i) { return RIFF::File::chunkData(i); };
void setChunkData(uint i, const ByteVector &data) {
RIFF::File::setChunkData(i, data);
}
void setChunkData(const ByteVector &name, const ByteVector &data) {
RIFF::File::setChunkData(name, data);
};
virtual TagLib::Tag* tag() const { return 0; };
virtual TagLib::AudioProperties* audioProperties() const { return 0;};
virtual bool save() { return false; };
void removeChunk(uint i) { RIFF::File::removeChunk(i); }
void removeChunk(const ByteVector &name) { RIFF::File::removeChunk(name); }
};
class TestRIFF : public CppUnit::TestFixture
@ -35,6 +40,7 @@ class TestRIFF : public CppUnit::TestFixture
CPPUNIT_TEST(testLastChunkAtEvenPosition);
CPPUNIT_TEST(testLastChunkAtEvenPosition2);
CPPUNIT_TEST(testLastChunkAtEvenPosition3);
CPPUNIT_TEST(testChunkOffset);
CPPUNIT_TEST_SUITE_END();
public:
@ -193,6 +199,63 @@ public:
delete f;
}
void testChunkOffset()
{
ScopedFileCopy copy("empty", ".aiff");
string filename = copy.fileName();
PublicRIFF *f = new PublicRIFF(filename.c_str());
CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f->chunkName(0));
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0));
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f->chunkName(1));
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x0026 + 8), f->chunkOffset(1));
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->chunkName(2));
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x1728 + 8), f->chunkOffset(2));
const ByteVector data(0x400, ' ');
f->setChunkData("SSND", data);
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0));
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x0026 + 8), f->chunkOffset(1));
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x042E + 8), f->chunkOffset(2));
f->seek(f->chunkOffset(0) - 8);
CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f->readBlock(4));
f->seek(f->chunkOffset(1) - 8);
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f->readBlock(4));
f->seek(f->chunkOffset(2) - 8);
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->readBlock(4));
f->setChunkData(0, data);
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0));
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x0414 + 8), f->chunkOffset(1));
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x081C + 8), f->chunkOffset(2));
f->seek(f->chunkOffset(0) - 8);
CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f->readBlock(4));
f->seek(f->chunkOffset(1) - 8);
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f->readBlock(4));
f->seek(f->chunkOffset(2) - 8);
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->readBlock(4));
f->removeChunk("SSND");
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0));
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x0414 + 8), f->chunkOffset(1));
f->seek(f->chunkOffset(0) - 8);
CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f->readBlock(4));
f->seek(f->chunkOffset(1) - 8);
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->readBlock(4));
f->removeChunk(0);
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0));
f->seek(f->chunkOffset(0) - 8);
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->readBlock(4));
delete f;
}
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestRIFF);

View File

@ -14,6 +14,7 @@ class TestWAV : public CppUnit::TestFixture
CPPUNIT_TEST_SUITE(TestWAV);
CPPUNIT_TEST(testLength);
CPPUNIT_TEST(testZeroSizeDataChunk);
CPPUNIT_TEST(testStripTags);
CPPUNIT_TEST_SUITE_END();
public:
@ -31,6 +32,43 @@ public:
CPPUNIT_ASSERT_EQUAL(false, f.isValid());
}
void testStripTags()
{
ScopedFileCopy copy("empty", ".wav");
string filename = copy.fileName();
RIFF::WAV::File *f = new RIFF::WAV::File(filename.c_str());
f->ID3v2Tag()->setTitle("test title");
f->InfoTag()->setTitle("test title");
f->save();
delete f;
f = new RIFF::WAV::File(filename.c_str());
CPPUNIT_ASSERT(f->hasID3v2Tag());
CPPUNIT_ASSERT(f->hasInfoTag());
f->save(RIFF::WAV::File::ID3v2, true);
delete f;
f = new RIFF::WAV::File(filename.c_str());
CPPUNIT_ASSERT(f->hasID3v2Tag());
CPPUNIT_ASSERT(!f->hasInfoTag());
f->ID3v2Tag()->setTitle("test title");
f->InfoTag()->setTitle("test title");
f->save();
delete f;
f = new RIFF::WAV::File(filename.c_str());
CPPUNIT_ASSERT(f->hasID3v2Tag());
CPPUNIT_ASSERT(f->hasInfoTag());
f->save(RIFF::WAV::File::Info, true);
delete f;
f = new RIFF::WAV::File(filename.c_str());
CPPUNIT_ASSERT(!f->hasID3v2Tag());
CPPUNIT_ASSERT(f->hasInfoTag());
delete f;
}
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestWAV);