summaryrefslogtreecommitdiff
path: root/firmware/id3.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/id3.c')
-rw-r--r--firmware/id3.c76
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. */
424static int parserva2( struct mp3entry* entry, char* tag, int bufferpos ) 416static 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