Skip to content

Commit 4daa660

Browse files
committed
Add support for ID3v2.4 GRP1 tag.
Fixes issue#7.
1 parent 1fa3847 commit 4daa660

File tree

6 files changed

+70
-64
lines changed

6 files changed

+70
-64
lines changed

Changes

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
Revision history for Audio::Scan
22

3-
1.11 2025-09-12
3+
1.11 2025-09-18
44
- fix compatibility with Perl 5.42
5+
- mp3: fix odd reported bitrates for certain files.
6+
- added support for ID3v2.4 GRP1 frame.
57

68
1.10 2024-02-29
79
- ogg/flac: add support for ogf file format.

include/id3.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,4 @@ void _id3_skip(id3info *id3, uint32_t size);
136136
char const * _id3_genre_index(unsigned int index);
137137
char const * _id3_genre_name(char const *string);
138138
static id3_compat const * _id3_compat_lookup(register char const *, register unsigned int);
139-
static id3_frametype const * _id3_frametype_lookup(register char const *, register unsigned int);
139+
const struct id3_frametype * _id3_frametype_lookup(register const char *, register size_t);

src/id3_frametype.c

Lines changed: 54 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* C code produced by gperf version 3.0.4 */
1+
/* ANSI-C code produced by gperf version 3.1 */
22
/* Command-line: gperf -tCcTonDE -K id -N _id3_frametype_lookup -s -3 -k '*' id3_frametype.gperf */
33

44
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
@@ -25,7 +25,7 @@
2525
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
2626
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
2727
/* The character set is not based on ISO-646. */
28-
error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu[email protected]>."
28+
#error "gperf generated tables don't work with this execution character set. Please report a bug to <[email protected]>."
2929
#endif
3030

3131
#line 1 "id3_frametype.gperf"
@@ -284,7 +284,7 @@ FRAMETYPE(url, url, "Unknown URL link frame");
284284
FRAMETYPE(experimental, unknown, "Experimental frame");
285285
FRAMETYPE(unknown, unknown, "Unknown frame");
286286
FRAMETYPE(obsolete, unknown, "Obsolete frame");
287-
/* maximum key range = 149, duplicates = 0 */
287+
/* maximum key range = 171, duplicates = 0 */
288288

289289
#ifdef __GNUC__
290290
__inline
@@ -294,60 +294,50 @@ inline
294294
#endif
295295
#endif
296296
static unsigned int
297-
frametype_hash (str, len)
298-
register const char *str;
299-
register unsigned int len;
297+
frametype_hash (register const char *str, register size_t len)
300298
{
301299
static const unsigned char asso_values[] =
302300
{
303-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
304-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
305-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
306-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
307-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
308-
47, 4, 13, 34, 156, 156, 156, 156, 156, 156,
309-
156, 156, 156, 156, 156, 31, 63, 3, 15, 3,
310-
24, 25, 10, 52, 69, 5, 23, 30, 1, 5,
301+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
302+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
303+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
304+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
305+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
306+
69, 4, 13, 47, 178, 178, 178, 178, 178, 178,
307+
178, 178, 178, 178, 178, 31, 63, 3, 15, 3,
308+
24, 25, 10, 52, 74, 5, 23, 30, 1, 5,
311309
10, 62, 20, 0, 28, 28, 22, 19, 25, 62,
312-
10, 156, 156, 156, 156, 156, 156, 156, 156, 156,
313-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
314-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
315-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
316-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
317-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
318-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
319-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
320-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
321-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
322-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
323-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
324-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
325-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
326-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
327-
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
328-
156, 156, 156, 156, 156, 156, 156
310+
10, 178, 178, 178, 178, 178, 178, 178, 178, 178,
311+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
312+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
313+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
314+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
315+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
316+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
317+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
318+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
319+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
320+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
321+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
322+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
323+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
324+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
325+
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
326+
178, 178, 178, 178, 178, 178, 178
329327
};
330328
return asso_values[(unsigned char)str[3]+1] + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[1]] + asso_values[(unsigned char)str[0]];
331329
}
332330

333-
#ifdef __GNUC__
334-
__inline
335-
#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
336-
__attribute__ ((__gnu_inline__))
337-
#endif
338-
#endif
339331
const struct id3_frametype *
340-
_id3_frametype_lookup (str, len)
341-
register const char *str;
342-
register unsigned int len;
332+
_id3_frametype_lookup (register const char *str, register size_t len)
343333
{
344334
enum
345335
{
346-
TOTAL_KEYWORDS = 85,
336+
TOTAL_KEYWORDS = 86,
347337
MIN_WORD_LENGTH = 4,
348338
MAX_WORD_LENGTH = 4,
349339
MIN_HASH_VALUE = 7,
350-
MAX_HASH_VALUE = 155
340+
MAX_HASH_VALUE = 177
351341
};
352342

353343
static const struct id3_frametype wordlist[] =
@@ -438,8 +428,6 @@ _id3_frametype_lookup (str, len)
438428
{"TMOO", FRAME(text), "Mood"},
439429
#line 324 "id3_frametype.gperf"
440430
{"TRCK", FRAME(text), "Track number/position in set"},
441-
#line 320 "id3_frametype.gperf"
442-
{"TPE4", FRAME(text), "Interpreted, remixed, or otherwise modified by"},
443431
#line 294 "id3_frametype.gperf"
444432
{"TDLY", FRAME(text), "Playlist delay"},
445433
#line 282 "id3_frametype.gperf"
@@ -462,8 +450,8 @@ _id3_frametype_lookup (str, len)
462450
{"TALB", FRAME(text), "Album/movie/show title"},
463451
#line 307 "id3_frametype.gperf"
464452
{"TLAN", FRAME(text), "Language(s)"},
465-
#line 317 "id3_frametype.gperf"
466-
{"TPE1", FRAME(text), "Lead performer(s)/soloist(s)"},
453+
#line 320 "id3_frametype.gperf"
454+
{"TPE4", FRAME(text), "Interpreted, remixed, or otherwise modified by"},
467455
#line 338 "id3_frametype.gperf"
468456
{"WCOP", FRAME(url), "Copyright/legal information"},
469457
#line 309 "id3_frametype.gperf"
@@ -496,24 +484,28 @@ _id3_frametype_lookup (str, len)
496484
{"MLLT", FRAME(MLLT), "MPEG location lookup table"},
497485
#line 287 "id3_frametype.gperf"
498486
{"SYTC", FRAME(SYTC), "Synchronised tempo codes"},
499-
#line 350 "id3_frametype.gperf"
487+
#line 351 "id3_frametype.gperf"
500488
{"ZOBS", FRAME(ZOBS), "Obsolete frame"},
501489
#line 334 "id3_frametype.gperf"
502490
{"UFID", FRAME(UFID), "Unique file identifier"},
503491
#line 264 "id3_frametype.gperf"
504492
{"APIC", FRAME(APIC), "Attached picture"},
505-
#line 265 "id3_frametype.gperf"
506-
{"ASPI", FRAME(ASPI), "Audio seek point index"},
493+
#line 317 "id3_frametype.gperf"
494+
{"TPE1", FRAME(text), "Lead performer(s)/soloist(s)"},
507495
#line 304 "id3_frametype.gperf"
508496
{"TIT2", FRAME(text), "Title/songname/content description"},
509497
#line 286 "id3_frametype.gperf"
510498
{"SYLT", FRAME(SYLT), "Synchronised lyric/text"},
511-
#line 274 "id3_frametype.gperf"
512-
{"MCDI", FRAME(MCDI), "Music CD identifier"},
499+
#line 265 "id3_frametype.gperf"
500+
{"ASPI", FRAME(ASPI), "Audio seek point index"},
513501
#line 302 "id3_frametype.gperf"
514502
{"TIPL", FRAME(text), "Involved people list"},
515503
#line 305 "id3_frametype.gperf"
516504
{"TIT3", FRAME(text), "Subtitle/description refinement"},
505+
#line 274 "id3_frametype.gperf"
506+
{"MCDI", FRAME(MCDI), "Music CD identifier"},
507+
#line 347 "id3_frametype.gperf"
508+
{"GRP1", FRAME(text), "Content group description"},
517509
#line 345 "id3_frametype.gperf"
518510
{"WXXX", FRAME(WXXX), "User defined URL link frame"},
519511
#line 281 "id3_frametype.gperf"
@@ -524,27 +516,28 @@ _id3_frametype_lookup (str, len)
524516
{"TIT1", FRAME(text), "Content group description"}
525517
};
526518

527-
static const short lookup[] =
519+
static const signed char lookup[] =
528520
{
529521
-1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1,
530522
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1,
531523
2, 3, -1, 4, -1, -1, -1, -1, 5, 6, 7, 8, -1, 9,
532524
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
533525
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
534-
38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
535-
52, 53, -1, 54, 55, 56, -1, 57, 58, 59, 60, 61, 62, 63,
536-
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, -1, 75, -1,
537-
76, 77, -1, -1, -1, 78, -1, -1, 79, 80, -1, -1, -1, -1,
538-
-1, -1, -1, -1, -1, 81, -1, -1, -1, -1, 82, -1, -1, -1,
539-
83, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
540-
-1, 84
526+
38, 39, 40, 41, 42, -1, 43, 44, 45, 46, 47, 48, 49, 50,
527+
51, 52, -1, 53, 54, 55, -1, 56, 57, 58, 59, 60, 61, 62,
528+
63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, 74, -1,
529+
75, 76, -1, 77, -1, -1, -1, -1, 78, 79, 80, -1, 81, -1,
530+
-1, -1, -1, -1, -1, 82, -1, -1, -1, -1, 83, -1, -1, -1,
531+
84, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
532+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
533+
-1, -1, -1, -1, -1, -1, -1, -1, -1, 85
541534
};
542535

543536
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
544537
{
545-
register int key = frametype_hash (str, len);
538+
register unsigned int key = frametype_hash (str, len);
546539

547-
if (key <= MAX_HASH_VALUE && key >= 0)
540+
if (key <= MAX_HASH_VALUE)
548541
{
549542
register int index = lookup[key];
550543

src/id3_frametype.gperf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ WPAY, FRAME(url), "Payment"
344344
WPUB, FRAME(url), "Publishers official webpage"
345345
WXXX, FRAME(WXXX), "User defined URL link frame"
346346
XSOP, FRAME(text), "Performer sort order (v2.3)"
347+
GRP1, FRAME(text), "Content group description"
347348
#
348349
# Special frames
349350
#

t/mp3.t

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use strict;
33
use Digest::MD5 qw(md5_hex);
44
use File::Spec::Functions;
55
use FindBin ();
6-
use Test::More tests => 399;
6+
use Test::More tests => 400;
77
use Test::Warn;
88

99
use Audio::Scan;
@@ -508,6 +508,16 @@ eval {
508508
# XXX: 2 WOAR frames
509509
}
510510

511+
# ID3v2.4 UTF-8 with GRP1
512+
{
513+
my $s = Audio::Scan->scan_tags( _f('v2.4-utf8-grp1.mp3') );
514+
515+
my $tags = $s->{tags};
516+
517+
is( $tags->{GRP1}, 'Last Embrace', 'ID3v2.4 GRP1 ok' );
518+
}
519+
520+
511521
# ID3v2.4 with negative RVA2
512522
{
513523
my $s = Audio::Scan->scan_tags( _f('v2.4-rva2-neg.mp3') );

t/mp3/v2.4-utf8-grp1.mp3

4 KB
Binary file not shown.

0 commit comments

Comments
 (0)