Audio-Scan

 view release on metacpan or  search on metacpan

t/mp3.t  view on Meta::CPAN

    is( ref $tags->{TCON}, 'ARRAY', 'ID3v2.3 multiple TCON is array' );
    is( $tags->{TCON}->[0], 'Live', 'ID3v2.3 multiple TCON value 1 ok' );
    is( $tags->{TCON}->[1], 'Pop', 'ID3v2.3 multiple TCON value 2 ok' );
}

# Multiple TCON genre values in v2.3 numeric form (51)(39)
{
    my $s = Audio::Scan->scan( _f('v2.3-multiple-tcon-numeric.mp3') );
    my $tags = $s->{tags};

    is( ref $tags->{TCON}, 'ARRAY', 'ID3v2.3 multiple numeric TCON is array' );
    is( $tags->{TCON}->[0], 'Techno-Industrial', 'ID3v2.3 multiple numeric TCON value 1 ok' );
    is( $tags->{TCON}->[1], 'Noise', 'ID3v2.3 multiple numeric TCON value 2 ok' );
}

# Multiple TCON genre values in v2.3 with text (55)(Text)
{
    my $s = Audio::Scan->scan( _f('v2.3-multiple-tcon-text.mp3') );
    my $tags = $s->{tags};

    is( ref $tags->{TCON}, 'ARRAY', 'ID3v2.3 multiple numeric+text TCON is array' );
    is( $tags->{TCON}->[0], 'Dream', 'ID3v2.3 multiple numeric+text TCON value 1 ok' );
    is( $tags->{TCON}->[1], 'Text', 'ID3v2.3 multiple numeric+text TCON value 2 ok' );
}

# Multiple TCON genre values in v2.3 with RX/CR special keywords
{
    my $s = Audio::Scan->scan( _f('v2.3-multiple-tcon-rx-cr.mp3') );
    my $tags = $s->{tags};

    is( ref $tags->{TCON}, 'ARRAY', 'ID3v2.3 multiple RX/CR TCON is array' );
    is( $tags->{TCON}->[0], 'Remix', 'ID3v2.3 multiple RX/CR TCON value 1 ok' );
    is( $tags->{TCON}->[1], 'Cover', 'ID3v2.3 multiple RX/CR TCON value 2 ok' );
}

# Bug 15197, MPEG-2 Layer 3 bitrate calculation
{
    my $s = Audio::Scan->scan( _f('v2.3-mp2l3-64k-22khz.mp3') );

    my $info = $s->{info};

    is( $info->{bitrate}, 64000, 'MPEG-2 Layer 3 bitrate ok' );
    is( $info->{samplerate}, 22050, 'MPEG-2 Layer 3 sample rate ok' );
    is( $info->{song_length_ms}, 364, 'MPEG-2 Layer 3 duration ok' );
}

# RGAD frame parsing
{
    my $s = Audio::Scan->scan( _f('v2.3-rgad.mp3') );

    my $tags = $s->{tags};

    is( ref $tags->{RGAD}, 'HASH', 'RGAD frame is a hash' );
    is( $tags->{RGAD}->{peak}, '0.999020', 'RGAD peak ok' );
    is( $tags->{RGAD}->{track_originator}, 3, 'RGAD track originator ok' );
    is( $tags->{RGAD}->{track_gain}, '-5.700000 dB', 'RGAD track gain ok' );
    is( $tags->{RGAD}->{album_originator}, 3, 'RGAD album originator ok' );
    is( $tags->{RGAD}->{album_gain}, '-5.600000 dB', 'RGAD album gain ok' );
}

# v2.4 per-frame unsynchronisation
{
    my $s = Audio::Scan->scan( _f('v2.4-unsync.mp3') );
    my $tags = $s->{tags};

    is( $tags->{TALB}, 'Album', 'v2.4 unsync TALB ok' );
    is( $tags->{TDRC}, 2009, 'v2.4 unsync TDRC ok' );
    is( $tags->{TIT2}, 'Title', 'v2.4 unsync TIT2 ok' );
    is( $tags->{TPE1}, 'Artist', 'v2.4 unsync TPE1 ok' );
}

# v2.3 whole tag unsynchronisation
{
    my $s = Audio::Scan->scan( _f('v2.3-unsync.mp3') );
    my $tags = $s->{tags};

    is( $tags->{TALB}, 'Hydroponic Garden', 'v2.3 unsync TALB ok' );
    is( $tags->{TCON}, 'Ambient', 'v2.3 unsync TCON ok' );
    is( $tags->{TPE1}, 'Carbon Based Lifeforms', 'v2.3 unsync TPE1 ok' );
    is( $tags->{TPE2}, 'Carbon Based Lifeforms', 'v2.3 unsync TPE2 ok' );
    is( $tags->{TRCK}, 4, 'v2.3 unsync TRCK ok' );
}

# v2.3 with whole tag unsync and APIC artwork. There was a bug where the wrong offset
# was reported for the artwork when in fact it's not possible to provide an offset
# due to potential unsync issues.
# XXX test this with v2.2 unsync
{
    local $ENV{AUDIO_SCAN_NO_ARTWORK} = 1;
    my $s = Audio::Scan->scan( _f('v2.3-unsync-apic-bad-offset.mp3') );
    my $info = $s->{info};
    my $tags = $s->{tags};

    is( $info->{id3_was_unsynced}, 1, 'v2.3 id3_was_unsynced ok' );
    is( $tags->{APIC}->[0], 'image/jpg', 'v2.3 unsync APIC JPEG mime type ok (NO_ARTWORK mode)' );
    is( $tags->{APIC}->[1], 0, 'v2.3 unsync APIC JPEG picture type ok (NO_ARTWORK mode)' );
    is( $tags->{APIC}->[2], '', 'v2.3 unsync APIC JPEG description ok (NO_ARTWORK mode)' );
    is( $tags->{APIC}->[3], 10377, 'v2.3 unsync APIC JPEG length ok (NO_ARTWORK mode)' );
    is( !defined $tags->{APIC}->[4], 1, 'v2.3 unsync APIC JPEG no offset returned (NO_ARTWORK mode)' );
}

# Test file again in normal artwork mode, where it will be correctly unsync'ed
{
    my $s = Audio::Scan->scan( _f('v2.3-unsync-apic-bad-offset.mp3') );
    my $tags = $s->{tags};

    is( length( $tags->{APIC}->[3] ), 10377, 'v2.3 unsync APIC JPEG length ok (normal mode)' );
    is( md5_hex( $tags->{APIC}->[3] ), '4c2fbdab0d4c81d95017896d23e1e391', 'v2.3 unsync APIC JPEG picture data ok (normal mode)' );
}

# v2.3 frame compression
{
    my $s = Audio::Scan->scan( _f('v2.3-compressed-frame.mp3') );
    my $tags = $s->{tags};

    is( $tags->{TIT2}, 'Compressed TIT2 Frame', 'v2.3 compressed frame ok' );
    is( $tags->{TPE1}, 'Artist Name', 'v2.3 frame after compressed frame ok' );
}

# v2.4 frame compression
{
    my $s = Audio::Scan->scan( _f('v2.4-compressed-frame.mp3') );
    my $tags = $s->{tags};

    is( $tags->{TIT2}, 'Compressed TIT2 Frame', 'v2.4 compressed frame ok' );
    is( $tags->{TRCK}, '02/10', 'v2.4 frame after compressed frame ok' );
}

# v2.3 extended header
{
    my $s = Audio::Scan->scan_tags( _f('v2.3-ext-header.mp3') );
    my $tags = $s->{tags};

t/mp3.t  view on Meta::CPAN

    is( $content->[0]->{text}, "Let's talk about time", 'v2.3 SYLT text 1 ok' );
    is( $content->[0]->{timestamp}, 2000, 'v2.3 SYLT timestamp 1 ok' );
    is( $content->[-1]->{text}, '(Repeat)', 'v2.3 SYLT text -1 ok' );
    is( $content->[-1]->{timestamp}, 181000, 'v2.3 SYLT timestamp -1 ok' );
}

# invalid encoding bytes
{
    my $s = Audio::Scan->scan( _f('v2.3-invalid-encoding.mp3') );
    my $tags = $s->{tags};

    ok( !exists $tags->{TRCK}, 'v2.3 invalid encoding ok' );
}

# v2.3 encrypted frame
{
    my $s = Audio::Scan->scan( _f('v2.3-encrypted-frame.mp3') );
    my $tags = $s->{tags};

    ok( !exists $tags->{TIT2}, 'v2.3 encrypted frame is skipped' );
    is( $tags->{TPE1}, 'Artist Name', 'v2.3 frame after encrypted frame is ok' );
}

# v2.3 group id frame
{
    my $s = Audio::Scan->scan( _f('v2.3-group-id.mp3') );
    my $tags = $s->{tags};

    is( $tags->{TIT2}, 'Track Title', 'v2.3 group id frame ok' );
    is( $tags->{TRCK}, '02/10', 'v2.3 frame after group id frame ok' );
}

# v2.4 encrypted frame
{
    my $s = Audio::Scan->scan( _f('v2.4-encrypted-frame.mp3') );
    my $tags = $s->{tags};

    ok( !exists $tags->{TIT2}, 'v2.4 encrypted frame is skipped' );
    is( $tags->{TRCK}, '02/10', 'v2.4 frame after encrypted frame is ok' );
}

# v2.4 group id frame
{
    my $s = Audio::Scan->scan( _f('v2.4-group-id.mp3') );
    my $tags = $s->{tags};

    is( $tags->{TIT2}, 'Track Title', 'v2.4 group id frame ok' );
    is( $tags->{TRCK}, '02/10', 'v2.4 frame after group id frame ok' );
}

# v2.4 with UTF-8 encoded comment with empty null description
{
    my $s = Audio::Scan->scan( _f('v2.4-utf8-null-comment.mp3') );
    my $tags = $s->{tags};

    is( $tags->{COMM}->[0], 'eng', 'v2.4 UTF-8 null comment lang ok' );
    is( $tags->{COMM}->[1], '', 'v2.4 UTF-8 null comment description ok' );
    is( $tags->{COMM}->[2], 'Test 123', 'v2.4 UTF-8 null comment value ok' );
}

# v2.4 with unsynchronized APIC frame, check that the correct length is read
# in both artwork and no-artwork modes
{
    local $ENV{AUDIO_SCAN_NO_ARTWORK} = 1;
    my $s = Audio::Scan->scan( _f('v2.4-apic-unsync.mp3') );
    my $tags = $s->{tags};

    # This is not the actual length but it's OK since we don't unsync in no-artwork mode
    is( $tags->{APIC}->[3], 46240, 'v2.4 APIC unsync no-artwork length ok' );
    is( !defined $tags->{APIC}->[4], 1, 'v2.4 APIC unsync no-artwork has no offset ok' );
}

{
    my $s = Audio::Scan->scan( _f('v2.4-apic-unsync.mp3') );
    my $tags = $s->{tags};

    is( length( $tags->{APIC}->[3] ), 45984, 'v2.4 APIC unsync actual length ok' );
    is( md5_hex( $tags->{APIC}->[3] ), 'e55a67f541dfdae8b4d645396d2c542a', 'v2.4 APIC unsync JPEG data ok' );
}

# v2.4 with empty text frame, a bug would insert the text from the previous frame
{
    my $s = Audio::Scan->scan( _f('v2.4-empty-text.mp3') );
    my $tags = $s->{tags};

    ok ( !exists $tags->{TPE3}, 'v2.4 empty text TPE3 frame not present' );
    is( $tags->{CATALOGNUMBER}, 'DUKE149D', 'v2.4 empty text next frame ok' );
}

# Bug 15992, v2.3 + v1.1 + APEv2 + Lyricsv2
{
    my $s = Audio::Scan->scan( _f('v2.3-apev2-lyricsv2.mp3') );
    my $info = $s->{info};
    my $tags = $s->{tags};

    is( $info->{id3_version}, 'ID3v2.3.0, ID3v1.1', 'v2.3 APEv2+Lyricsv2 id3_version ok' );
    is( $info->{ape_version}, 'APEv2', 'v2.3 APEv2+Lyricsv2 ape_version ok' );
    is( $tags->{TIT2}, 'Fifteen Floors', 'v2.3 APEv2+Lyricsv2 TIT2 ok' );
    is( $tags->{REPLAYGAIN_TRACK_PEAK}, '1.077664', 'v2.3 APEv2+Lyricsv2 REPLAYGAIN_TRACK_PEAK ok' );
}

# Bug 16056, v2.4 + APEv2 with invalid key
{
    # Hide stderr
    no strict 'subs';
    no warnings;
    open OLD_STDERR, '>&', STDERR;
    close STDERR;

    my $s = Audio::Scan->scan( _f('v2.4-ape-invalid-key.mp3') );
    my $tags = $s->{tags};

    is( $tags->{REPLAYGAIN_ALBUM_GAIN}, '-1.720000 dB', 'v2.4 APE invalid key tag read ok' );

    # Restore stderr
    open STDERR, '>&', OLD_STDERR;
}

# Bug 16073, zero-byte frames
{
    my $s = Audio::Scan->scan( _f('v2.3-zero-frame.mp3') );



( run in 2.211 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )