diff options
Diffstat (limited to 'firmware/id3.c')
-rw-r--r-- | firmware/id3.c | 76 |
1 files changed, 54 insertions, 22 deletions
diff --git a/firmware/id3.c b/firmware/id3.c index 184bdb5725..a0dda92eb9 100644 --- a/firmware/id3.c +++ b/firmware/id3.c | |||
@@ -400,8 +400,6 @@ static int parseuser( struct mp3entry* entry, char* tag, int bufferpos ) | |||
400 | int desc_len = strlen(tag); | 400 | int desc_len = strlen(tag); |
401 | int value_len = 0; | 401 | int value_len = 0; |
402 | 402 | ||
403 | /* Note: for ID3v2.4, parse_replaygain will not overwrite replaygain | ||
404 | values already parsed from RVA2 tags */ | ||
405 | if ((tag - entry->id3v2buf + desc_len + 2) < bufferpos) { | 403 | if ((tag - entry->id3v2buf + desc_len + 2) < bufferpos) { |
406 | /* At least part of the value was read, so we can safely try to | 404 | /* At least part of the value was read, so we can safely try to |
407 | * parse it | 405 | * parse it |
@@ -411,37 +409,71 @@ static int parseuser( struct mp3entry* entry, char* tag, int bufferpos ) | |||
411 | bufferpos - (tag - entry->id3v2buf)); | 409 | bufferpos - (tag - entry->id3v2buf)); |
412 | } | 410 | } |
413 | 411 | ||
414 | if (value_len) { | 412 | return tag - entry->id3v2buf + value_len; |
415 | bufferpos = tag - entry->id3v2buf + value_len; | ||
416 | } else { | ||
417 | bufferpos = tag - entry->id3v2buf; | ||
418 | } | ||
419 | |||
420 | return bufferpos; | ||
421 | } | 413 | } |
422 | 414 | ||
423 | /* parse RVA2 binary data and convert to replaygain information. */ | 415 | /* parse RVA2 binary data and convert to replaygain information. */ |
424 | static int parserva2( struct mp3entry* entry, char* tag, int bufferpos ) | 416 | static int parserva2( struct mp3entry* entry, char* tag, int bufferpos ) |
425 | { | 417 | { |
426 | char* value = NULL; | ||
427 | int desc_len = strlen(tag); | 418 | int desc_len = strlen(tag); |
419 | int end_pos = tag - entry->id3v2buf + desc_len + 5; | ||
428 | int value_len = 0; | 420 | int value_len = 0; |
421 | unsigned char* value = tag + desc_len + 1; | ||
429 | 422 | ||
430 | /* Only parse RVA2 replaygain tags if tag version == 2.4 */ | 423 | /* Only parse RVA2 replaygain tags if tag version == 2.4 and channel |
431 | if (entry->id3version == ID3_VER_2_4 && | 424 | * type is master volume. |
432 | (tag - entry->id3v2buf + desc_len + 2) < bufferpos) { | 425 | */ |
433 | value = tag + desc_len + 1; | 426 | if (entry->id3version == ID3_VER_2_4 && end_pos < bufferpos |
434 | value_len = parse_replaygain_rva(tag, value, entry, tag, | 427 | && *value++ == 1) { |
435 | bufferpos - (tag - entry->id3v2buf)); | 428 | long gain = 0; |
436 | } | 429 | long peak = 0; |
430 | long peakbits; | ||
431 | long peakbytes; | ||
432 | bool album = false; | ||
433 | |||
434 | /* The RVA2 specification is unclear on some things (id string and | ||
435 | * peak volume), but this matches how Quod Libet use them. | ||
436 | */ | ||
437 | |||
438 | gain = (int16_t) ((value[0] << 8) | value[1]); | ||
439 | value += 2; | ||
440 | peakbits = *value++; | ||
441 | peakbytes = (peakbits + 7) / 8; | ||
442 | |||
443 | /* Only use the topmost 24 bits for peak volume */ | ||
444 | if (peakbytes > 3) { | ||
445 | peakbytes = 3; | ||
446 | } | ||
437 | 447 | ||
438 | if (value_len) { | 448 | /* Make sure the peak bits were read */ |
439 | bufferpos = tag - entry->id3v2buf + value_len; | 449 | if (end_pos + peakbytes < bufferpos) { |
440 | } else { | 450 | long shift = ((8 - (peakbits & 7)) & 7) + (3 - peakbytes) * 8; |
441 | bufferpos = tag - entry->id3v2buf; | 451 | |
452 | for ( ; peakbytes; peakbytes--) { | ||
453 | peak <<= 8; | ||
454 | peak += *value++; | ||
455 | } | ||
456 | |||
457 | peak <<= shift; | ||
458 | |||
459 | if (peakbits > 24) { | ||
460 | peak += *value >> (8 - shift); | ||
461 | } | ||
462 | } | ||
463 | |||
464 | if (strcasecmp(tag, "album") == 0) { | ||
465 | album = true; | ||
466 | } else if (strcasecmp(tag, "track") != 0) { | ||
467 | gain = 0; | ||
468 | } | ||
469 | |||
470 | if (gain) { | ||
471 | value_len = parse_replaygain_int(album, gain, peak * 2, entry, | ||
472 | tag, sizeof(entry->id3v2buf) - (tag - entry->id3v2buf)); | ||
473 | } | ||
442 | } | 474 | } |
443 | 475 | ||
444 | return bufferpos; | 476 | return tag - entry->id3v2buf + value_len; |
445 | } | 477 | } |
446 | #endif | 478 | #endif |
447 | 479 | ||