Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > by-pkgid > 1f8d0d1e253a3f5aed78d2096c2df11f > files > 52

audiere-debug-1.9.4-7mdv2009.0.i586.rpm

// Speex helper library
// Copyright (C) 2002-2003 Janne Hyvärinen
// Parts from speexdec (C) Jean Marc-Valin
//
// Changes:
//  (2003-04-12): Now reports length as double and seek position is specified as double
//  (2002-12-25): Added tag reading, fixed seeking bugs, some other minor changes
//  (2002-11-19): Initial version

#ifndef _speexfile_h
#define _speexfile_h

//#define SL_READER   // uncomment to provide own reader

extern "C" {
#include <speex/speex.h>
#include <speex/speex_header.h>
#include <speex/speex_stereo.h>
#include <speex/speex_callbacks.h>
//#include <misc.h>
#include <ogg/ogg.h>
}

#include "../types.h"

namespace speexfile {
    typedef audiere::u64            uint64_t;
    typedef audiere::s64            int64_t;
    typedef audiere::u32            uint32_t;
    typedef audiere::s32            int32_t;
    typedef unsigned long           ulong_t;
    typedef long double             ldouble_t;
    typedef int64_t                 offset_t;
    typedef float                   audio_sample;

    // -------------------------------------

    class Reader {
    public:
        Reader() {}
        virtual ~Reader() {}
        virtual int read ( void *ptr, int size ) = 0;
        //virtual int write ( void *ptr, int size ) = 0;
        virtual offset_t seek ( offset_t offset ) = 0;
        virtual offset_t get_position() = 0;
        virtual offset_t get_length() = 0;
        //virtual int set_eof ( offset_t ofs ) { return 0; }
        virtual bool can_seek() { return 0; }
    };

    // -------------------------------------

    typedef struct {
        char                *item;          // tag item name
        char                *value;         // tag value (can be NULL)
    } speextags;

    class speexfile {
    private:
        typedef struct {
            int                 frame_size;
            int                 packet_count;
            int                 stream_init;
            int                 enh_enabled;
            int                 nframes;
            int                 forceMode;
            int64_t             samplepos;
            void                *st;
            SpeexBits           bits;
            SpeexStereoState    stereo;
            int                 channels;
            ogg_sync_state      oy;
            ogg_page            og;
            ogg_packet          op;
            ogg_stream_state    os;

            char                *data;
            int                 i, j;
            uint32_t            nb_read;

            bool                init;
            bool                eos, eof;

            int                 decoderpos;
        } speexdecoder;

        typedef struct {
            offset_t            offset;         // byte offset in file
            int64_t             sample;         // sample number in chain
        } speexseekinfo_t;

        typedef struct {
            SpeexHeader         *header;        // Speex header
            speextags           **tags;         // tag fields
            speexseekinfo_t     **seekinfo;     // info to help seeking
            int32_t             tagcount;       // number of tag fields
            int32_t             sicount;        // number of seekpositions
            offset_t            streamsize;     // size in bytes
        } speexstream_t;

    private:
        Reader              *pReader;       // reader
        speexstream_t       **stream;       // stream info
        int32_t             streamcount;    // number of streams
        offset_t            offset;         // position in file
        //long                skipsamples;    // number of samples to skip for accurate seek
        int64_t             seektosample;
        int32_t             current_stream;

    public:
        speexdecoder        *decoder;       // Speex decoder
        bool                seekable;       // file is seekable
        bool                initialized;    // file init was successful
        long                bitrate;        // temporary bitrate on vbr files
        char                speex_last_error[512];
        int32_t             current_serial;

    public:
        speexfile ( Reader *r );
        ~speexfile ();

        int  seek_sample ( int64_t samplepos );                     // seek to given sample position
        int  seek_time   ( double timepos   );                      // seek to given position, time in seconds

        int  decode  ( audio_sample *buffer );                      // decode at maximum 2000 samples to buffer

        int32_t   get_stream    ();                                 // return current stream
        int32_t   get_streams   ();                                 // return number of streams
        int64_t   get_samples   ();                                 // return samples in whole chain
        double    get_duration  ();                                 // return duration of whole chain
        double    get_bitrate   ();                                 // return average bitrate of whole chain

        int32_t   stream_get_samplerate ( int32_t _stream = -1 );   // return samplerate of given stream number (0 = first stream in chain)
        int32_t   stream_get_channels   ( int32_t _stream = -1 );   // return number of channels
        int64_t   stream_get_firstsample( int32_t _stream = -1 );   // return first sample in stream
        int64_t   stream_get_lastsample ( int32_t _stream = -1 );   // return last sample in stream
        int64_t   stream_get_samples    ( int32_t _stream = -1 );   // return number of samples
        double    stream_get_duration   ( int32_t _stream = -1 );   // return duration in seconds
        double    stream_get_bitrate    ( int32_t _stream = -1 );   // return average bitrate in bits / second
        offset_t  stream_get_size       ( int32_t _stream = -1 );   // return size in bytes
        int32_t   stream_get_tagcount   ( int32_t _stream = -1 );   // return number of tag fields
        const speextags**  stream_get_tags        ( int32_t _stream = -1 ); // return pointer to tag struct
        const SpeexHeader* stream_get_speexheader ( int32_t _stream = -1 ); // return pointer to header struct

    private:
        int  initfile ();                                           // read file header and scan lengths and seek positions
        int  init_decoder  ();                                      // initialize Speex decoder
        int  close_decoder ();                                      // free Speex decoder
        int  readtags ( char *tagdata, long size );                 // read tags
        void free_tags ();                                          // free all tags from memory
        void stream_free_tags ( int32_t _stream );                  // free tags from specified stream
        //void *process_header ( ogg_packet *op, int enh_enabled, int *frame_size, int *rate, int *nframes, int forceMode, int *channels, SpeexStereoState *stereo );
        void *header_to_decoder ( SpeexHeader *header, int enh_enabled, int *frame_size, int *rate, int *nframes, int forceMode, int *channels, SpeexStereoState *stereo );
    };

    // -------------------------------------

    #ifdef SL_READER

    class Reader_file : public Reader {
    private:
        HANDLE fh;

    public:
        Reader_file ( HANDLE _fh ) {
            fh = _fh;
        }

        ~Reader_file() {
            if ( fh != INVALID_HANDLE_VALUE ) {
                CloseHandle ( fh );
                fh = INVALID_HANDLE_VALUE;
            }
        }

        virtual int read ( void *ptr, int size ) {
            DWORD bytesread;
            if ( !ReadFile (fh, ptr, size, &bytesread, NULL) ) return 0;
            return bytesread;
        }

        virtual int write ( void *ptr, int size ) {
            DWORD byteswritten;
            if ( !WriteFile (fh, ptr, size, &byteswritten, NULL) ) return 0;
            return byteswritten;
        }

        virtual __int64 seek ( __int64 offset ) {
            LONG high = (DWORD)(offset >> 32);
            DWORD low = SetFilePointer ( fh, (LONG)offset, &high, FILE_BEGIN );
            if ( (low == 0xFFFFFFFF) && (GetLastError() != NO_ERROR) ) return -1;
            return ((__int64)high << 32) | low;
        }

        virtual __int64 get_position() {
            LONG high = 0;
            DWORD low = SetFilePointer ( fh, 0, &high, FILE_CURRENT );
            if ( (low == 0xFFFFFFFF) && (GetLastError() != NO_ERROR) ) return -1;
            return ((__int64)high << 32) | low;
        }

        virtual __int64 get_length() {
            ULONG high;
            DWORD low = GetFileSize ( fh, &high );
            if ( (low == INVALID_FILE_SIZE) && (GetLastError() != NO_ERROR) ) return -1;
            return ((__int64)high << 32) | low;
        }

        virtual int set_eof ( __int64 offset ) {
            if ( seek (offset) != offset ) return 0;
            return SetEndOfFile ( fh );
        };

        virtual bool can_seek () {
            if ( GetFileType (fh) == FILE_TYPE_DISK ) return true;
            return false;
        }
    };

    #endif // SL_READER
}

#endif // _speexfile_h