Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate a hash of a mp3 file without tag info?

Tags:

c++

id3lib

We need to calculate a hash of a mp3 file to uniquely identify it. The problem is that Traktor software modifies file's tags and there is no chance to change it.

We use id3lib library, so I thought maybe there is some way to get a prepended and appended size of tags of various versions and just read only media content between them to calculate hash of it. I've been searching in id3lib docs and the only thing I have found is ID3_Tag::GetPrependedBytes() and ID3_Tag::GetAppendedBytes(), like that:

const std::size_t prepend = tagOpener.GetPrependedBytes();
const std::size_t append = tagOpener.GetAppendedBytes();
const std::size_t overall = tagOpener.Size();

but they merely return 0.

If that can help, we are developing in C++ along with Qt, so maybe there can be some things to help with the snag.

like image 768
Roman Kruglov Avatar asked Nov 14 '22 00:11

Roman Kruglov


1 Answers

I have solved the issue with the below code. Maybe it will help someone.

/** Return QString hash for the given path */
inline QString GetHash( const QString& filePath )
{
   /// Determine positions of ID3 tags
   ID3_Tag tagOpener( filePath.toLocal8Bit() );
   const std::size_t prepend = tagOpener.GetPrependedBytes();
   const std::size_t append = tagOpener.GetAppendedBytes();

   /// Calculate a hash
   QString hashValueString;
   QFile file( filePath );
   QCryptographicHash hash( QCryptographicHash::Md5 );
   if( file.open(QIODevice::ReadOnly) )
   {
      /// Read only useful media data and skip tags
      const bool seekRes = file.seek( prepend ); // skip prepend tags info
      const qint64 mediaDataSize = file.size() - append - prepend;
      hash.addData( file.read(mediaDataSize) );

      /// Set hash md5 for current file
      hashValueString =  hash.result().toHex().data();
      file.close();
   }

   tagOpener.Clear();
   return hashValueString;
}

It's a solution using Qt and ID3Lib. You can merely use a value returned by the hash.result() code to get a numerical representation.

like image 190
Roman Kruglov Avatar answered Apr 02 '23 05:04

Roman Kruglov