Pull Request: Added initial support for reading ID3 and Vorbis Comments


#1

I’ve added a preliminary pull request to support Vorbis Comments and (the painstaking amount of) ID3 tags.


What has been done in this PR

  • Resaved the JUCE Demo, and added OGG, FLAC and WMA reading support to it.
  • Added a namespace to encapsulate Vorbis Comments and a tiny bit of functionality along with it.
  • Added a namespace to encapsulate ID3 tags and a tiny bit of functionality along with it.
  • Fixed a bug when enabling both OGG and FLAC: when trying to playback an OGG file, FlacAudioFormat was getting used to sample waveforms. Fixed by resorting the OGG/FLAC format order in the audio format manager.
  • Added support for metadata reading in FLAC.
  • Tidied up some data processing in FLAC.
  • Removed unsupported sample rates in FlacAudioFormat (see https://xiph.org/flac/format.html#frame_header )

What needs to be added

  • MP3 ID3 tag support. (Can’t seem to find any details on this…)
  • AIFF ID3 tag support. (Can’t seem to find any details on this…)
  • Writing the tags, and testing the results, using all supported codecs.
    • Unit tests?
  • A Component that lists out all of an audio file’s metadata should be added to the JUCE Demo. Would be handy…

Things broken/questionable

  • I removed the existing OGG metadata keys… this breaks compatibility with JUCE, but none of those tags were official. Probably worthwhile putting them back in my PR - easily done - just making that change visible here.

#2

ID3v1 or ID3v2 ?

v1 is simply appended at the end of the file…

Some old/historic MFC code I have lying around…

if (!m_MP3.Open(szPath, CFile::modeReadWrite|CFile::shareDenyNone, &e))
	return FALSE;

dwValue = m_MP3.GetLength() - 128L;

m_MP3.Seek(dwValue, CFile::begin);

m_MP3.Read(szBuff, 3);
szBuff[3] = '\0';

szTemp = szBuff;

if (szTemp == "TAG")
	{
	// Read TAG

	memset(szBuff, 0, 31);
	m_MP3.Read(szBuff, 30);
	m_stID3tag.szTitle = szBuff;
	m_stID3tag.szTitle.TrimRight();

	memset(szBuff, 0, 31);
	m_MP3.Read(szBuff, 30);
	m_stID3tag.szArtist = szBuff;
	m_stID3tag.szArtist.TrimRight();

	memset(szBuff, 0, 31);
	m_MP3.Read(szBuff, 30);
	m_stID3tag.szAlbum = szBuff;
	m_stID3tag.szAlbum.TrimRight();

	memset(szBuff, 0, 31);
	m_MP3.Read(szBuff, 4);
	m_stID3tag.szYear = szBuff;
	m_stID3tag.szYear.TrimRight();

	memset(szBuff, 0, 31);
	m_MP3.Read(szBuff, 30);
	m_stID3tag.szComment = szBuff;
	m_stID3tag.szComment.TrimRight();

	memset(szBuff, 0, 31);
	m_MP3.Read(szBuff, 1);
	m_stID3tag.chGenre = szBuff[0];

	m_stID3tag.bNoIDTag = FALSE;

	m_MP3.Seek(dwValue, CFile::begin);
	}
else
	{
	// No TAG in this file

	m_stID3tag.szAlbum.Empty();
	m_stID3tag.szArtist.Empty() ;
	m_stID3tag.szTitle.Empty();
	m_stID3tag.szYear.Empty();
	m_stID3tag.szComment.Empty();
	
	m_stID3tag.chGenre = -1;
	
	m_stID3tag.bNoIDTag = TRUE;

	m_MP3.Seek(m_MP3.GetLength(), CFile::begin);
	}

Genre is an integer… see http://www.dreamincode.net/forums/topic/47881-reading-id3-tags-from-mp3/

ID3v2 is defined in the spec:

http://id3.org/id3guide

Cheers,

Rail


#3

My question is all-encompassing. :slight_smile: Simply, I’m seeking the blatantly obvious: any indicators where the metadata is supposed to exist, and what each piece’s size would be.

By the looks of your shared code, the expectation for the v1 strings is 30 elements each? Do they have a guaranteed encoding - ASCII, UTF8…?


#4

It’s been a long while since I wrote that… and it was merely for some quick example code I posted… I believe it’s ASCII

Cheers,

Rail


#5

Ah, and here I was trying to avoid Wiki which seems to have worked against me - looks like that page has juicy details… thanks!


#6

It looks like you github pull request has changes in all the images, project files etc. There is a lot of noise, removing some changes might make it easier for others to review?

EDIT: Maybe that is just refreshing the projucer projects? Maybe good as a separate commit?


#7

Sure yeah, I can split that out in a separate commit. It’s from resaving the JUCE Demo as you said.

Edit: …and done.