Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File ratings set in Winamp are not parsed correctly #1897

Closed
2 tasks done
msikma opened this issue Nov 2, 2023 · 7 comments · Fixed by #1899 or #1900
Closed
2 tasks done

File ratings set in Winamp are not parsed correctly #1897

msikma opened this issue Nov 2, 2023 · 7 comments · Fixed by #1899 or #1900
Assignees
Labels
bug Bug, will addressed with high priority

Comments

@msikma
Copy link

msikma commented Nov 2, 2023

Is there an existing issue for this?

  • I have searched the existing issues

music-metadata version

8.1.4

JavaScript module eco system

ECMAScript modules (ESM), music-medata ≥ version 8

Current Behavior

When parsing that have a rating set using the Winamp Media Library (tested using version 5.666), the rating does not show up correctly for all filetypes. Specifically, the rating is not found at all for .m4a files (even in the native tags), and an unusual representation is given for .mp3 files.

Given that Webamp is using this library I thought it'd be worth reporting this even though Winamp ratings are probably pretty niche at this point.

I've made a test case that shows the problem and includes a quick and dirty workaround. This repo contains audio files as well.

An MP3 file given a 4 star rating gets the following parsed result for res.common.rating (res being the result of parseFile()):

[ { source: '[email protected]', rating: 0.7677165354330708 } ]

I'm not sure why the value is like that (especially since it's such a weird fraction) but it does seem like you can just divide it by 0.25 and round it to get an integer. Winamp only supports setting ratings 0-5.

An M4A file does not find a rating at all. It seems to be present in the file as "rate" (which is how my workaround can find it). It might be that "rating" is more common?

The FLAC and OPUS files correctly get their 4 star rating reflected in the res.common object as a string value 0-100, so "80" for these files.

Expected Behavior

Both the MP3 and M4A files should report a rating value of "80" in the res.common.rating object returned by parseFile().

Attached audio sample?

  • I have provided sufficient information to reproduce the issue
@msikma msikma added the bug Bug, will addressed with high priority label Nov 2, 2023
@msikma
Copy link
Author

msikma commented Nov 2, 2023

Also, just a note on the float value given to .mp3 files, it seems that the native tag as parsed by this library looks like this:

{
  id: 'POPM',
  value: { email: '[email protected]', rating: 196, counter: 0 }
},

@msikma
Copy link
Author

msikma commented Nov 2, 2023

After talking about it a bit more with The_DoctorO on the Webamp Discord, I added an extra test case to the repo which prints out the native tag values, as parsed by parseFile(), for MP3 files with all valid star ratings. (0 stars, which doesn't have a ratings tag at all, and 1-5.)

This prints out the following:

testcases/testcase-1star.mp3:
  native POPM: {
  id: 'POPM',
  value: { email: '[email protected]', rating: 1, counter: 0 }
}
testcases/testcase-2star.mp3:
  native POPM: {
  id: 'POPM',
  value: { email: '[email protected]', rating: 64, counter: 0 }
}
testcases/testcase-3star.mp3:
  native POPM: {
  id: 'POPM',
  value: { email: '[email protected]', rating: 128, counter: 0 }
}
testcases/testcase-4star.mp3:
  native POPM: {
  id: 'POPM',
  value: { email: '[email protected]', rating: 196, counter: 0 }
}
testcases/testcase-5star.mp3:
  native POPM: {
  id: 'POPM',
  value: { email: '[email protected]', rating: 255, counter: 0 }
}

These rating values are generated by Winamp's in_mp3.dll.

@Borewit Borewit self-assigned this Nov 4, 2023
@Borewit
Copy link
Owner

Borewit commented Nov 4, 2023

Hi @msikma, thanks for your detailed analysis, and nice to hear something from the WebAmp project.

I think there is misunderstanding how the rating is normalized in music-metadata.

I'm not sure why the value is like that (especially since it's such a weird fraction)

Not so weird at all, the stars are weirder in my opinion.
The rating in common is expressed as a fraction. 0.0 is the worst score (0%), 1.0 is the best score (100%).

Note that the lowest rating is defined as 1 in ID3v2.3 POPM.

ID3v2.3 POPM Winamp 5.666 music-metadata common.rating[n]
undefined 0 star undefined
1 1 star 0 / 254 = 0
64 2 stars 63 / 254 = 0.24803149606299213
128 3 stars 127 / 254 = 0.5
196 4 stars 195 / 254 = 0.7677165354330708
255 5 stars 254 / 254 = 1

Using the following formula you can convert the fraction to starts:

const countingStars = Math.round(common.rating[0].rating * 4 + 1);

However this is not necessary, as there the ratingToStars() function has been made available to do this translation.

The following test case process your audio files just fine:

it('4.18 POPM', async () => {

      // Note: all test cases have a 4 star rating set using the Winamp 5.666 Media Library.
      const testCaseFiles = [
        {file: 'testcase-0star.mp3', rating: undefined},
        {file: 'testcase-1star.mp3', rating: 1},
        {file: 'testcase-2star.mp3', rating: 2},
        {file: 'testcase-3star.mp3', rating: 3},
        {file: 'testcase-4star.mp3', rating: 4},
        {file: 'testcase-5star.mp3', rating: 5}
      ];

      for (const testCaseFile of testCaseFiles) {
        const filePath = path.join(samplePath, 'rating', testCaseFile.file);
        const {common, format, native} = await mm.parseFile(filePath);
        if (common.rating === undefined) {
          assert.isUndefined(common.rating, 'Expect no rating property to be present in ' + testCaseFile.file);
        } else {
          assert.isDefined(common.rating, 'Expect rating property to be present in ' + testCaseFile.file);
          console.log(common.rating[0].rating);
          assert.equal(Math.round(common.rating[0].rating * 4 + 1), testCaseFile.rating, 'ID3v2.3 rating conversion' + testCaseFile.file);
          assert.equal(mm.ratingToStars(common.rating[0].rating), testCaseFile.rating, 'ID3v2.3 rating conversion' + testCaseFile.file);
        }
      }
    });

@Borewit
Copy link
Owner

Borewit commented Nov 4, 2023

I need to look into FLAC and OPUS files, as those results are inconsistent. It should be 0.8 and not "80" or 80.

@Borewit
Copy link
Owner

Borewit commented Nov 4, 2023

Both FLAC and OPUS are using the Vorbis Comment tag header.

music-metadata did not recognize the rating tag, as it was expecting a tag: RATING:user with 0.8 representing 80%.

What you received was the raw value, as the "post mapping", did not kick in.

if (tag.id.indexOf('RATING:') === 0) {

On the wiki page is describes a rating convention in line with the way Winamp 5.666 encodes it:

RATING, and tags for ReplayGain information. Ratings are usually mapped as 1-5 stars with 20,40,60,80,100 as the actual string values.

So what I will do is map the RATING tag, and calculate that value accordingly. So an 80% score will be returned as 0.8.

@Borewit
Copy link
Owner

Borewit commented Nov 4, 2023

There is also a wav file in your test case present, I did not find any rating in there, are you sure it is set @msikma?

@msikma
Copy link
Author

msikma commented Nov 7, 2023

Thanks for your reply, very interesting. Metadata tags truly seems like a wild west, so I'm glad this project exists to bring some clarity to how it's all supposed to tie together.

In all honesty, a float from 0-1 sounds much more sensible, seems I misunderstood how it's supposed to work.

Also, you're right, there is no tag in the wav file, it's just there for reference. I believe Winamp doesn't support wav files in the media library. (edit: seems the 5.666 Media Library does support wav files, but they don't work very well and it doesn't set a tag when you use the rating interface.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bug, will addressed with high priority
Projects
None yet
2 participants