Main Page | Class List | Directories | File List | File Members | Related Pages

streaminfo.c

Go to the documentation of this file.
00001 /*
00002   Copyright (c) 2005, The Musepack Development Team
00003   All rights reserved.
00004 
00005   Redistribution and use in source and binary forms, with or without
00006   modification, are permitted provided that the following conditions are
00007   met:
00008 
00009   * Redistributions of source code must retain the above copyright
00010   notice, this list of conditions and the following disclaimer.
00011 
00012   * Redistributions in binary form must reproduce the above
00013   copyright notice, this list of conditions and the following
00014   disclaimer in the documentation and/or other materials provided
00015   with the distribution.
00016 
00017   * Neither the name of the The Musepack Development Team nor the
00018   names of its contributors may be used to endorse or promote
00019   products derived from this software without specific prior
00020   written permission.
00021 
00022   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00025   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00026   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00027   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00028   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00029   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00030   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00031   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00032   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 */
00034 
00037 
00038 #include "musepack/musepack.h"
00039 #include "musepack/internal.h"
00040 
00041 static const char *
00042 Stringify(mpc_uint32_t profile) // profile is 0...15, where 7...13 is used
00043 {
00044     static const char na[] = "n.a.";
00045     static const char *Names[] = {
00046         na, "'Unstable/Experimental'", na, na,
00047         na, "'quality 0'", "'quality 1'", "'Telephone'",
00048         "'Thumb'", "'Radio'", "'Standard'", "'Xtreme'",
00049         "'Insane'", "'BrainDead'", "'quality 9'", "'quality 10'"
00050     };
00051 
00052     return profile >= sizeof(Names) / sizeof(*Names) ? na : Names[profile];
00053 }
00054 
00055 void
00056 mpc_streaminfo_init(mpc_streaminfo * si)
00057 {
00058     memset(si, 0, sizeof(mpc_streaminfo));
00059 }
00060 
00061 // read information from SV8 header
00062 // not yet implemented
00063 static mpc_int32_t
00064 streaminfo_read_header_sv8(mpc_streaminfo * si, mpc_reader * fp)
00065 {
00066     return 0;
00067 }
00068 
00070 static mpc_int32_t
00071 streaminfo_read_header_sv7(mpc_streaminfo * si, mpc_uint32_t HeaderData[8])
00072 {
00073     const mpc_int32_t samplefreqs[4] = { 44100, 48000, 37800, 32000 };
00074 
00075     //mpc_uint32_t    HeaderData [8];
00076     mpc_uint16_t Estimatedpeak_title = 0;
00077 
00078     if (si->stream_version > 0x71) {
00079         //        Update (si->stream_version);
00080         return 0;
00081     }
00082 
00083     /*
00084        if ( !fp->seek ( si->header_position ) )         // seek to header start
00085        return ERROR_CODE_FILE;
00086        if ( fp->read ( HeaderData, sizeof HeaderData) != sizeof HeaderData )
00087        return ERROR_CODE_FILE;
00088      */
00089 
00090     si->bitrate = 0;
00091     si->frames = HeaderData[1];
00092     si->is = 0;
00093     si->ms = (HeaderData[2] >> 30) & 0x0001;
00094     si->max_band = (HeaderData[2] >> 24) & 0x003F;
00095     si->block_size = 1;
00096     si->profile = (HeaderData[2] << 8) >> 28;
00097     si->profile_name = Stringify(si->profile);
00098     si->sample_freq = samplefreqs[(HeaderData[2] >> 16) & 0x0003];
00099     Estimatedpeak_title = (mpc_uint16_t) (HeaderData[2] & 0xFFFF);   // read the ReplayGain data
00100     si->gain_title = (mpc_uint16_t) ((HeaderData[3] >> 16) & 0xFFFF);
00101     si->peak_title = (mpc_uint16_t) (HeaderData[3] & 0xFFFF);
00102     si->gain_album = (mpc_uint16_t) ((HeaderData[4] >> 16) & 0xFFFF);
00103     si->peak_album = (mpc_uint16_t) (HeaderData[4] & 0xFFFF);
00104     si->is_true_gapless = (HeaderData[5] >> 31) & 0x0001; // true gapless: used?
00105     si->last_frame_samples = (HeaderData[5] >> 20) & 0x07FF;  // true gapless: valid samples for last frame
00106     si->encoder_version = (HeaderData[6] >> 24) & 0x00FF;
00107 
00108     if (si->encoder_version == 0) {
00109         sprintf(si->encoder, "Buschmann 1.7.0...9, Klemm 0.90...1.05");
00110     }
00111     else {
00112         switch (si->encoder_version % 10) {
00113         case 0:
00114             sprintf(si->encoder, "Release %u.%u", si->encoder_version / 100,
00115                     si->encoder_version / 10 % 10);
00116             break;
00117         case 2:
00118         case 4:
00119         case 6:
00120         case 8:
00121             sprintf(si->encoder, "Beta %u.%02u", si->encoder_version / 100,
00122                     si->encoder_version % 100);
00123             break;
00124         default:
00125             sprintf(si->encoder, "--Alpha-- %u.%02u",
00126                     si->encoder_version / 100, si->encoder_version % 100);
00127             break;
00128         }
00129     }
00130 
00131     //    if ( si->peak_title == 0 )                                      // there is no correct peak_title contained within header
00132     //        si->peak_title = (mpc_uint16_t)(Estimatedpeak_title * 1.18);
00133     //    if ( si->peak_album == 0 )
00134     //        si->peak_album = si->peak_title;                          // no correct peak_album, use peak_title
00135 
00136     //si->sample_freq    = 44100;                                     // AB: used by all files up to SV7
00137     si->channels = 2;
00138 
00139     return ERROR_CODE_OK;
00140 }
00141 
00142 // read information from SV4-SV6 header
00143 static mpc_int32_t
00144 streaminfo_read_header_sv6(mpc_streaminfo * si, mpc_uint32_t HeaderData[8])
00145 {
00146     //mpc_uint32_t    HeaderData [8];
00147 
00148     /*
00149        if ( !fp->seek (  si->header_position ) )         // seek to header start
00150        return ERROR_CODE_FILE;
00151        if ( fp->read ( HeaderData, sizeof HeaderData ) != sizeof HeaderData )
00152        return ERROR_CODE_FILE;
00153      */
00154 
00155     si->bitrate = (HeaderData[0] >> 23) & 0x01FF;   // read the file-header (SV6 and below)
00156     si->is = (HeaderData[0] >> 22) & 0x0001;
00157     si->ms = (HeaderData[0] >> 21) & 0x0001;
00158     si->stream_version = (HeaderData[0] >> 11) & 0x03FF;
00159     si->max_band = (HeaderData[0] >> 6) & 0x001F;
00160     si->block_size = (HeaderData[0]) & 0x003F;
00161     si->profile = 0;
00162     si->profile_name = Stringify((mpc_uint32_t) (-1));
00163     if (si->stream_version >= 5)
00164         si->frames = HeaderData[1]; // 32 bit
00165     else
00166         si->frames = (HeaderData[1] >> 16); // 16 bit
00167 
00168     si->gain_title = 0;          // not supported
00169     si->peak_title = 0;
00170     si->gain_album = 0;
00171     si->peak_album = 0;
00172 
00173     si->last_frame_samples = 0;
00174     si->is_true_gapless = 0;
00175 
00176     si->encoder_version = 0;
00177     si->encoder[0] = '\0';
00178 
00179     if (si->stream_version == 7)
00180         return ERROR_CODE_SV7BETA;  // are there any unsupported parameters used?
00181     if (si->bitrate != 0)
00182         return ERROR_CODE_CBR;
00183     if (si->is != 0)
00184         return ERROR_CODE_IS;
00185     if (si->block_size != 1)
00186         return ERROR_CODE_BLOCKSIZE;
00187 
00188     if (si->stream_version < 6) // Bugfix: last frame was invalid for up to SV5
00189         si->frames -= 1;
00190 
00191     si->sample_freq = 44100;     // AB: used by all files up to SV7
00192     si->channels = 2;
00193 
00194     if (si->stream_version < 4 || si->stream_version > 7)
00195         return ERROR_CODE_INVALIDSV;
00196 
00197     return ERROR_CODE_OK;
00198 }
00199 
00200 // reads file header and tags
00201 mpc_int32_t
00202 mpc_streaminfo_read(mpc_streaminfo * si, mpc_reader * r)
00203 {
00204     mpc_uint32_t HeaderData[8];
00205     mpc_int32_t Error = 0;
00206 
00207     // get header position
00208     if ((si->header_position = JumpID3v2(r)) < 0) {
00209         return ERROR_CODE_FILE;
00210     }
00211     // seek to first byte of mpc data
00212     if (!r->seek(r->data, si->header_position)) {
00213         return ERROR_CODE_FILE;
00214     }
00215     if (r->read(r->data, HeaderData, 8 * 4) != 8 * 4) {
00216         return ERROR_CODE_FILE;
00217     }
00218     if (!r->seek(r->data, si->header_position + 6 * 4)) {
00219         return ERROR_CODE_FILE;
00220     }
00221 
00222     si->total_file_length = r->get_size(r->data);
00223     si->tag_offset = si->total_file_length;
00224     if (memcmp(HeaderData, "MP+", 3) == 0) {
00225 #ifndef MPC_LITTLE_ENDIAN
00226         mpc_uint32_t ptr;
00227         for (ptr = 0; ptr < 8; ptr++) {
00228             HeaderData[ptr] = swap32(HeaderData[ptr]);
00229         }
00230 #endif
00231         si->stream_version = HeaderData[0] >> 24;
00232 
00233         // stream version 8
00234         if ((si->stream_version & 15) >= 8) {
00235             Error = streaminfo_read_header_sv8(si, r);
00236         }
00237         // stream version 7
00238         else if ((si->stream_version & 15) == 7) {
00239             Error = streaminfo_read_header_sv7(si, HeaderData);
00240         }
00241     }
00242     else {
00243         // stream version 4-6
00244         Error = streaminfo_read_header_sv6(si, HeaderData);
00245     }
00246 
00247     // estimation, exact value needs too much time
00248     si->pcm_samples = 1152 * si->frames - 576;
00249 
00250     if (si->pcm_samples > 0) {
00251         si->average_bitrate =
00252             (si->tag_offset -
00253              si->header_position) * 8.0 * si->sample_freq / si->pcm_samples;
00254     }
00255     else {
00256         si->average_bitrate = 0;
00257     }
00258 
00259     return Error;
00260 }
00261 
00262 double
00263 mpc_streaminfo_get_length(mpc_streaminfo * si)
00264 {
00265     return (double)mpc_streaminfo_get_length_samples(si) /
00266         (double)si->sample_freq;
00267 }
00268 
00269 mpc_int64_t
00270 mpc_streaminfo_get_length_samples(mpc_streaminfo * si)
00271 {
00272     mpc_int64_t samples = (mpc_int64_t) si->frames * MPC_FRAME_LENGTH;
00273     if (si->is_true_gapless) {
00274         samples -= (MPC_FRAME_LENGTH - si->last_frame_samples);
00275     }
00276     else {
00277         samples -= MPC_DECODER_SYNTH_DELAY;
00278     }
00279     return samples;
00280 }

Generated on Sat Jan 22 09:34:07 2005 for libmusepack by  doxygen 1.4.1