/*
Copyright (C) JAEHYUK CHO
All rights reserved.
Code by JaeHyuk Cho <mailto:minzkn@minzkn.com>
*/
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64)
# include <windows.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <io.h>
# include <direct.h>
# include <stdio.h>
# include <fcntl.h>
# if !defined(O_RDONLY)
# define O_RDONLY _O_RDONLY
# endif
# if !defined(ssize_t)
# define ssize_t int
# endif
#else
# include <sys/types.h>
# include <stdio.h>
# include <unistd.h>
# include <fcntl.h>
#endif
#if !defined(t_mzmp3_byte)
# if defined(BYTE)
# define t_mzmp3_byte BYTE
# else
# define t_mzmp3_byte unsigned char
# endif
#endif
#if !defined(t_mzmp3_word)
# if defined(WORD)
# define t_mzmp3_word WORD
# else
# define t_mzmp3_word short unsigned int
# endif
#endif
#if !defined(t_mzmp3_dword)
# if defined(DWORD)
# define t_mzmp3_dword DWORD
# else
# define t_mzmp3_dword long unsigned int
# endif
#endif
static t_mzmp3_dword (mzmp3_duration)(const char *s_filename)
{
static const t_mzmp3_word cg_bi[][3][16] = { /* bitrate index table */
{ /* v2.5 */
/* layer 1 */ {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0},
/* layer 2 */ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
/* layer 3 */ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
},
{ /* reserved version */
{0,},{0,},{0,}
},
{ /* v2.0 (ISO/IEC 13818-3) */
/* layer 1 */ {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0},
/* layer 2 */ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
/* layer 3 */ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
},
{ /* v1.0 (ISO/IEC 11172-3) */
/* layer 1 */ {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},
/* layer 2 */ {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
/* layer 3 */ {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}
}
};
static const t_mzmp3_word cg_fi[][4] = { /* frequency index table */
/* v2.5 */ {11025, 12000, 8000, 0},
/* reserved version */ {0,},
/* v2.0 */ {22050, 24000, 16000, 0},
/* v1.0 */ {44100, 48000, 32000, 0}
};
int s_fd;
t_mzmp3_dword s_dword = (t_mzmp3_dword)0, s_v = (t_mzmp3_dword)0, s_l, s_bi, s_fi = (t_mzmp3_dword)0, s_p, s_fs, s_fc = (t_mzmp3_dword)0, s_ss = (t_mzmp3_dword)0;
t_mzmp3_byte s_byte;
if((s_fd = open(s_filename, O_RDONLY)) == (-1))return((t_mzmp3_dword)0);
while((read(s_fd, (void *)(&s_byte), (size_t)sizeof(s_byte)) > ((ssize_t)0)) && ((++s_ss) < ((t_mzmp3_dword)(256 << 10))))
{
s_dword = (s_dword << 8) | ((t_mzmp3_dword)s_byte); /* shift charge fourcc */
if((s_dword & ((t_mzmp3_dword)0xffe00000)) != ((t_mzmp3_dword)0xffe00000))continue; /* fourcc header filter */
if((s_v = (s_dword >> 19) & ((t_mzmp3_dword)3)) == ((t_mzmp3_dword)1))continue; /* version id */
if((s_l = ((t_mzmp3_dword)3) - ((s_dword >> 17) & ((t_mzmp3_dword)3))) == ((t_mzmp3_dword)0))continue; /* layer type */
if((s_bi = (s_dword >> 12) & ((t_mzmp3_dword)15)) == ((t_mzmp3_dword)15))continue; /* bitrate index */
if((s_fi = (s_dword >> 10) & ((t_mzmp3_dword)3)) == ((t_mzmp3_dword)3))continue; /* frequency index */
s_p = (s_dword >> 9) & ((t_mzmp3_dword)1); /* padding */
switch(s_l)
{
case 0: /* layer 1 */
s_fs = ((((((t_mzmp3_dword)12000) * ((t_mzmp3_dword)cg_bi[s_v][s_l][s_bi])) / ((t_mzmp3_dword)cg_fi[s_v][s_fi])) + s_p) << 2) - ((t_mzmp3_dword)4);
break;
case 1: /* layer 2 */
s_fs = ((((t_mzmp3_dword)144000) * ((t_mzmp3_dword)cg_bi[s_v][s_l][s_bi])) / ((t_mzmp3_dword)cg_fi[s_v][s_fi])) + s_p - ((t_mzmp3_dword)4);
break;
case 2: /* layer 3 */
default:
s_fs = ((((t_mzmp3_dword)144000) * ((t_mzmp3_dword)cg_bi[s_v][s_l][s_bi])) / (((t_mzmp3_dword)cg_fi[s_v][s_fi]) << ((s_v == ((t_mzmp3_dword)3)) ? 0 : 1))) + s_p - ((t_mzmp3_dword)4);
break;
}
s_dword = (t_mzmp3_dword)0; /* reset fourcc */
if((s_fs > ((t_mzmp3_dword)0)) && (s_fs < ((t_mzmp3_dword)(64 << 10))))
{ /* move position */
s_fc++;
s_ss = (t_mzmp3_dword)0; /* skip size */
if(lseek(s_fd, (off_t)s_fs, SEEK_CUR) == ((off_t)(-1)))break;
}
}
close(s_fd);
return(((s_fc * ((t_mzmp3_dword)1152)) / cg_fi[s_v][s_fi]) >> ((s_v == ((t_mzmp3_dword)3)) ? 0 : 1));
}
int main(int s_argc, char **s_argv)
{
int s_count = 0; unsigned long int s_duration;
if(s_argc < 2){ (void)fprintf(stderr, "mp3_time <mp3 file>\n"); return(0); }
while((++s_count) < s_argc)
{
s_duration = (unsigned long int)mzmp3_duration(s_argv[s_count]);
(void)fprintf(stdout, "\"%s\" - %02lu:%02lu:%02lu\n",
s_argv[s_count], s_duration / 3600ul, s_duration / 60ul, s_duration % 60ul);
}
return(0);
}
/* End of source */