Ignore:
Timestamp:
11/08/06 00:20:07 (17 years ago)
Author:
r2d
Message:
  • can read sv7 & sv8
  • seek broken (not implemented)
  • added demuxer in API
  • added access to decoder in API
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libmpcdec/branches/zorg/src/streaminfo.c

    r81 r104  
    3535/// Implementation of streaminfo reading functions.
    3636
     37#include <mpcdec/mpcdec.h>
    3738#include <mpcdec/streaminfo.h>
    3839#include <stdio.h>
    3940#include "internal.h"
     41
     42mpc_uint32_t mpc_bits_read(mpc_bits_reader * r, const unsigned int nb_bits);
     43unsigned int mpc_bits_get_size(mpc_bits_reader * r, mpc_uint64_t * p_size);
    4044
    4145static const char na[] = "n.a.";
     
    5357}
    5458
     59static void
     60mpc_get_encoder_string(mpc_streaminfo* si)
     61{
     62        if (si->encoder_version == 0) {
     63                sprintf(si->encoder, "Buschmann 1.7.0...9, Klemm 0.90...1.05");
     64        } else {
     65                switch (si->encoder_version % 10) {
     66                        case 0:
     67                                sprintf(si->encoder, "Release %u.%u", si->encoder_version / 100,
     68                                                si->encoder_version / 10 % 10);
     69                                break;
     70                        case 2: case 4: case 6: case 8:
     71                                sprintf(si->encoder, "Beta %u.%02u", si->encoder_version / 100,
     72                                                si->encoder_version % 100);
     73                                break;
     74                        default:
     75                                sprintf(si->encoder, "--Alpha-- %u.%02u",
     76                                                si->encoder_version / 100, si->encoder_version % 100);
     77                                break;
     78                }
     79        }
     80}
     81
    5582/// Reads streaminfo from SV7 header.
    56 static mpc_status
    57 streaminfo_read_header_sv7(mpc_streaminfo* si, mpc_uint32_t HeaderData[8])
     83mpc_status
     84streaminfo_read_header_sv7(mpc_streaminfo* si, mpc_bits_reader * r)
    5885{
    5986    mpc_uint16_t Estimatedpeak_title = 0;
    6087
    61     if (si->stream_version > 0x71) {
    62         //        Update (si->stream_version);
    63         return MPC_STATUS_OK;
    64     }
    65 
    66     si->bitrate            = 0;
    67     si->frames             = HeaderData[1];
    68     si->is                 = 0;
    69     si->ms                 = (HeaderData[2] >> 30) & 0x0001;
    70     si->max_band           = (HeaderData[2] >> 24) & 0x003F;
    71     si->block_size         = 1;
    72     si->profile            = (HeaderData[2] << 8) >> 28;
     88        si->bitrate            = 0;
     89        si->block_size         = 1;
     90        si->frames             = mpc_bits_read(r, 32);
     91        si->is                 = mpc_bits_read(r, 1); // should be 0
     92        si->ms                 = mpc_bits_read(r, 1);
     93        si->max_band           = mpc_bits_read(r, 6);
     94        si->profile            = mpc_bits_read(r, 4);
    7395    si->profile_name       = mpc_get_version_string(si->profile);
    74     si->sample_freq        = samplefreqs[(HeaderData[2] >> 16) & 0x0003];
    75     Estimatedpeak_title    = (mpc_uint16_t) (HeaderData[2] & 0xFFFF);   // read the ReplayGain data
    76     si->gain_title         = (mpc_uint16_t) ((HeaderData[3] >> 16) & 0xFFFF);
    77     si->peak_title         = (mpc_uint16_t) (HeaderData[3] & 0xFFFF);
    78     si->gain_album         = (mpc_uint16_t) ((HeaderData[4] >> 16) & 0xFFFF);
    79     si->peak_album         = (mpc_uint16_t) (HeaderData[4] & 0xFFFF);
    80     si->is_true_gapless    = (HeaderData[5] >> 31) & 0x0001; // true gapless: used?
    81     si->last_frame_samples = (HeaderData[5] >> 20) & 0x07FF; // true gapless: valid samples for last frame
    82     si->fast_seek          = (HeaderData[5] >> 19) & 0x0001; // fast seeking
    83     si->encoder_version    = (HeaderData[6] >> 24) & 0x00FF;
     96        mpc_bits_read(r, 2); // Link ?
     97        si->sample_freq        = samplefreqs[mpc_bits_read(r, 2)];
     98        Estimatedpeak_title    = (mpc_uint16_t) mpc_bits_read(r, 16);   // read the ReplayGain data
     99        si->gain_title         = (mpc_uint16_t) mpc_bits_read(r, 16);
     100        si->peak_title         = (mpc_uint16_t) mpc_bits_read(r, 16);
     101        si->gain_album         = (mpc_uint16_t) mpc_bits_read(r, 16);
     102        si->peak_album         = (mpc_uint16_t) mpc_bits_read(r, 16);
     103        si->is_true_gapless    = mpc_bits_read(r, 1); // true gapless: used?
     104        si->last_frame_samples = mpc_bits_read(r, 11); // true gapless: valid samples for last frame
     105        si->fast_seek          = mpc_bits_read(r, 1); // fast seeking
     106        mpc_bits_read(r, 19); // unused
     107        si->encoder_version    = mpc_bits_read(r, 8);
    84108    si->channels           = 2;
    85109
    86     if (si->encoder_version == 0) {
    87         sprintf(si->encoder, "Buschmann 1.7.0...9, Klemm 0.90...1.05");
    88     }
    89     else {
    90         switch (si->encoder_version % 10) {
    91         case 0:
    92             sprintf(si->encoder, "Release %u.%u", si->encoder_version / 100,
    93                     si->encoder_version / 10 % 10);
    94             break;
    95         case 2: case 4: case 6: case 8:
    96             sprintf(si->encoder, "Beta %u.%02u", si->encoder_version / 100,
    97                     si->encoder_version % 100);
    98             break;
    99         default:
    100             sprintf(si->encoder, "--Alpha-- %u.%02u",
    101                     si->encoder_version / 100, si->encoder_version % 100);
    102             break;
    103         }
    104     }
     110        mpc_get_encoder_string(si);
     111
     112        // estimation, exact value needs too much time
     113        si->pcm_samples     = 1152 * si->frames - 576;
     114        si->average_bitrate = 0;
     115        if (si->pcm_samples > 0)
     116                si->average_bitrate = (si->tag_offset  - si->header_position) * 8.0
     117                                *  si->sample_freq / si->pcm_samples;
    105118
    106119    return MPC_STATUS_OK;
     
    108121
    109122/// Reads streaminfo from SV8 header.
    110 static mpc_status
    111 streaminfo_read_header_sv8(mpc_streaminfo* si, mpc_reader * p_reader)
     123mpc_status
     124streaminfo_read_header_sv8(mpc_streaminfo* si, const mpc_bits_reader * r_in)
    112125{
    113         int ret;
    114         mpc_block_t block;
    115         mpc_bits_reader bits_reader = {0, 0};
    116126        mpc_uint32_t CRC;
    117         mpc_int32_t header_pos;
    118         unsigned char tmp;
    119127        mpc_uint64_t sampleCount = 0;
    120 
    121         ret = mpc_find_block(p_reader, &block, "SI", "AD");
    122         if (ret != MPC_STATUS_OK)
    123                 return ret;
    124 
    125         header_pos = p_reader->tell(p_reader);
     128        mpc_bits_reader r = *r_in;
    126129
    127130        // FIXME : add CRC check
    128         CRC = mpc_read_bits(p_reader, &bits_reader, 32);
    129         si->stream_version = mpc_read_bits(p_reader, &bits_reader, 8);
    130 
    131         do {
    132                 p_reader->read(p_reader, &tmp, 1);
    133                 sampleCount = (sampleCount << 7) | (tmp & 0x7F);
    134         } while((tmp & 0x80));
    135 
     131        CRC = mpc_bits_read(&r, 32);
     132        si->stream_version = mpc_bits_read(&r, 8);
     133        mpc_bits_get_size(&r, &sampleCount);
    136134        si->frames = (sampleCount + MPC_FRAME_LENGTH - 1) / MPC_FRAME_LENGTH;
    137135        si->is_true_gapless = 1;
    138136        si->last_frame_samples = sampleCount - (si->frames - 1) * MPC_FRAME_LENGTH;
    139         si->sample_freq = samplefreqs[mpc_read_bits(p_reader, &bits_reader, 4)];
    140         si->channels = mpc_read_bits(p_reader, &bits_reader, 4) + 1;
    141         si->max_band = mpc_read_bits(p_reader, &bits_reader, 5) + 1;
     137        si->sample_freq = samplefreqs[mpc_bits_read(&r, 4)];
     138        si->channels = mpc_bits_read(&r, 4) + 1;
     139        si->max_band = mpc_bits_read(&r, 5) + 1;
    142140        // FIXME : this flag will be removed, must be 0
    143         si->is = mpc_read_bits(p_reader, &bits_reader, 1);
    144         si->ms = mpc_read_bits(p_reader, &bits_reader, 1);
     141        si->is = mpc_bits_read(&r, 1);
     142        si->ms = mpc_bits_read(&r, 1);
    145143
    146144        si->bitrate            = 0;
     
    152150                si->average_bitrate = (si->tag_offset - si->header_position) * 8.0
    153151                                *  si->sample_freq / si->pcm_samples;
    154 
    155         // seek to the end of the block
    156         p_reader->seek(p_reader, header_pos + block.size);
    157 
    158         return MPC_STATUS_OK;
    159 }
    160 
    161 // reads file header and tags
    162 mpc_status
    163 mpc_streaminfo_init(mpc_streaminfo * si, mpc_reader *p_reader)
    164 {
    165     mpc_uint32_t headerData[8]; int err;
    166 
    167     memset(si, 0, sizeof *si);
    168     // get header position
    169     err = si->header_position = mpc_skip_id3v2(p_reader);
    170     if(err < 0) return MPC_STATUS_FILE;
    171 
    172     // seek to first byte of mpc data
    173     err = p_reader->seek(p_reader, si->header_position);
    174     if(!err) return MPC_STATUS_FILE;
    175 
    176         // read magic
    177         err = p_reader->read(p_reader, headerData, 4);
    178         if(err != 4) return MPC_STATUS_FILE;
    179 
    180         if (memcmp(headerData, "MP+", 3) == 0) {
    181                 // SV 4-7
    182                 err = p_reader->read(p_reader, headerData + 1, 7 * 4);
    183                 if(err != 7 * 4) return MPC_STATUS_FILE;
    184                 err = p_reader->seek(p_reader, si->header_position + 6 * 4);
    185                 if(!err) return MPC_STATUS_FILE;
    186 
    187                 err = p_reader->get_size(p_reader);
    188                 if(err < 0) return MPC_STATUS_FILE;
    189                 si->tag_offset = si->total_file_length = err;
    190 
    191 #ifndef MPC_LITTLE_ENDIAN
    192                 {
    193                         mpc_uint32_t ptr;
    194                         for (ptr = 0; ptr < 8; ptr++)
    195                                 headerData[ptr] = mpc_swap32(headerData[ptr]);
    196                 }
    197 #endif
    198                 si->stream_version = headerData[0] >> 24;
    199 
    200                 if ((si->stream_version & 15) >= 8)
    201                         return MPC_STATUS_INVALIDSV;
    202                 else if ((si->stream_version & 15) == 7) {
    203                         err = streaminfo_read_header_sv7(si, headerData);
    204                         if(err < 0) return err;
    205                 }
    206 
    207                 // estimation, exact value needs too much time
    208                 si->pcm_samples     = 1152 * si->frames - 576;
    209                 si->average_bitrate = 0;
    210                 if (si->pcm_samples > 0)
    211                         si->average_bitrate = (si->tag_offset  - si->header_position) * 8.0
    212                                         *  si->sample_freq / si->pcm_samples;
    213         } else if (memcmp(headerData, "MPCK", 4) == 0) {
    214                 // SV 8
    215                 printf("sv8\n");
    216                 streaminfo_read_header_sv8(si, p_reader);
    217         } else
    218                 return MPC_STATUS_INVALIDSV;
    219152
    220153        return MPC_STATUS_OK;
Note: See TracChangeset for help on using the changeset viewer.