Tassilo von Parseval

NAME

Audio::MPC - Perl extension for decoding musepack-encoded files

SYNOPSIS

    use Audio::MPC;
    use Fcntl qw/:seek/;
    
    my $mpc = Audio::MPC->new("file.mpc") or die Audio::MPC->errstr;
    
    open OUT, ">", "file.wav" or die $!;
    seek OUT, WAV_HEADER_SIZE, SEEK_SET;    # leave space for wave-header
    
    my $total;
    while ((my $num_bytes = $mpc->decode(my $buf)) > 0) {
        $total += $num_bytes;
        print OUT $buf;
    }

    # insert wave-header for $total bytes of data
    seek OUT, 0, SEEK_SET;
    print OUT $mpc->wave_header($total);
    close OUT;
        

DESCRIPTION

This module is a wrapper around libmpcdec that allows for decoding musepack-encoded digital audio.

Musepack is a lossy audio-compression format optimized for higher bitrates. See http://www.musepack.net/ for details.

METHODS

new (file)
new (filehandle-ref)
new (Audio::MPC::Reader)

These construct a new Audio::MPC object. The compressed audio-data will either come from file, filehandle-ref or from an Audio::MPC::Reader object (see "Audio::MPC::Reader" further below for details).

Returns the newly created object or undef in case of an error. In this case, check Audio::MPC->errstr.

decode (buffer, [ MPC_LITTLE_ENDIAN || MPC_BIG_ENDIAN ])

Reads data from the audio-stream and puts the decoded PCM-samples into buffer which must not be readonly. The PCM data will be stereo (that is, two channels) and 44.1 kHZ with each sample 16 bit wide.

The optional second argument specifies the byte-order of each sample. If not specified, MPC_LITTLE_ENDIAN is assumed.

Returns the length of buffer, "0 but true" if the stream was succesfully decoded with no more samples left and false in case of an error.

errstr

This class method returns a string telling you what kind of error occured. Currently, only use this method after the constructor new failed to return a new object.

wave_header (length, [ MPC_LITTLE_ENDIAN || MPC_BIG_ENDIAN ])

Returns a wave file header suitable for length bytes of data. The optional second argument specifies the byte-order of the wave file and should match the byte-order you specified in your calls to decode. If ommitted, MPC_LITTLE_ENDIAN is assumed.

See "SYNOPSIS" for an example on how to use the decode and wave_header couple.

seek_sample (sample)

Seeks to the sample-th sample in the audio-stream.

Returns true on success, false otherwise.

seek_seconds (second)

Seeks to the specified position in seconds.

Returns true on success, false otherwise.

length

Returns the length of the audio-stream in seconds.

frequency

Returns the sample frequency of the stream.

channels

Returns number of channels of the stream.

header_pos

Returns byte offset of the header's position in the stream.

version

Returns this stream's version.

bps

Returns bitrate per second of this stream. I have yet to find a file where this method will not return 0.

average_bps

Returns the average bitrate per second of this stream.

frames

Returns the number of frames in this stream.

samples

Returns the number of samples in this stream. Unfortunately, this value cannot be used to precalculate the size of the resulting PCM stream.

max_band

Returns the maximum band-index used in this file (in the range 0 .. 31).

is

Returns true if intensitiy stereo is on. However, nowhere it is explained what intensity stereo is.

ms

Returns true if mid/side stereo is on.

block_size

This appears to be supported only on version 4 throughout 6 streams.

profile

Returns an integer specifying the quality profile of this stream.

profile_name

Returns the name of the quality profiled used for this stream.

gain_title

Returns the replay gain title value.

gain_album

Returns the replay gain album value.

peak_title

Returns the peak title loudness level.

peak_album

Returns the peak album loudness level.

is_gapless

Returns true if this stream is gapless.

last_frame_samples

Returns the number of valid samples in the last frame.

encoder_version

Returns the version of the encoder this stream was encoded with.

encoder

Returns the name of the encoder this was stream was encoded with.

tag_offset

Returns the offset to the file tags.

total_length

Returns the total length of the underlying file.

Audio::MPC::Reader

Aside from a filename or a reference to a filehandle, Audio::MPC->new can also be fed an Audio::MPC::Reader object. Such an object is a collection of callback functions that get called by the decoding engine on the various file operations, such as reading data or seeking in them.

new (filehandle, [ args ])

Constructs a new Audio::MPC::Reader object:

    open my $fh, "file.mpc" or die $!;
    my $reader = Audio::MPC::Reader->new(
        $fh,
        read        => \&my_read,
        seek        => \&my_seek,
        tell        => \&my_tell,
        get_size    => \&my_get_size,
        canseek     => \&canseek,
        userdata    => { }, # arbitrary user data associated with the reader
    );

    my $mpc = Audio::MPC->new( $reader );

filehandle is the only mandatory argument. If any of the other fields (or even all of them) remain unspecified, Audio::MPC::Reader will use its own default handlers.

Each handler receives the Audio::MPC::Reader object as its first argument. To get at the filehandle, you call the fh method on this object. Call userdata to retrieve the user data you associated with this reader.

The purpose and calling-convention for each handler is as follows:

* read (reader, size)

This is called when the decoder wants to acquire more data to decode. reader is the object as returned by Audio::MPC::Reader->new and size denotes the number of bytes that should be read from the stream. The function is expected to return the data read from the underlying filehandle.

    sub my_read {
        my ($reader, $size) = @_;
        read $reader->fh, my ($buf), $size;
        return $buf;
    }
* seek (reader, offset)

offset is the byte position to seek to. The function is expected to return true if the seek operation was succesful:

    sub my_seek {
        my ($reader, $offset) = @_;
        return seek $reader->fh, $offset, SEEK_SET;
    }
* tell (reader)

The function is expected to return the filepointer's current position in the stream:

    sub my_tell {
        my $reader = shift;
        return tell $reader->fh;
    }
* get_size (reader)

The function is expected to return the size of the complete data-stream:

    sub my_get_size {
        my $reader = shift;
        return -s $reader->fh;
    }
* canseek (reader)

The function is expected to return a true value if the underlying filehandle is seekable. However, experiments showed that non-seekable streams cannot be decoded and are therefore not handled at all:

    sub canseek {
        my $reader = shift;
        return seek $reader->fh, 0, SEEK_CUR;   # test if seek succeeded
    }

EXPORT

These symbols are exported by default:

    WAV_HEADER_SIZE
    MPC_LITTLE_ENDIAN
    MPC_BIG_ENDIAN

BUGS AND LIMITATIONS

I am not aware of any outright bugs yet.

A limitation of libmpcdec seems to be that you cannot decode from STDIN as it is not seekable. It should however be possible to craft your own Audio::MPC::Reader object which maintains an internal character buffer as userdata that can be used to fake up a seekable filehandle.

SEE ALSO

http://www.musepack.net/

VERSION

This is version 0.04.

AUTHOR

Tassilo von Parseval, <tassilo.von.parseval@rwth-aachen.de>

libmpcdec support patch by Sylvain Cresto, <scresto@gmail.com>

COPYRIGHT AND LICENSE

Copyright (C) 2005, 2006 by Tassilo von Parseval

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.4 or, at your option, any later version of Perl 5 you may have available.

5 POD Errors

The following errors were encountered while parsing the POD:

Around line 310:

Expected text after =item, not a bullet

Around line 323:

Expected text after =item, not a bullet

Around line 333:

Expected text after =item, not a bullet

Around line 342:

Expected text after =item, not a bullet

Around line 351:

Expected text after =item, not a bullet