Main Page | Class List | Directories | File List | Class Members | 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 <mpcdec/mpcdec.h>
00039 #include <mpcdec/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     (void) si;
00067     (void) fp;
00068     return 0;
00069 }
00070 
00072 static mpc_int32_t
00073 streaminfo_read_header_sv7(mpc_streaminfo * si, mpc_uint32_t HeaderData[8])
00074 {
00075     const mpc_int32_t samplefreqs[4] = { 44100, 48000, 37800, 32000 };
00076 
00077     //mpc_uint32_t    HeaderData [8];
00078     mpc_uint16_t Estimatedpeak_title = 0;
00079 
00080     if (si->stream_version > 0x71) {
00081         //        Update (si->stream_version);
00082         return 0;
00083     }
00084 
00085     /*
00086        if ( !fp->seek ( si->header_position ) )         // seek to header start
00087        return ERROR_CODE_FILE;
00088        if ( fp->read ( HeaderData, sizeof HeaderData) != sizeof HeaderData )
00089        return ERROR_CODE_FILE;
00090      */
00091 
00092     si->bitrate = 0;
00093     si->frames = HeaderData[1];
00094     si->is = 0;
00095     si->ms = (HeaderData[2] >> 30) & 0x0001;
00096     si->max_band = (HeaderData[2] >> 24) & 0x003F;
00097     si->block_size = 1;
00098     si->profile = (HeaderData[2] << 8) >> 28;
00099     si->profile_name = Stringify(si->profile);
00100     si->sample_freq = samplefreqs[(HeaderData[2] >> 16) & 0x0003];
00101     Estimatedpeak_title = (mpc_uint16_t) (HeaderData[2] & 0xFFFF);   // read the ReplayGain data
00102     si->gain_title = (mpc_uint16_t) ((HeaderData[3] >> 16) & 0xFFFF);
00103     si->peak_title = (mpc_uint16_t) (HeaderData[3] & 0xFFFF);
00104     si->gain_album = (mpc_uint16_t) ((HeaderData[4] >> 16) & 0xFFFF);
00105     si->peak_album = (mpc_uint16_t) (HeaderData[4] & 0xFFFF);
00106     si->is_true_gapless = (HeaderData[5] >> 31) & 0x0001; // true gapless: used?
00107     si->last_frame_samples = (HeaderData[5] >> 20) & 0x07FF;  // true gapless: valid samples for last frame
00108     si->encoder_version = (HeaderData[6] >> 24) & 0x00FF;
00109 
00110     if (si->encoder_version == 0) {
00111         sprintf(si->encoder, "Buschmann 1.7.0...9, Klemm 0.90...1.05");
00112     }
00113     else {
00114         switch (si->encoder_version % 10) {
00115         case 0:
00116             sprintf(si->encoder, "Release %u.%u", si->encoder_version / 100,
00117                     si->encoder_version / 10 % 10);
00118             break;
00119         case 2:
00120         case 4:
00121         case 6:
00122         case 8:
00123             sprintf(si->encoder, "Beta %u.%02u", si->encoder_version / 100,
00124                     si->encoder_version % 100);
00125             break;
00126         default:
00127             sprintf(si->encoder, "--Alpha-- %u.%02u",
00128                     si->encoder_version / 100, si->encoder_version % 100);
00129             break;
00130         }
00131     }
00132 
00133     //    if ( si->peak_title == 0 )                                      // there is no correct peak_title contained within header
00134     //        si->peak_title = (mpc_uint16_t)(Estimatedpeak_title * 1.18);
00135     //    if ( si->peak_album == 0 )
00136     //        si->peak_album = si->peak_title;                          // no correct peak_album, use peak_title
00137 
00138     //si->sample_freq    = 44100;                                     // AB: used by all files up to SV7
00139     si->channels = 2;
00140 
00141     return ERROR_CODE_OK;
00142 }
00143 
00144 // read information from SV4-SV6 header
00145 static mpc_int32_t
00146 streaminfo_read_header_sv6(mpc_streaminfo * si, mpc_uint32_t HeaderData[8])
00147 {
00148     //mpc_uint32_t    HeaderData [8];
00149 
00150     /*
00151        if ( !fp->seek (  si->header_position ) )         // seek to header start
00152        return ERROR_CODE_FILE;
00153        if ( fp->read ( HeaderData, sizeof HeaderData ) != sizeof HeaderData )
00154        return ERROR_CODE_FILE;
00155      */
00156 
00157     si->bitrate = (HeaderData[0] >> 23) & 0x01FF;   // read the file-header (SV6 and below)
00158     si->is = (HeaderData[0] >> 22) & 0x0001;
00159     si->ms = (HeaderData[0] >> 21) & 0x0001;
00160     si->stream_version = (HeaderData[0] >> 11) & 0x03FF;
00161     si->max_band = (HeaderData[0] >> 6) & 0x001F;
00162     si->block_size = (HeaderData[0]) & 0x003F;
00163     si->profile = 0;
00164     si->profile_name = Stringify((mpc_uint32_t) (-1));
00165     if (si->stream_version >= 5)
00166         si->frames = HeaderData[1]; // 32 bit
00167     else
00168         si->frames = (HeaderData[1] >> 16); // 16 bit
00169 
00170     si->gain_title = 0;          // not supported
00171     si->peak_title = 0;
00172     si->gain_album = 0;
00173     si->peak_album = 0;
00174 
00175     si->last_frame_samples = 0;
00176     si->is_true_gapless = 0;
00177 
00178     si->encoder_version = 0;
00179     si->encoder[0] = '\0';
00180 
00181     if (si->stream_version == 7)
00182         return ERROR_CODE_SV7BETA;  // are there any unsupported parameters used?
00183     if (si->bitrate != 0)
00184         return ERROR_CODE_CBR;
00185     if (si->is != 0)
00186         return ERROR_CODE_IS;
00187     if (si->block_size != 1)
00188         return ERROR_CODE_BLOCKSIZE;
00189 
00190     if (si->stream_version < 6) // Bugfix: last frame was invalid for up to SV5
00191         si->frames -= 1;
00192 
00193     si->sample_freq = 44100;     // AB: used by all files up to SV7
00194     si->channels = 2;
00195 
00196     if (si->stream_version < 4 || si->stream_version > 7)
00197         return ERROR_CODE_INVALIDSV;
00198 
00199     return ERROR_CODE_OK;
00200 }
00201 
00202 // reads file header and tags
00203 mpc_int32_t
00204 mpc_streaminfo_read(mpc_streaminfo * si, mpc_reader * r)
00205 {
00206     mpc_uint32_t HeaderData[8];
00207     mpc_int32_t Error = 0;
00208 
00209     // get header position
00210     if ((si->header_position = JumpID3v2(r)) < 0) {
00211         return ERROR_CODE_FILE;
00212     }
00213     // seek to first byte of mpc data
00214     if (!r->seek(r->data, si->header_position)) {
00215         return ERROR_CODE_FILE;
00216     }
00217     if (r->read(r->data, HeaderData, 8 * 4) != 8 * 4) {
00218         return ERROR_CODE_FILE;
00219     }
00220     if (!r->seek(r->data, si->header_position + 6 * 4)) {
00221         return ERROR_CODE_FILE;
00222     }
00223 
00224     si->total_file_length = r->get_size(r->data);
00225     si->tag_offset = si->total_file_length;
00226     if (memcmp(HeaderData, "MP+", 3) == 0) {
00227 #ifndef MPC_LITTLE_ENDIAN
00228         mpc_uint32_t ptr;
00229         for (ptr = 0; ptr < 8; ptr++) {
00230             HeaderData[ptr] = mpc_swap32(HeaderData[ptr]);
00231         }
00232 #endif
00233         si->stream_version = HeaderData[0] >> 24;
00234 
00235         // stream version 8
00236         if ((si->stream_version & 15) >= 8) {
00237             Error = streaminfo_read_header_sv8(si, r);
00238         }
00239         // stream version 7
00240         else if ((si->stream_version & 15) == 7) {
00241             Error = streaminfo_read_header_sv7(si, HeaderData);
00242         }
00243     }
00244     else {
00245         // stream version 4-6
00246         Error = streaminfo_read_header_sv6(si, HeaderData);
00247     }
00248 
00249     // estimation, exact value needs too much time
00250     si->pcm_samples = 1152 * si->frames - 576;
00251 
00252     if (si->pcm_samples > 0) {
00253         si->average_bitrate =
00254             (si->tag_offset -
00255              si->header_position) * 8.0 * si->sample_freq / si->pcm_samples;
00256     }
00257     else {
00258         si->average_bitrate = 0;
00259     }
00260 
00261     return Error;
00262 }
00263 
00264 double
00265 mpc_streaminfo_get_length(mpc_streaminfo * si)
00266 {
00267     return (double)mpc_streaminfo_get_length_samples(si) /
00268         (double)si->sample_freq;
00269 }
00270 
00271 mpc_int64_t
00272 mpc_streaminfo_get_length_samples(mpc_streaminfo * si)
00273 {
00274     mpc_int64_t samples = (mpc_int64_t) si->frames * MPC_FRAME_LENGTH;
00275     if (si->is_true_gapless) {
00276         samples -= (MPC_FRAME_LENGTH - si->last_frame_samples);
00277     }
00278     else {
00279         samples -= MPC_DECODER_SYNTH_DELAY;
00280     }
00281     return samples;
00282 }

Generated on Sun Oct 23 16:35:24 2005 for libmpcdec by  doxygen 1.4.4