summaryrefslogtreecommitdiff
path: root/apps/codecs/libmusepack/streaminfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libmusepack/streaminfo.c')
-rw-r--r--apps/codecs/libmusepack/streaminfo.c392
1 files changed, 181 insertions, 211 deletions
diff --git a/apps/codecs/libmusepack/streaminfo.c b/apps/codecs/libmusepack/streaminfo.c
index 3edf50a5ea..5c135ef64a 100644
--- a/apps/codecs/libmusepack/streaminfo.c
+++ b/apps/codecs/libmusepack/streaminfo.c
@@ -1,5 +1,5 @@
1/* 1/*
2 Copyright (c) 2005, The Musepack Development Team 2 Copyright (c) 2005-2009, The Musepack Development Team
3 All rights reserved. 3 All rights reserved.
4 4
5 Redistribution and use in source and binary forms, with or without 5 Redistribution and use in source and binary forms, with or without
@@ -31,256 +31,226 @@
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*/ 33*/
34
35/// \file streaminfo.c 34/// \file streaminfo.c
36/// Implementation of streaminfo reading functions. 35/// Implementation of streaminfo reading functions.
37 36
38#include "musepack.h" 37#include <math.h>
38#include "mpcdec.h"
39#include "streaminfo.h"
40#include <stdio.h>
39#include "internal.h" 41#include "internal.h"
40 42#include "huffman.h"
43#include "mpc_bits_reader.h"
44
45unsigned long mpc_crc32(unsigned char *buf, int len);
46/* rockbox: not used
47static const char na[] = "n.a.";
48static char const * const versionNames[] = {
49 na, "'Unstable/Experimental'", na, na, na, "'quality 0'", "'quality 1'",
50 "'Telephone'", "'Thumb'", "'Radio'", "'Standard'", "'Extreme'", "'Insane'",
51 "'BrainDead'", "'quality 9'", "'quality 10'"
52};
53*/
54static const mpc_int32_t samplefreqs[8] = { 44100, 48000, 37800, 32000 };
55/* rockbox: not used
41static const char * 56static const char *
42Stringify(mpc_uint32_t profile) // profile is 0...15, where 7...13 is used 57mpc_get_version_string(float profile) // profile is 0...15, where 7...13 is used
43{ 58{
44 static const char na[] = "n.a."; 59 return profile >= sizeof versionNames / sizeof *versionNames ? na : versionNames[(int)profile];
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];
53} 60}
54 61*/
55void 62/* rockbox: not used
56mpc_streaminfo_init(mpc_streaminfo * si) 63static void
64mpc_get_encoder_string(mpc_streaminfo* si)
57{ 65{
58 memset(si, 0, sizeof(mpc_streaminfo)); 66 int ver = si->encoder_version;
67 if (si->stream_version >= 8)
68 ver = (si->encoder_version >> 24) * 100 + ((si->encoder_version >> 16) & 0xFF);
69 if (ver <= 116) {
70 if (ver == 0) {
71 sprintf(si->encoder, "Buschmann 1.7.0...9, Klemm 0.90...1.05");
72 } else {
73 switch (ver % 10) {
74 case 0:
75 sprintf(si->encoder, "Release %u.%u", ver / 100,
76 ver / 10 % 10);
77 break;
78 case 2: case 4: case 6: case 8:
79 sprintf(si->encoder, "Beta %u.%02u", ver / 100,
80 ver % 100);
81 break;
82 default:
83 sprintf(si->encoder, "--Alpha-- %u.%02u",
84 ver / 100, ver % 100);
85 break;
86 }
87 }
88 } else {
89 int major = si->encoder_version >> 24;
90 int minor = (si->encoder_version >> 16) & 0xFF;
91 int build = (si->encoder_version >> 8) & 0xFF;
92 char * tmp = "--Stable--";
93
94 if (minor & 1)
95 tmp = "--Unstable--";
96
97 sprintf(si->encoder, "%s %u.%u.%u", tmp, major, minor, build);
98 }
59} 99}
100*/
60 101
61/// Reads streaminfo from SV7 header. 102static mpc_status check_streaminfo(mpc_streaminfo * si)
62static mpc_int32_t
63streaminfo_read_header_sv7(mpc_streaminfo * si, mpc_uint32_t HeaderData[8])
64{ 103{
65 const mpc_int32_t samplefreqs[4] = { 44100, 48000, 37800, 32000 }; 104 if (si->max_band == 0 || si->max_band >= 32
105 || si->channels > 2)
106 return MPC_STATUS_FILE;
107 return MPC_STATUS_OK;
108}
66 109
67 //mpc_uint32_t HeaderData [8]; 110/// Reads streaminfo from SV7 header.
111mpc_status
112streaminfo_read_header_sv7(mpc_streaminfo* si, mpc_bits_reader * r)
113{
68 mpc_uint16_t Estimatedpeak_title = 0; 114 mpc_uint16_t Estimatedpeak_title = 0;
69 115 mpc_uint32_t frames, last_frame_samples;
70 if (si->stream_version > 0x71) { 116
71 // Update (si->stream_version); 117 si->bitrate = 0;
72 return 0; 118 frames = (mpc_bits_read(r, 16) << 16) | mpc_bits_read(r, 16);
119 mpc_bits_read(r, 1); // intensity stereo : should be 0
120 si->ms = mpc_bits_read(r, 1);
121 si->max_band = mpc_bits_read(r, 6);
122 si->profile = mpc_bits_read(r, 4);
123/* rockbox: not used
124 si->profile_name = mpc_get_version_string(si->profile);
125*/
126 mpc_bits_read(r, 2); // Link ?
127 si->sample_freq = samplefreqs[mpc_bits_read(r, 2)];
128 Estimatedpeak_title = (mpc_uint16_t) mpc_bits_read(r, 16); // read the ReplayGain data
129 si->gain_title = (mpc_uint16_t) mpc_bits_read(r, 16);
130 si->peak_title = (mpc_uint16_t) mpc_bits_read(r, 16);
131 si->gain_album = (mpc_uint16_t) mpc_bits_read(r, 16);
132 si->peak_album = (mpc_uint16_t) mpc_bits_read(r, 16);
133 si->is_true_gapless = mpc_bits_read(r, 1); // true gapless: used?
134 last_frame_samples = mpc_bits_read(r, 11); // true gapless: valid samples for last frame
135 si->fast_seek = mpc_bits_read(r, 1); // fast seeking
136 mpc_bits_read(r, 19); // unused
137 si->encoder_version = mpc_bits_read(r, 8);
138 si->channels = 2;
139 si->block_pwr = 0;
140
141/* rockbox: not used
142 // convert gain info
143 if (si->gain_title != 0) {
144 int tmp = (int)((MPC_OLD_GAIN_REF - (mpc_int16_t)si->gain_title / 100.) * 256. + .5);
145 if (tmp >= (1 << 16) || tmp < 0) tmp = 0;
146 si->gain_title = (mpc_int16_t) tmp;
73 } 147 }
74 148
75 /* 149 if (si->gain_album != 0) {
76 if ( !fp->seek ( si->header_position ) ) // seek to header start 150 int tmp = (int)((MPC_OLD_GAIN_REF - (mpc_int16_t)si->gain_album / 100.) * 256. + .5);
77 return ERROR_CODE_FILE; 151 if (tmp >= (1 << 16) || tmp < 0) tmp = 0;
78 if ( fp->read ( HeaderData, sizeof HeaderData) != sizeof HeaderData ) 152 si->gain_album = (mpc_int16_t) tmp;
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->encoder_version = (HeaderData[6] >> 24) & 0x00FF;
99
100 if (si->encoder_version == 0) {
101 //sprintf(si->encoder, "Buschmann 1.7.0...9, Klemm 0.90...1.05");
102 }
103 else {
104 switch (si->encoder_version % 10) {
105 case 0:
106 //sprintf(si->encoder, "Release %u.%u", si->encoder_version / 100,
107 // si->encoder_version / 10 % 10);
108 break;
109 case 2:
110 case 4:
111 case 6:
112 case 8:
113 //sprintf(si->encoder, "Beta %u.%02u", si->encoder_version / 100,
114 // si->encoder_version % 100);
115 break;
116 default:
117 //sprintf(si->encoder, "--Alpha-- %u.%02u",
118 // si->encoder_version / 100, si->encoder_version % 100);
119 break;
120 }
121 } 153 }
154
155 if (si->peak_title != 0)
156 si->peak_title = (mpc_uint16_t) (log10(si->peak_title) * 20 * 256 + .5);
157
158 if (si->peak_album != 0)
159 si->peak_album = (mpc_uint16_t) (log10(si->peak_album) * 20 * 256 + .5);
160
161 mpc_get_encoder_string(si);
162*/
122 163
123 // if ( si->peak_title == 0 ) // there is no correct peak_title contained within header 164 if (last_frame_samples == 0) last_frame_samples = MPC_FRAME_LENGTH;
124 // si->peak_title = (mpc_uint16_t)(Estimatedpeak_title * 1.18); 165 si->samples = (mpc_int64_t) frames * MPC_FRAME_LENGTH;
125 // if ( si->peak_album == 0 ) 166 if (si->is_true_gapless)
126 // si->peak_album = si->peak_title; // no correct peak_album, use peak_title 167 si->samples -= (MPC_FRAME_LENGTH - last_frame_samples);
168 else
169 si->samples -= MPC_DECODER_SYNTH_DELAY;
127 170
128 //si->sample_freq = 44100; // AB: used by all files up to SV7 171 si->average_bitrate = (si->tag_offset - si->header_position) * 8.0
129 si->channels = 2; 172 * si->sample_freq / si->samples;
130 173
131 return ERROR_CODE_OK; 174 return check_streaminfo(si);
132} 175}
133 176
134// read information from SV4-SV6 header 177/// Reads replay gain datas
135#ifdef MPC_SUPPORT_SV456 178void streaminfo_gain(mpc_streaminfo* si, const mpc_bits_reader * r_in)
136static mpc_int32_t
137streaminfo_read_header_sv6(mpc_streaminfo * si, mpc_uint32_t HeaderData[8])
138{ 179{
139 //mpc_uint32_t HeaderData [8]; 180 mpc_bits_reader r = *r_in;
140 181
141 /* 182 int version = mpc_bits_read(&r, 8); // gain version
142 if ( !fp->seek ( si->header_position ) ) // seek to header start 183 if (version != 1) // we only know ver 1
143 return ERROR_CODE_FILE; 184 return;
144 if ( fp->read ( HeaderData, sizeof HeaderData ) != sizeof HeaderData ) 185 si->gain_title = (mpc_uint16_t) mpc_bits_read(&r, 16);
145 return ERROR_CODE_FILE; 186 si->peak_title = (mpc_uint16_t) mpc_bits_read(&r, 16);
146 */ 187 si->gain_album = (mpc_uint16_t) mpc_bits_read(&r, 16);
147 188 si->peak_album = (mpc_uint16_t) mpc_bits_read(&r, 16);
148 si->bitrate = (HeaderData[0] >> 23) & 0x01FF; // read the file-header (SV6 and below) 189}
149 si->is = (HeaderData[0] >> 22) & 0x0001;
150 si->ms = (HeaderData[0] >> 21) & 0x0001;
151 si->stream_version = (HeaderData[0] >> 11) & 0x03FF;
152 si->max_band = (HeaderData[0] >> 6) & 0x001F;
153 si->block_size = (HeaderData[0]) & 0x003F;
154 si->profile = 0;
155 si->profile_name = Stringify((mpc_uint32_t) (-1));
156 if (si->stream_version >= 5)
157 si->frames = HeaderData[1]; // 32 bit
158 else
159 si->frames = (HeaderData[1] >> 16); // 16 bit
160 190
161 si->gain_title = 0; // not supported 191/// Reads streaminfo from SV8 header.
162 si->peak_title = 0; 192mpc_status
163 si->gain_album = 0; 193streaminfo_read_header_sv8(mpc_streaminfo* si, const mpc_bits_reader * r_in,
164 si->peak_album = 0; 194 mpc_size_t block_size)
195{
196 mpc_uint32_t CRC;
197 mpc_bits_reader r = *r_in;
165 198
166 si->last_frame_samples = 0; 199 CRC = (mpc_bits_read(&r, 16) << 16) | mpc_bits_read(&r, 16);
167 si->is_true_gapless = 0; 200 if (CRC != mpc_crc32(r.buff + 1 - (r.count >> 3), (int)block_size - 4))
201 return MPC_STATUS_FILE;
168 202
169 si->encoder_version = 0; 203 si->stream_version = mpc_bits_read(&r, 8);
170 si->encoder[0] = '\0'; 204 if (si->stream_version != 8)
205 return MPC_STATUS_INVALIDSV;
171 206
172 if (si->stream_version == 7) 207 mpc_bits_get_size(&r, &si->samples);
173 return ERROR_CODE_SV7BETA; // are there any unsupported parameters used? 208 mpc_bits_get_size(&r, &si->beg_silence);
174 if (si->bitrate != 0)
175 return ERROR_CODE_CBR;
176 if (si->is != 0)
177 return ERROR_CODE_IS;
178 if (si->block_size != 1)
179 return ERROR_CODE_BLOCKSIZE;
180 209
181 if (si->stream_version < 6) // Bugfix: last frame was invalid for up to SV5 210 si->is_true_gapless = 1;
182 si->frames -= 1; 211 si->sample_freq = samplefreqs[mpc_bits_read(&r, 3)];
212 si->max_band = mpc_bits_read(&r, 5) + 1;
213 si->channels = mpc_bits_read(&r, 4) + 1;
214 si->ms = mpc_bits_read(&r, 1);
215 si->block_pwr = mpc_bits_read(&r, 3) * 2;
183 216
184 si->sample_freq = 44100; // AB: used by all files up to SV7 217 si->bitrate = 0;
185 si->channels = 2;
186 218
187 if (si->stream_version < 4 || si->stream_version > 7) 219 if ((si->samples - si->beg_silence) != 0)
188 return ERROR_CODE_INVALIDSV; 220 si->average_bitrate = (si->tag_offset - si->header_position) * 8.0
221 * si->sample_freq / (si->samples - si->beg_silence);
189 222
190 return ERROR_CODE_OK; 223 return check_streaminfo(si);
191} 224}
192#endif
193// reads file header and tags
194mpc_int32_t
195mpc_streaminfo_read(mpc_streaminfo * si, mpc_reader * r)
196{
197 mpc_uint32_t HeaderData[8];
198 mpc_int32_t Error = 0;
199
200 // get header position
201 if ((si->header_position = JumpID3v2(r)) < 0) {
202 return ERROR_CODE_FILE;
203 }
204 // seek to first byte of mpc data
205 if (!r->seek(r->data, si->header_position)) {
206 return ERROR_CODE_FILE;
207 }
208 if (r->read(r->data, HeaderData, 8 * 4) != 8 * 4) {
209 return ERROR_CODE_FILE;
210 }
211 if (!r->seek(r->data, si->header_position + 6 * 4)) {
212 return ERROR_CODE_FILE;
213 }
214
215 si->total_file_length = r->get_size(r->data);
216 si->tag_offset = si->total_file_length;
217 if (memcmp(HeaderData, "MP+", 3) == 0) {
218#ifndef MPC_LITTLE_ENDIAN
219 mpc_uint32_t ptr;
220 for (ptr = 0; ptr < 8; ptr++) {
221 HeaderData[ptr] = mpc_swap32(HeaderData[ptr]);
222 }
223#endif
224 si->stream_version = HeaderData[0] >> 24;
225
226 // stream version 7
227 if ((si->stream_version & 15) == 7) {
228 Error = streaminfo_read_header_sv7(si, HeaderData);
229 if (Error != ERROR_CODE_OK) return Error;
230 } else {
231 // only sv7 allowed with "MP+" signature
232 return ERROR_CODE_INVALIDSV;
233 }
234 } else if (memcmp(HeaderData, "MPCK", 4) == 0) {
235 // stream version 8 uses "MPCK" signature
236 return ERROR_CODE_INVALIDSV;
237 } else {
238#ifdef MPC_SUPPORT_SV456
239#ifndef MPC_LITTLE_ENDIAN
240 mpc_uint32_t ptr;
241 for (ptr = 0; ptr < 8; ptr++) {
242 HeaderData[ptr] = mpc_swap32(HeaderData[ptr]);
243 }
244#endif
245 // stream version 4-6
246 Error = streaminfo_read_header_sv6(si, HeaderData);
247 if (Error != ERROR_CODE_OK) return Error;
248#else
249 return ERROR_CODE_INVALIDSV;
250#endif
251 }
252 225
253 // estimation, exact value needs too much time 226/// Reads encoder informations
254 si->pcm_samples = 1152 * si->frames - 576; 227void streaminfo_encoder_info(mpc_streaminfo* si, const mpc_bits_reader * r_in)
228{
229 mpc_bits_reader r = *r_in;
255 230
256 if (si->pcm_samples > 0) { 231 si->profile = mpc_bits_read(&r, 7) / 8.;
257 si->average_bitrate = 232/* rockbox: not used
258 (si->tag_offset - 233 si->profile_name = mpc_get_version_string(si->profile);
259 si->header_position) * 8.0 * si->sample_freq / si->pcm_samples; 234*/
260 } 235 si->pns = mpc_bits_read(&r, 1);
261 else { 236 si->encoder_version = mpc_bits_read(&r, 8) << 24; // major
262 si->average_bitrate = 0; 237 si->encoder_version |= mpc_bits_read(&r, 8) << 16; // minor
263 } 238 si->encoder_version |= mpc_bits_read(&r, 8) << 8; // build
264 239
265 return ERROR_CODE_OK; 240/* rockbox: not used
241 mpc_get_encoder_string(si);
242*/
266} 243}
267 244
245/* rockbox: not used
268double 246double
269mpc_streaminfo_get_length(mpc_streaminfo * si) 247mpc_streaminfo_get_length(mpc_streaminfo * si)
270{ 248{
271 return (double)mpc_streaminfo_get_length_samples(si) / 249 return (double) (si->samples - si->beg_silence) / si->sample_freq;
272 (double)si->sample_freq;
273} 250}
274 251
275mpc_int64_t 252mpc_int64_t mpc_streaminfo_get_length_samples(mpc_streaminfo *si)
276mpc_streaminfo_get_length_samples(mpc_streaminfo * si)
277{ 253{
278 mpc_int64_t samples = (mpc_int64_t) si->frames * MPC_FRAME_LENGTH; 254 return si->samples - si->beg_silence;
279 if (si->is_true_gapless) {
280 samples -= (MPC_FRAME_LENGTH - si->last_frame_samples);
281 }
282 else {
283 samples -= MPC_DECODER_SYNTH_DELAY;
284 }
285 return samples;
286} 255}
256*/