40 #ifdef HAVE_SYS_STAT_H
44 #define INPUT_BUFFER_SIZE 16*1024
45 #define MAD_AVERAGE_FRAMES 10
46 #define DO_FAST_CALC 1
47 #define XING_MAGIC1 ( ('X' << 24) | ('i' << 16) | ('n' << 8) | 'g' )
48 #define XING_MAGIC2 ( ('I' << 24) | ('n' << 16) | ('f' << 8) | 'o' )
55 unsigned char toc[100];
67 #undef DETECT_BY_CONTENT_NOT_BORKEN
68 #ifdef DETECT_BY_CONTENT_NOT_BORKEN
76 static short mp3_content_check(FILE *
const in)
78 unsigned char tmp[1024];
85 read = (int)fread(tmp, (
size_t)1, (size_t)1024, in);
87 for (i=0; i<read; i++) {
88 if (tmp[i] != (
unsigned char)0x00)
96 if ((tmp[i] == (
unsigned char)0xff) && ((tmp[i+1] & (
unsigned char)0xfe) == (
unsigned char)0xfa))
98 if ((tmp[i] == (
unsigned char)0xff) && ((tmp[i+1] & (
unsigned char)0xfe) == (
unsigned char)0xfc))
100 if ((tmp[i] == (
unsigned char)
'I') && (tmp[i+1] == (
unsigned char)
'D') && (tmp[i+2] == (
unsigned char)
'3'))
118 unsigned long xing_magic;
123 xing_magic = mad_bit_read(&ptr, 32);
127 xing->
flags = mad_bit_read(&ptr, 32);
134 xing->
frames = mad_bit_read(&ptr, 32);
142 xing->
bytes = mad_bit_read(&ptr, 32);
147 register unsigned short i;
152 for (i = 0; i < 100; ++i)
153 xing->
toc[i] = mad_bit_read(&ptr, 8);
162 xing->
scale = mad_bit_read(&ptr, 32);
180 #ifndef DETECT_BY_CONTENT_NOT_BORKEN
183 const char *
const ext = strrchr(filename,
'.');
184 if (ext && (!strncasecmp(ext,
".mp3", 4) || !strncasecmp(ext,
".mp2", 4)))
206 unsigned short index)
208 const struct id3_frame *frame = NULL;
209 const union id3_field *field = NULL;
210 const id3_ucs4_t *ucs4 = NULL;
211 unsigned int nstrings, i, mp3gid;
213 if ((frame = id3_tag_findframe (tag, frameid, index))) {
214 field = id3_frame_field(frame, 1);
215 nstrings = id3_field_getnstrings(field);
216 for (i = 0; i < nstrings; ++i) {
217 if ((ucs4 = id3_field_getstrings(field, i))) {
218 if (strcmp(frameid, ID3_FRAME_GENRE) == 0) {
221 if ((ucs4[0] ==
'(') && (isdigit(ucs4[1]))) {
222 mp3gid = id3_ucs4_getnumber(ucs4+1);
223 ucs4 = id3_genre_index(mp3gid);
226 ucs4 = id3_genre_name(ucs4);
228 return(id3_ucs4_utf8duplicate(ucs4));
253 const char *
const filename)
258 struct id3_file *id3struct = NULL;
259 struct id3_tag *tag = NULL;
260 id3_utf8_t *utf8 = NULL;
262 struct stat filestat;
264 struct mad_stream madstream;
265 struct mad_header madheader;
266 struct mad_frame madframe;
267 struct xing xing = { .
frames = 0, .bytes = 0 };
270 size_t madread_size, remaining;
271 mad_timer_t madduration = mad_timer_zero;
273 unsigned short has_xing = 0;
274 unsigned long tagsize = 0, data_used = 0,
frames = 0;
276 #ifdef DETECT_BY_CONTENT_NOT_BORKEN
277 if (mp3_content_check(in))
283 fstat(fileno(in), &filestat);
292 p->
size = filestat.st_size;
293 p->
mtime = filestat.st_mtime;
296 if ((id3struct = id3_file_open(filename, ID3_FILE_MODE_READONLY))) {
297 if ((tag = id3_file_tag(id3struct)) && (tag->frames)) {
316 p->
date = atoi((
char *)utf8);
321 p->
track = atoi((
char *)utf8);
326 p->
posn = atoi((
char *)utf8);
331 if ((atoi((
char *)utf8) / 1000) > 0)
332 p->
length = atoi((
char *)utf8) / 1000;
341 id3_file_close (id3struct);
349 mad_stream_init(&madstream);
350 mad_header_init(&madheader);
351 mad_frame_init(&madframe);
355 remaining = madstream.bufend - madstream.next_frame;
356 memcpy(madinput_buffer, madstream.this_frame, remaining);
357 madread_size = fread(madinput_buffer + remaining, 1,
INPUT_BUFFER_SIZE - remaining, in);
359 if (madread_size <= 0) {
360 mi_rdebug(
"maderror madread_size <= 0 on %s", filename);
365 mad_stream_buffer(&madstream, madinput_buffer, madread_size + remaining);
368 if (mad_header_decode(&madheader, &madstream) == -1) {
369 if (madstream.error == MAD_ERROR_BUFLEN)
371 if (!MAD_RECOVERABLE(madstream.error)) {
373 mi_rdebug(
"maderror unrecoverable header decode on %s", filename);
376 if (madstream.error == MAD_ERROR_LOSTSYNC) {
378 tagsize = id3_tag_query(madstream.this_frame, madstream.bufend - madstream.this_frame);
380 mad_stream_skip(&madstream, tagsize);
388 mad_timer_add(&madduration, madheader.duration);
389 data_used += madstream.next_frame - madstream.this_frame;
393 p->
freq = madheader.samplerate;
394 p->
bitrate = madheader.bitrate;
397 madframe.header = madheader;
398 if (mad_frame_decode(&madframe, &madstream) == -1) {
399 if (!MAD_RECOVERABLE(madstream.error)) {
401 mi_rdebug(
"maderror unrecoverable frame decode on %s", filename);
406 if (
xing_parse(&xing, madstream.anc_ptr, madstream.anc_bitlen) == 0) {
413 mad_timer_multiply(&madduration,
frames);
414 p->
bitrate = 8 * xing.
bytes / mad_timer_count(madduration, MAD_UNITS_SECONDS);
421 if (p->
bitrate != madheader.bitrate)
424 p->
bitrate += madheader.bitrate;
438 mad_timer_multiply(&madduration,
frames);
454 p->
length = mad_timer_count(madduration, MAD_UNITS_SECONDS);
457 mad_frame_finish(&madframe);
458 mad_header_finish(&madheader);
459 mad_stream_finish(&madstream);