Saturday, February 10, 2001

This is MP3::Info.  Two small bugfixes: one with proper return value
for get_mp3tag() special case, and one small, but possibly significant,
fix with /o.

A wrapper module is included so scripts calling MPEG::MP3Info (the
old name) will still work.

This archive can always be obtained from:

    http://sourceforge.net/projects/mp3-info/
    http://www.perl.com/CPAN/authors/id/CNANDOR/
    http://www.perl.com/CPAN/modules/by-module/MP3/

Mac users: The file is a tarred, gzipped file.  Use Stuffit Expander 
or a similar program (like my cpan-mac stuff, also in the CNANDOR
directory) to get at the archive.

Please let me know how well it does(n't) work, and any changes you'd 
like to see.   Thanks to all of the people who have sent me feedback
and ideas.  If something you want still remains unimplemented, let me
know.

#============================================================================

NAME
    MP3::Info - Manipulate / fetch info from MP3 audio files

SYNOPSIS
            #!perl -w
            use MP3::Info;
            my $file = 'Pearls_Before_Swine.mp3';
            set_mp3tag($file, 'Pearls Before Swine', q"77's",
                    'Sticks and Stones', '1990',
                    q"(c) 1990 77's LTD.", 'rock & roll');

            my $tag = get_mp3tag($file) or die "No TAG info";
            $tag->{GENRE} = 'rock';
            set_mp3tag($file, $tag);

            my $info = get_mp3info($file);
            printf "$file length is %d:%d\n", $info->{MM}, $info->{SS};

            my $mp3 = new MP3::Info $file;
            printf "$file length is %s, title is %s\n",
                    $mp3->time, $mp3->title;

DESCRIPTION
    use_winamp_genres()
        Puts WinAmp genres into `@mp3_genres' and `%mp3_genres' (adds 68
        additional genres to the default list of 80). This is a separate
        function because these are non-standard genres, but they are
        included because they are widely used.

        You can import the data structures with one of:

                use MP3::Info qw(:genres);
                use MP3::Info qw(:DEFAULT :genres);
                use MP3::Info qw(:all);

    remove_mp3tag (FILE [, VERSION, BUFFER])
        Can remove ID3v1 or ID3v2 tags. VERSION should be `1' for ID3v1, `2'
        for ID3v2, and `ALL' for both.

        For ID3v1, removes last 128 bytes from file if those last 128 bytes
        begin with the text 'TAG'. File will be 128 bytes shorter.

        For ID3v2, removes ID3v2 tag. Because an ID3v2 tag is at the
        beginning of the file, we rewrite the file after removing the tag
        data. The buffer for rewriting the file is 4MB. BUFFER (in bytes) ca
        change the buffer size.

        Returns the number of bytes removed, or -1 if no tag removed, or
        undef if there is an error.

    set_mp3tag (FILE, TITLE, ARTIST, ALBUM, YEAR, COMMENT, GENRE [,
    TRACKNUM])
    set_mp3tag (FILE, $HASHREF)
        Adds/changes tag information in an MP3 audio file. Will clobber any
        existing information in file.

        Fields are TITLE, ARTIST, ALBUM, YEAR, COMMENT, GENRE. All fields
        have a 30-byte limit, except for YEAR, which has a four-byte limit,
        and GENRE, which is one byte in the file. The GENRE passed in the
        function is a case-insensitive text string representing a genre
        found in `@mp3_genres'.

        Will accept either a list of values, or a hashref of the type
        returned by `get_mp3tag'.

        If TRACKNUM is present (for ID3v1.1), then the COMMENT field can
        only be 28 bytes.

        ID3v2 support may come eventually.

    get_mp3tag (FILE [, VERSION, RAW_V2])
        Returns hash reference containing tag information in MP3 file. Same
        info as described in `set_mp3tag'.

        If VERSION is `1', the information is taken from the ID3v1 tag (if
        present). If VERSION is `2', the information is taken from the ID3v2
        tag (if present). If VERSION is not supplied, the ID3v1 tag is read
        if present, and then, if present, the ID3v2 tag information will
        override any existing ID3v1 tag info.

        If the ID3v2 version is older than ID3v2.2.0, it will not be read
        (and a warning will be issued if -w is on).

        If RAW_V2 is false or not supplied and VERSION is `2', only the tags
        corresponding to ID3v1 tags are returned, with the same keys in the
        returned hashref.

        If RAW_V2 is true and VERSION is `2', `get_mp3tag' will return a
        hash of tag four-character IDs and their data. Tag IDs and their
        meanings are in the global hash (not exported) `%v2_tag_names'.

                my $tag = get_mp3tag('mysong.mp3', 2, 1);   # ID3v2, raw ID3v2 tags
                for (keys %$tag) {
                        printf "%s => %s\n", $MP3::Info::v2_tag_names{$_}, $tag->{$_};
                }

    get_mp3info (FILE)
        Returns hash reference containing file information for MP3 file.
        This data cannot be changed. Returned data:

                VERSION         MPEG audio version (1, 2, 2.5)
                LAYER           MPEG layer description (1, 2, 3)
                STEREO          boolean for audio is in stereo

                VBR             boolean for variable bitrate
                BITRATE         bitrate in kbps (average for VBR files)
                FREQUENCY       frequency in kHz
                SIZE            bytes in audio stream

                SECS            total seconds
                MM              minutes
                SS              leftover seconds
                MS              leftover milliseconds
                TIME            time in MM:SS

                COPYRIGHT       boolean for audio is copyrighted
                PADDING         boolean for MP3 frames are padded
                MODE            channel mode (0 = stereo, 1 = joint stereo,
                                2 = dual channel, 3 = single channel)
                FRAMES          approximate number of frames
                FRAME_LENGTH    approximate length of a frame
                VBR_SCALE       VBR scale from VBR header

TROUBLESHOOTING
    If you find a bug, please send me a patch. If you cannot figure out why
    it does not work for you, please put the MP3 file in a place where I can
    get it (preferably via FTP) and send me mail regarding where I can get
    the file, with a detailed description of the problem.

    If I download the file, after debugging the problem I will not keep the
    MP3 file if it is not legal for me to have it. Just let me know if it is
    legal for me ot keep it or not.

TODO
    ID3v2 Support
        First go at adding support for reading ID3v2 tags. Still need to do
        more, such as using Compress::Zlib to decompress compressed tags.
        But until I see this in use more, I won't bother. I might not be
        able to support Unicode at all, until Perl supports 16-bit Unicode.
        If something does not work properly with reading, follow the
        instructions above for troubleshooting.

        I think I might just use Matt DiMeo's MPEG::ID3v2Tag; the problem is
        that right now it requires 5.005, and MacPerl uses 5.004 (for now).

    Get data from scalar
        Instead of passing a file spec or filehandle, pass the data itself.
        Would take some work, converting the seeks, etc.

    Padding bit ?
        Do something with padding bit.

    ID3v2.4.0
        It's the new standard. There are no specific plans to update to
        2.4.0. I'd like it to be done, but there is no pressing need, and I
        don't really have the time right now. Patches welcome! :-)

    Test suite
        Test suite could use a bit of an overhaul and update.

HISTORY
    v0.91, Saturday, February 10, 2001
        Fix dumb bug with /o. (David Reuteler)

        Fix bug where C<get_mp3tag> would return an empty hashref instead
        of undef if ID3v1 tag is asked for, and there is no ID3v1 tag, but
        there is an ID3v2 tag.  (Stuart)

    v0.90, Sunday, January 14, 2001
        Added experimental OOP support for getting and setting data; doesn't
        work for removing tags.

        Made all functions optionally accept filehandle in place of
        filename.

        Remove all croaks/dies and replace with simple returns or
        carps/warns. (Jeffrey Sumler)

        Fix various input data problems, bad warnings, division by zero,
        etc.

        Undef `$/' in set_mp3tag() so caller can't mess up the print.

        Fix bitrate if ID == 0 and VBR. (Kyle Farrell, Per Bolmstedt)

        Split off _get_info() from get_mp3info(), so, eventually,
        programmers can access that functionality without passing in a file
        or filehandle. Not supported yet, but available for playing.

        Added total frames, leftover milliseconds, and formatted time.

        Fixed sample frequency for MPEG 2.5 files (perhaps not including
        VBR, though ... see bug above).

        Add in some additional genres. (Peter Marschall)

        Added ID3v2 tag removal. (Ronan Waide) NOTE: this is DANGEROUS. It
        is tested, but needs more testing. The file is rewritten entirely.
        Lots of data moving around.

        Added ID3v2.2.0 tag reading. (Ronan Waide, Kee Hinckley)

        Changed ID3v2 tag recognition to only match [A-Z0-9] instead of \w.
        (Christoph Oberauer)

    v0.80, Monday, March 6, 2000
        Better stripping of bad data (after nulls) in ID3 tags (Dave
        O'Neill)

        Fixed VERSION in get_mp3info to properly return 2 when appropriate.
        (Bogdan Surdu)

        Added VBR support. Average bitrate is returned as BITRATE, and
        minutes and seconds (MM and SS) should be accurate. (Andy Waite for
        pointer to MP3Ext)

        Made time calculation better overall.

        Made MP3 header validation routines more comprehensive. (Matthew
        Sachs for pointer to xmms source)

        Changed name to MP3::Info (with wrapper still named MP3::Info).

    v0.71, Thursday, July 8, 1999
        Several fixes to ID3v2 support unpack unsigned instead of signed,
        don't bail out after 4096-byte offsets on long ID3v2 headers. Thanks
        much to Matthew Sachs.

    v0.70, Saturday, July 3, 1999
        Added preliminary ID3v2 reading support in `get_mp3tag'. Thanks much
        to Tom Brown.

    v0.64, Thursday, July 1, 1999
        Found bug in checking TRACKNUM parameter, used \d instead of \d+.
        Only gives spurious warnings, doesn't affect anything else.

        Cleaned up a bit, prepare for impending ID3v2 support.

        NOTE: truncate() broken in some builds of ActivePerl (517, maybe
        others). No changes to module to fix problem. (Brian Goodwin)

    v0.63, Friday, April 30, 1999
        Added ID3v1.1 support. (Trond Michelsen, Pass F. B. Travis)

        Added 255 (\xFF) as default genre. (Andrew Phillips)

        I think I fixed bug relating to spaces in ID3v2 headers. (Tom Brown)

    v0.62, Sunday, March 7, 1999
        Doc updates.

        Fix small unnoticable bug where ID3v2 offset is tag size plus 10,
        not just tag size.

        Not publickly released.

    v0.61, Monday, March 1, 1999
        Fixed problem of not removing nulls on return from `get_mp3tag' (was
        using spaces for padding before ... now trailing whitespace and all
        nulls are removed before returning tag info).

        Made tests more extensive (more for my own sanity when making all
        these changes than to make sure it works on other platforms and
        machines :).

    v0.60, Sunday, February 28, 1999
        Cleaned up a lot of stuff, added more comments, made `get_mp3info'
        much faster and much more reliable, and added recognition of ID3v2
        headers. (Tom Brown)

    v0.52, Sunday, February 21, 1999
        Fixed problem in `get_mp3tag' that changed value of `$_' in caller
        (Todd Hanneken).

    v0.51, Saturday, February 20, 1999
        Fixed problem with `%winamp_genres' having the wrong numbers
        (Matthew Sachs).

    v0.50, Friday, February 19, 1999
        Added `remove_mp3tag'. Addeed VERSION to the hash returned by
        `get_mp3info', and fixed a bug where STEREO was not being set
        correctly.

        Export all genre data structures on request. Added
        `use_winamp_genres' to use WinAmp genres. (Roland Steinbach)

        Added a `$MPEG::MP3Info::try_harder' (`$MP3::Info::try_harder')
        variable that will try harder to find the MP3 header in a file.
        False by default. Can take a long time to fail, but should find most
        headers at any offsets if set to true.

        Thanks to Matthew Sachs for his input and fixes, and for mp3tools.

    v0.20, Saturday, October 17, 1998
        Changed name from `MPEG::MP3Tag' to `MPEG::MP3Info', because it does
        more than just TAG stuff now.

        Made header stuff even more reliable. Lots of help and testing from
        Meng Weng Wong again. :-)

    v0.13, Thursday, October 8, 1998
        Had some problems with header verification, got some code from
        Predrag Supurovic with his mpgtools. Great stuff. Also did some
        looping to find a header if it is not in the "right" place. I did
        what I think it is a smart way to do it, since some files have the
        header as far down as 2 kbytes into the file. First, I look at
        position 0, then at position 36 (a position where I have found many
        headers), then I start at 0 again and jump in 128-byte chunks. Once
        I do that a bunch of times, I go back at the beginning and try at 0
        and go ahead in 1-byte chunks for a bunch more times.

        If you have an MP3 that has the header begin at an odd place like
        byte 761, then I suggest you strip out the junk before the header
        begins. :-)

    v0.12, Friday, October 2, 1998
        Added `get_mp3info'. Thanks again to mp3tool source from Johann
        Lindvall, because I basically stole it straight (after converting it
        from C to Perl, of course).

        I did everything I could to find the header info, but if anyone has
        valid MP3 files that are not recognized, or has suggestions for
        improvement of the algorithms, let me know.

    v0.04, Tuesday, September 29, 1998
        Changed a few things, replaced a regex with an `unpack'. (Meng Weng
        Wong)

    v0.03, Tuesday, September 8, 1998
        First public release.

THANKS
    Edward Allen <allenej@c51844-a.spokn1.wa.home.com>, Vittorio Bertola
    <v.bertola@vitaminic.com>, Michael Blakeley <mike@blakeley.com>, Per
    Bolmstedt <tomten@kol14.com>, Tony Bowden <tony@tmtm.com>, Tom Brown
    <thecap@usa.net>, Sergio Camarena <scamarena@users.sourceforge.net>,
    Chris Dawson <cdawson@webiphany.com>, Luke Drumm <lukedrumm@mypad.com>,
    Kyle Farrell <kyle@cantametrix.com>, Brian Goodwin <brian@fuddmain.com>,
    Todd Hanneken <thanneken@hds.harvard.edu>, Kee Hinckley
    <nazgul@somewhere.com>, Roman Hodek
    <Roman.Hodek@informatik.uni-erlangen.de>, Peter Kovacs
    <kovacsp@egr.uri.edu>, Johann Lindvall, Peter Marschall
    <peter.marschall@mayn.de>, Trond Michelsen <mike@crusaders.no>, Dave
    O'Neill <dave@nexus.carleton.ca>, Christoph Oberauer
    <christoph.oberauer@sbg.ac.at>, Andrew Phillips <asp@wasteland.org>,
    Matthew Sachs <matthewg@zevils.com>, Hermann Schwaerzler
    <Hermann.Schwaerzler@uibk.ac.at>, Chris Sidi <sidi@angband.org>, Roland
    Steinbach <roland@support-system.com>, Jeffery Sumler
    <jsumler@mediaone.net>, Predrag Supurovic <mpgtools@dv.co.yu>, Bogdan
    Surdu <tim@go.ro>, Pass F. B. Travis <pftravis@bellsouth.net>, Tobias
    Wagener <tobias@wagener.nu>, Ronan Waide <waider@stepstone.ie>, Andy
    Waite <andy@mailroute.com>, Ken Williams <ken@forum.swarthmore.edu>,
    Meng Weng Wong <mengwong@pobox.com>.

AUTHOR AND COPYRIGHT
    Chris Nandor <pudge@pobox.com>, http://pudge.net/

    Copyright (c) 1998-2001 Chris Nandor. All rights reserved. This program
    is free software; you can redistribute it and/or modify it under the
    terms of the Artistic License, distributed with Perl.

SEE ALSO
    SourceForge Page
                http://sourceforge.net/projects/mp3-info/

    mp3tools
                http://www.zevils.com/linux/mp3tools/

    mpgtools
                http://www.dv.co.yu/mpgscript/mpgtools.htm
                http://www.dv.co.yu/mpgscript/mpeghdr.htm

    mp3tool
                http://www.dtek.chalmers.se/~d2linjo/mp3/mp3tool.html

    ID3v2
                http://www.id3.org/

    Xing Variable Bitrate
                http://www.xingtech.com/support/partner_developer/mp3/vbr_sdk/

    MP3Ext
                http://rupert.informatik.uni-stuttgart.de/~mutschml/MP3ext/

    Xmms
                http://www.xmms.org/

VERSION
    v0.91, Saturday, February 10, 2001

#============================================================================
