00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00037
00038 #include <mpcdec/mpcdec.h>
00039 #include <mpcdec/internal.h>
00040
00041 static const char *
00042 Stringify(mpc_uint32_t profile)
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
00062
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
00078 mpc_uint16_t Estimatedpeak_title = 0;
00079
00080 if (si->stream_version > 0x71) {
00081
00082 return 0;
00083 }
00084
00085
00086
00087
00088
00089
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);
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;
00107 si->last_frame_samples = (HeaderData[5] >> 20) & 0x07FF;
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
00134
00135
00136
00137
00138
00139 si->channels = 2;
00140
00141 return ERROR_CODE_OK;
00142 }
00143
00144
00145 static mpc_int32_t
00146 streaminfo_read_header_sv6(mpc_streaminfo * si, mpc_uint32_t HeaderData[8])
00147 {
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 si->bitrate = (HeaderData[0] >> 23) & 0x01FF;
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];
00167 else
00168 si->frames = (HeaderData[1] >> 16);
00169
00170 si->gain_title = 0;
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;
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)
00191 si->frames -= 1;
00192
00193 si->sample_freq = 44100;
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
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
00210 if ((si->header_position = JumpID3v2(r)) < 0) {
00211 return ERROR_CODE_FILE;
00212 }
00213
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
00236 if ((si->stream_version & 15) >= 8) {
00237 Error = streaminfo_read_header_sv8(si, r);
00238 }
00239
00240 else if ((si->stream_version & 15) == 7) {
00241 Error = streaminfo_read_header_sv7(si, HeaderData);
00242 }
00243 }
00244 else {
00245
00246 Error = streaminfo_read_header_sv6(si, HeaderData);
00247 }
00248
00249
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 }