Changeset 68 for libmpcdec/branches/zorg/src/streaminfo.c
- Timestamp:
- 10/06/06 17:14:05 (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libmpcdec/branches/zorg/src/streaminfo.c
r37 r68 32 32 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 33 */ 34 35 34 /// \file streaminfo.c 36 35 /// Implementation of streaminfo reading functions. 37 36 38 #include <mpcdec/mpcdec.h> 39 #include <mpcdec/internal.h> 37 #include <mpcdec/streaminfo.h> 38 #include <stdio.h> 39 #include "internal.h" 40 41 static const char na[] = "n.a."; 42 static const char *versionNames[] = { 43 na, "'Unstable/Experimental'", na, na, na, "'quality 0'", "'quality 1'", 44 "'Telephone'", "'Thumb'", "'Radio'", "'Standard'", "'Extreme'", "'Insane'", 45 "'BrainDead'", "'quality 9'", "'quality 10'" 46 }; 47 static const mpc_int32_t samplefreqs[4] = { 44100, 48000, 37800, 32000 }; 40 48 41 49 static const char * 42 Stringify(mpc_uint32_t profile) // profile is 0...15, where 7...13 is used50 mpc_get_version_string(mpc_uint32_t profile) // profile is 0...15, where 7...13 is used 43 51 { 44 static const char na[] = "n.a."; 45 static const char *Names[] = { 46 na, "'Unstable/Experimental'", na, na, 47 na, "'quality 0'", "'quality 1'", "'Telephone'", 48 "'Thumb'", "'Radio'", "'Standard'", "'Xtreme'", 49 "'Insane'", "'BrainDead'", "'quality 9'", "'quality 10'" 50 }; 51 52 return profile >= sizeof(Names) / sizeof(*Names) ? na : Names[profile]; 52 return profile >= sizeof versionNames / sizeof *versionNames ? na : versionNames[profile]; 53 53 } 54 54 55 55 void 56 mpc_streaminfo_init(mpc_streaminfo 56 mpc_streaminfo_init(mpc_streaminfo* si) 57 57 { 58 memset(si, 0, sizeof (mpc_streaminfo));58 memset(si, 0, sizeof *si); 59 59 } 60 60 61 61 /// Reads streaminfo from SV7 header. 62 static mpc_ int32_t63 streaminfo_read_header_sv7(mpc_streaminfo 62 static mpc_status 63 streaminfo_read_header_sv7(mpc_streaminfo* si, mpc_uint32_t HeaderData[8]) 64 64 { 65 const mpc_int32_t samplefreqs[4] = { 44100, 48000, 37800, 32000 };66 67 //mpc_uint32_t HeaderData [8];68 65 mpc_uint16_t Estimatedpeak_title = 0; 69 66 70 67 if (si->stream_version > 0x71) { 71 68 // Update (si->stream_version); 72 return 0;69 return MPC_STATUS_OK; 73 70 } 74 71 75 /* 76 if ( !fp->seek ( si->header_position ) ) // seek to header start 77 return ERROR_CODE_FILE; 78 if ( fp->read ( HeaderData, sizeof HeaderData) != sizeof HeaderData ) 79 return ERROR_CODE_FILE; 80 */ 81 82 si->bitrate = 0; 83 si->frames = HeaderData[1]; 84 si->is = 0; 85 si->ms = (HeaderData[2] >> 30) & 0x0001; 86 si->max_band = (HeaderData[2] >> 24) & 0x003F; 87 si->block_size = 1; 88 si->profile = (HeaderData[2] << 8) >> 28; 89 si->profile_name = Stringify(si->profile); 90 si->sample_freq = samplefreqs[(HeaderData[2] >> 16) & 0x0003]; 91 Estimatedpeak_title = (mpc_uint16_t) (HeaderData[2] & 0xFFFF); // read the ReplayGain data 92 si->gain_title = (mpc_uint16_t) ((HeaderData[3] >> 16) & 0xFFFF); 93 si->peak_title = (mpc_uint16_t) (HeaderData[3] & 0xFFFF); 94 si->gain_album = (mpc_uint16_t) ((HeaderData[4] >> 16) & 0xFFFF); 95 si->peak_album = (mpc_uint16_t) (HeaderData[4] & 0xFFFF); 96 si->is_true_gapless = (HeaderData[5] >> 31) & 0x0001; // true gapless: used? 97 si->last_frame_samples = (HeaderData[5] >> 20) & 0x07FF; // true gapless: valid samples for last frame 98 si->fast_seek = (HeaderData[5] >> 19) & 0x0001; // fast seeking 99 si->encoder_version = (HeaderData[6] >> 24) & 0x00FF; 72 si->bitrate = 0; 73 si->frames = HeaderData[1]; 74 si->is = 0; 75 si->ms = (HeaderData[2] >> 30) & 0x0001; 76 si->max_band = (HeaderData[2] >> 24) & 0x003F; 77 si->block_size = 1; 78 si->profile = (HeaderData[2] << 8) >> 28; 79 si->profile_name = mpc_get_version_string(si->profile); 80 si->sample_freq = samplefreqs[(HeaderData[2] >> 16) & 0x0003]; 81 Estimatedpeak_title = (mpc_uint16_t) (HeaderData[2] & 0xFFFF); // read the ReplayGain data 82 si->gain_title = (mpc_uint16_t) ((HeaderData[3] >> 16) & 0xFFFF); 83 si->peak_title = (mpc_uint16_t) (HeaderData[3] & 0xFFFF); 84 si->gain_album = (mpc_uint16_t) ((HeaderData[4] >> 16) & 0xFFFF); 85 si->peak_album = (mpc_uint16_t) (HeaderData[4] & 0xFFFF); 86 si->is_true_gapless = (HeaderData[5] >> 31) & 0x0001; // true gapless: used? 87 si->last_frame_samples = (HeaderData[5] >> 20) & 0x07FF; // true gapless: valid samples for last frame 88 si->fast_seek = (HeaderData[5] >> 19) & 0x0001; // fast seeking 89 si->encoder_version = (HeaderData[6] >> 24) & 0x00FF; 90 si->channels = 2; 100 91 101 92 if (si->encoder_version == 0) { … … 108 99 si->encoder_version / 10 % 10); 109 100 break; 110 case 2: 111 case 4: 112 case 6: 113 case 8: 101 case 2: case 4: case 6: case 8: 114 102 sprintf(si->encoder, "Beta %u.%02u", si->encoder_version / 100, 115 103 si->encoder_version % 100); … … 122 110 } 123 111 124 // if ( si->peak_title == 0 ) // there is no correct peak_title contained within header 125 // si->peak_title = (mpc_uint16_t)(Estimatedpeak_title * 1.18); 126 // if ( si->peak_album == 0 ) 127 // si->peak_album = si->peak_title; // no correct peak_album, use peak_title 128 129 //si->sample_freq = 44100; // AB: used by all files up to SV7 130 si->channels = 2; 131 132 return ERROR_CODE_OK; 112 return MPC_STATUS_OK; 133 113 } 134 114 135 // read information from SV4-SV6 header 136 #ifdef MPC_SUPPORT_SV456 137 static mpc_int32_t 138 streaminfo_read_header_sv6(mpc_streaminfo * si, mpc_uint32_t HeaderData[8]) 115 // reads file header and tags 116 mpc_status 117 mpc_streaminfo_read(mpc_streaminfo * si, mpc_reader *p_reader) 139 118 { 140 //mpc_uint32_t HeaderData [8]; 141 142 /* 143 if ( !fp->seek ( si->header_position ) ) // seek to header start 144 return ERROR_CODE_FILE; 145 if ( fp->read ( HeaderData, sizeof HeaderData ) != sizeof HeaderData ) 146 return ERROR_CODE_FILE; 147 */ 148 149 si->bitrate = (HeaderData[0] >> 23) & 0x01FF; // read the file-header (SV6 and below) 150 si->is = (HeaderData[0] >> 22) & 0x0001; 151 si->ms = (HeaderData[0] >> 21) & 0x0001; 152 si->stream_version = (HeaderData[0] >> 11) & 0x03FF; 153 si->max_band = (HeaderData[0] >> 6) & 0x001F; 154 si->block_size = (HeaderData[0]) & 0x003F; 155 si->profile = 0; 156 si->profile_name = Stringify((mpc_uint32_t) (-1)); 157 if (si->stream_version >= 5) 158 si->frames = HeaderData[1]; // 32 bit 159 else 160 si->frames = (HeaderData[1] >> 16); // 16 bit 161 162 si->gain_title = 0; // not supported 163 si->peak_title = 0; 164 si->gain_album = 0; 165 si->peak_album = 0; 166 167 si->last_frame_samples = 0; 168 si->is_true_gapless = 0; 169 170 si->encoder_version = 0; 171 si->encoder[0] = '\0'; 172 173 if (si->stream_version == 7) 174 return ERROR_CODE_SV7BETA; // are there any unsupported parameters used? 175 if (si->bitrate != 0) 176 return ERROR_CODE_CBR; 177 if (si->is != 0) 178 return ERROR_CODE_IS; 179 if (si->block_size != 1) 180 return ERROR_CODE_BLOCKSIZE; 181 182 if (si->stream_version < 6) // Bugfix: last frame was invalid for up to SV5 183 si->frames -= 1; 184 185 si->sample_freq = 44100; // AB: used by all files up to SV7 186 si->channels = 2; 187 188 if (si->stream_version < 4 || si->stream_version > 7) 189 return ERROR_CODE_INVALIDSV; 190 191 return ERROR_CODE_OK; 192 } 193 #endif 194 // reads file header and tags 195 mpc_int32_t 196 mpc_streaminfo_read(mpc_streaminfo * si, mpc_reader * r) 197 { 198 mpc_uint32_t HeaderData[8]; 199 mpc_int32_t Error = 0; 119 mpc_uint32_t headerData[8]; int err; 200 120 201 121 // get header position 202 if ((si->header_position = JumpID3v2(r)) < 0) { 203 return ERROR_CODE_FILE; 122 err = si->header_position = mpc_skip_id3v2(p_reader); 123 if(err < 0) return MPC_STATUS_FILE; 124 125 // seek to first byte of mpc data 126 err = p_reader->seek(p_reader, si->header_position); 127 if(!err) return MPC_STATUS_FILE; 128 err = p_reader->read(p_reader, headerData, 8 * 4); 129 if(err != 8 * 4) return MPC_STATUS_FILE; 130 err = p_reader->seek(p_reader, si->header_position + 6 * 4); 131 if(!err) return MPC_STATUS_FILE; 132 133 err = p_reader->get_size(p_reader); 134 if(err < 0) return MPC_STATUS_FILE; 135 si->tag_offset = si->total_file_length = err; 136 137 err = memcmp(headerData, "MP+", 3); 138 if(!err) return MPC_STATUS_INVALIDSV; 139 140 #ifndef MPC_LITTLE_ENDIAN 141 { 142 mpc_uint32_t ptr; 143 for (ptr = 0; ptr < 8; ptr++) 144 headerData[ptr] = mpc_swap32(headerData[ptr]); 204 145 } 205 // seek to first byte of mpc data 206 if (!r->seek(r->data, si->header_position)) { 207 return ERROR_CODE_FILE; 208 } 209 if (r->read(r->data, HeaderData, 8 * 4) != 8 * 4) { 210 return ERROR_CODE_FILE; 211 } 212 if (!r->seek(r->data, si->header_position + 6 * 4)) { 213 return ERROR_CODE_FILE; 214 } 146 #endif 147 si->stream_version = headerData[0] >> 24; 215 148 216 si->total_file_length = r->get_size(r->data); 217 si->tag_offset = si->total_file_length; 218 if (memcmp(HeaderData, "MP+", 3) == 0) { 219 #ifndef MPC_LITTLE_ENDIAN 220 mpc_uint32_t ptr; 221 for (ptr = 0; ptr < 8; ptr++) { 222 HeaderData[ptr] = mpc_swap32(HeaderData[ptr]); 223 } 224 #endif 225 si->stream_version = HeaderData[0] >> 24; 226 227 // stream version 8 228 if ((si->stream_version & 15) >= 8) { 229 return ERROR_CODE_INVALIDSV; 230 } 231 // stream version 7 232 else if ((si->stream_version & 15) == 7) { 233 Error = streaminfo_read_header_sv7(si, HeaderData); 234 if (Error != ERROR_CODE_OK) return Error; 235 } 236 } else { 237 #ifdef MPC_SUPPORT_SV456 238 // stream version 4-6 239 Error = streaminfo_read_header_sv6(si, HeaderData); 240 #else 241 return ERROR_CODE_INVALIDSV; 242 #endif 243 } 149 if ((si->stream_version & 15) >= 8) 150 return MPC_STATUS_INVALIDSV; 151 else if ((si->stream_version & 15) == 7) 152 { 153 err = streaminfo_read_header_sv7(si, headerData); 154 if(err < 0) return err; 155 } 244 156 245 157 // estimation, exact value needs too much time 246 si->pcm_samples = 1152 * si->frames - 576; 158 si->pcm_samples = 1152 * si->frames - 576; 159 si->average_bitrate = 0; 160 if (si->pcm_samples > 0) 161 si->average_bitrate = (si->tag_offset - si->header_position) * 8.0 162 * si->sample_freq / si->pcm_samples; 247 163 248 if (si->pcm_samples > 0) { 249 si->average_bitrate = 250 (si->tag_offset - 251 si->header_position) * 8.0 * si->sample_freq / si->pcm_samples; 252 } 253 else { 254 si->average_bitrate = 0; 255 } 256 257 return ERROR_CODE_OK; 164 return MPC_STATUS_OK; 258 165 } 259 166 … … 261 168 mpc_streaminfo_get_length(mpc_streaminfo * si) 262 169 { 263 return (double)mpc_streaminfo_get_length_samples(si) / 264 (double)si->sample_freq; 170 return (double) mpc_streaminfo_get_length_samples(si) / si->sample_freq; 265 171 } 266 172 … … 269 175 { 270 176 mpc_int64_t samples = (mpc_int64_t) si->frames * MPC_FRAME_LENGTH; 271 if (si->is_true_gapless) {177 if (si->is_true_gapless) 272 178 samples -= (MPC_FRAME_LENGTH - si->last_frame_samples); 273 } 274 else { 179 else 275 180 samples -= MPC_DECODER_SYNTH_DELAY; 276 }277 181 return samples; 278 182 }
Note: See TracChangeset
for help on using the changeset viewer.