FS#8961 - Anti-Aliased Fonts.
[kugel-rb/myfork.git] / apps / codecs / libmusepack / streaminfo.c
blobd9c925dbfbb8d981d0776432de26582506e76a1e
1 /*
2 Copyright (c) 2005, The Musepack Development Team
3 All rights reserved.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
17 * Neither the name of the The Musepack Development Team nor the
18 names of its contributors may be used to endorse or promote
19 products derived from this software without specific prior
20 written permission.
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
35 /// \file streaminfo.c
36 /// Implementation of streaminfo reading functions.
38 #include "musepack.h"
39 #include "internal.h"
41 static const char *
42 Stringify(mpc_uint32_t profile) // profile is 0...15, where 7...13 is used
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'"
52 return profile >= sizeof(Names) / sizeof(*Names) ? na : Names[profile];
55 void
56 mpc_streaminfo_init(mpc_streaminfo * si)
58 memset(si, 0, sizeof(mpc_streaminfo));
61 /// Reads streaminfo from SV7 header.
62 static mpc_int32_t
63 streaminfo_read_header_sv7(mpc_streaminfo * si, mpc_uint32_t HeaderData[8])
65 const mpc_int32_t samplefreqs[4] = { 44100, 48000, 37800, 32000 };
67 //mpc_uint32_t HeaderData [8];
68 mpc_uint16_t Estimatedpeak_title = 0;
70 if (si->stream_version > 0x71) {
71 // Update (si->stream_version);
72 return 0;
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;
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;
100 if (si->encoder_version == 0) {
101 //sprintf(si->encoder, "Buschmann 1.7.0...9, Klemm 0.90...1.05");
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;
123 // if ( si->peak_title == 0 ) // there is no correct peak_title contained within header
124 // si->peak_title = (mpc_uint16_t)(Estimatedpeak_title * 1.18);
125 // if ( si->peak_album == 0 )
126 // si->peak_album = si->peak_title; // no correct peak_album, use peak_title
128 //si->sample_freq = 44100; // AB: used by all files up to SV7
129 si->channels = 2;
131 return ERROR_CODE_OK;
134 // read information from SV4-SV6 header
135 #ifdef MPC_SUPPORT_SV456
136 static mpc_int32_t
137 streaminfo_read_header_sv6(mpc_streaminfo * si, mpc_uint32_t HeaderData[8])
139 //mpc_uint32_t HeaderData [8];
142 if ( !fp->seek ( si->header_position ) ) // seek to header start
143 return ERROR_CODE_FILE;
144 if ( fp->read ( HeaderData, sizeof HeaderData ) != sizeof HeaderData )
145 return ERROR_CODE_FILE;
148 si->bitrate = (HeaderData[0] >> 23) & 0x01FF; // read the file-header (SV6 and below)
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
161 si->gain_title = 0; // not supported
162 si->peak_title = 0;
163 si->gain_album = 0;
164 si->peak_album = 0;
166 si->last_frame_samples = 0;
167 si->is_true_gapless = 0;
169 si->encoder_version = 0;
170 si->encoder[0] = '\0';
172 if (si->stream_version == 7)
173 return ERROR_CODE_SV7BETA; // are there any unsupported parameters used?
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;
181 if (si->stream_version < 6) // Bugfix: last frame was invalid for up to SV5
182 si->frames -= 1;
184 si->sample_freq = 44100; // AB: used by all files up to SV7
185 si->channels = 2;
187 if (si->stream_version < 4 || si->stream_version > 7)
188 return ERROR_CODE_INVALIDSV;
190 return ERROR_CODE_OK;
192 #endif
193 // reads file header and tags
194 mpc_int32_t
195 mpc_streaminfo_read(mpc_streaminfo * si, mpc_reader * r)
197 mpc_uint32_t HeaderData[8];
198 mpc_int32_t Error = 0;
200 // get header position
201 if ((si->header_position = JumpID3v2(r)) < 0) {
202 return ERROR_CODE_FILE;
204 // seek to first byte of mpc data
205 if (!r->seek(r->data, si->header_position)) {
206 return ERROR_CODE_FILE;
208 if (r->read(r->data, HeaderData, 8 * 4) != 8 * 4) {
209 return ERROR_CODE_FILE;
211 if (!r->seek(r->data, si->header_position + 6 * 4)) {
212 return ERROR_CODE_FILE;
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]);
223 #endif
224 si->stream_version = HeaderData[0] >> 24;
226 // stream version 8
227 if ((si->stream_version & 15) >= 8) {
228 return ERROR_CODE_INVALIDSV;
230 // stream version 7
231 else if ((si->stream_version & 15) == 7) {
232 Error = streaminfo_read_header_sv7(si, HeaderData);
233 if (Error != ERROR_CODE_OK) return Error;
235 } else {
236 #ifdef MPC_SUPPORT_SV456
237 #ifndef MPC_LITTLE_ENDIAN
238 mpc_uint32_t ptr;
239 for (ptr = 0; ptr < 8; ptr++) {
240 HeaderData[ptr] = mpc_swap32(HeaderData[ptr]);
242 #endif
243 // stream version 4-6
244 Error = streaminfo_read_header_sv6(si, HeaderData);
245 if (Error != ERROR_CODE_OK) return Error;
246 #else
247 return ERROR_CODE_INVALIDSV;
248 #endif
251 // estimation, exact value needs too much time
252 si->pcm_samples = 1152 * si->frames - 576;
254 if (si->pcm_samples > 0) {
255 si->average_bitrate =
256 (si->tag_offset -
257 si->header_position) * 8.0 * si->sample_freq / si->pcm_samples;
259 else {
260 si->average_bitrate = 0;
263 return ERROR_CODE_OK;
266 double
267 mpc_streaminfo_get_length(mpc_streaminfo * si)
269 return (double)mpc_streaminfo_get_length_samples(si) /
270 (double)si->sample_freq;
273 mpc_int64_t
274 mpc_streaminfo_get_length_samples(mpc_streaminfo * si)
276 mpc_int64_t samples = (mpc_int64_t) si->frames * MPC_FRAME_LENGTH;
277 if (si->is_true_gapless) {
278 samples -= (MPC_FRAME_LENGTH - si->last_frame_samples);
280 else {
281 samples -= MPC_DECODER_SYNTH_DELAY;
283 return samples;