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

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.
1 Like

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;

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

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

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

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

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

	m_stID3tag.bNoIDTag = FALSE;

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

	m_stID3tag.szArtist.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:




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…?

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



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

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?

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

Edit: …and done.

1 Like

Hi @t0m - would you be willing to look over my PR? I’m open to any feedback and suggestions if you prefer delegating making changes.

@jrlanglois you should consider rebasing https://github.com/WeAreROLI/JUCE/pull/277 on top of the latest develop branch, that would make less work for the JUCE team.

1 Like

Pretty sure I already have? I’ll double check.

Edit: Hm I must have rebased against a slightly older commit of develop. In any case - done!

1 Like

Bumping this both here and there. Being able to read the tags would be a very nice feature and it looks like this might have been lost in the woodwork.

As to the patch itself, while I love how cleanly it splits out the architecture, I’m not so certain about the backwards compat breakage - though I’m not familiar enough with the culture here to know how acceptable such things are. If that is causing some recalcitrance to merge this patch then maybe leave the old API in place wherever it currently is, mark its usage deprecated, and fill its StringPairArray from the new source?

Yeah, that’s why I made note of it in the original/first message. I fully admit that the approach I took is more idealistic than anything.

That’s fair actually. I’ll tweak sometime over the next few days.

1 Like

Simply bumping this as I’ve updated the branch and PR.

Echoing what Ricky said above, I’m not so certain about the backwards compatibility breakage but with JUCE 6 around the corner it could be worthwhile weighing these changes for the event of merging JUCE 6.