이 소스의 목적은 MP3파일의 재생시간을 검출하는 것입니다. 간략화 구현한것이라서 조금 검출속도가 느린편입니다.
파일 열고
2. 헤더 찾고 (0xffe00000)
3. 각 정보 추출후 실제 MP3가 사용 가능한 정보인지 구분하고
4. Frame 수를 누적하여 더한후 적정 Sampling 주파수로 나누어서 초단위 시간을 계산하고
5. 파일 닫고
6. 결과 출력하고...
MPEG audio header 를 간략히 정리하면 다음과 같습니다.
/* MPEG audio header
Edit by JaeHyuk Cho <mailto@infoeq.com>
*/
#define Frame header preview
32bit big endian - AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
#define Frame header bit index
A[31..21] : Frame sync
B[20..19] : MPEG audio version indentification
C[18..17] : Layer description
D[16] : Protection bit
E[15..12] : Bitrate index
F[11..10] : Sampling rate frequency index
G[9] : Padding bit
H[8] : Private bit
I[7..6] : Channel mode
J[5..4] : Mode extension
K[3] : Copyright
L[2] : Original
M[1..0] : Emphasis
#define Frame header description
A: 11bit - Frame sync (All bit '1')
'11111111 111'
B: 2bit - MPEG audio version identification
'00': MPEG version 2.5
'01': Reserved
'10': MPEG version 2.0 (ISO/IEC 13818-3)
'11': MPEG version 1.0 (ISO/IEC 11172-3)
C: 2bit - Layer description
'00': Reserved
'01': Layer III
'10': Layer II
'11': Layer I
D: 1bit - Protection bit
'0': Protected by CRC (16bit crc follow header)
'1': Not protected
E: 4bit - Bitrate index
See also mpeg_audio_bitrate.txt
F: 2bit - Sampling rate frequency index
MPEG version 1.0
'00': 44100
'01': 48000
'10': 32000
'11': Reserved
MPEG version 2.0
'00': 22050
'01': 24000
'10': 16000
'11': Reserved
MPEG version 2.5
'00': 11025
'01': 12000
'10': 8000
'11': Reserved
G: 1bit - Padding bit
'0': Frame is not padded
'1': Frame is padded with one extra slot
Layer I frame size
((12000 * Bitrate / Samplerate) + Padding) * 4
Layer II/III frame size
(144000 * Bitrate / Samplerate) + Padding
H: 1bit - Private bit
I: 2bit - Channel mode
'00': Stereo
'01': Joint stereo (Stereo)
'10': Dual channel (Stereo)
'11': Single channel (Mono)
J: 2bit - Mode extension (Only if joint stereo)
Layer I/II
'00': Bands 4 to 31
'01': Bands 8 to 31
'10': Bands 12 to 31
'11': Bands 16 to 31
Layer III
'00': Intensity stereo off, MS stereo off
'01': Intensity stereo on , MS stereo off
'10': Intensity stereo off, MS stereo on
'11': Intensity stereo on , MS stereo on
K: 1bit - Copyright
'0': Audio is not copyrighted
'1': Audio is copyrighted
L: 1bit - Original
'0': Copy of original media
'1': Original media
M: 2bit - Emphasis
'00': None
'01': 50/15ms
'10': Reserved
'11': CCIT J.17
/* End of README */
그리고 Bitrate table은 다음을 참조합니다.
/* MPEG audio bitrate table
Edit by JaeHyuk Cho <mailto:minzkn@infoeq.com>
*/
#define hint
A: MPEG version 1.0, Layer I
B: V1,Layer II
C: V1,Layer III
D: V2,Layer I
E: V2, L2 & L3
-: Free format
x: Not use (Invalid bitrate !)
#define table
[A] [B] [C] [D] [E]
0000 - - - - -
0001 32 32 32 32 8
0010 64 48 40 48 16
0011 96 56 48 56 24
0100 128 64 56 64 32
0101 160 80 64 80 40
0110 192 96 80 96 48
0111 224 112 96 112 56
1000 256 128 112 128 64
1001 288 160 128 144 80
1010 320 192 160 160 96
1011 352 224 192 176 112
1100 384 256 224 192 128
1101 416 320 256 224 144
1110 448 384 320 256 160
1111 x x x x x
/* End of README */
설명
- 파일 열고
2. 헤더 찾고 (0xffe00000) 3. 각 정보 추출후 실제 MP3가 사용 가능한 정보인지 구분하고 4. Frame 수를 누적하여 더한후 적정 Sampling 주파수로 나누어서 초단위 시간을 계산하고 5. 파일 닫고 6. 결과 출력하고... MPEG audio header 를 간략히 정리하면 다음과 같습니다./* MPEG audio header Edit by JaeHyuk Cho <mailto@infoeq.com> */ #define Frame header preview 32bit big endian - AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM #define Frame header bit index A[31..21] : Frame sync B[20..19] : MPEG audio version indentification C[18..17] : Layer description D[16] : Protection bit E[15..12] : Bitrate index F[11..10] : Sampling rate frequency index G[9] : Padding bit H[8] : Private bit I[7..6] : Channel mode J[5..4] : Mode extension K[3] : Copyright L[2] : Original M[1..0] : Emphasis #define Frame header description A: 11bit - Frame sync (All bit '1') '11111111 111' B: 2bit - MPEG audio version identification '00': MPEG version 2.5 '01': Reserved '10': MPEG version 2.0 (ISO/IEC 13818-3) '11': MPEG version 1.0 (ISO/IEC 11172-3) C: 2bit - Layer description '00': Reserved '01': Layer III '10': Layer II '11': Layer I D: 1bit - Protection bit '0': Protected by CRC (16bit crc follow header) '1': Not protected E: 4bit - Bitrate index See also mpeg_audio_bitrate.txt F: 2bit - Sampling rate frequency index MPEG version 1.0 '00': 44100 '01': 48000 '10': 32000 '11': Reserved MPEG version 2.0 '00': 22050 '01': 24000 '10': 16000 '11': Reserved MPEG version 2.5 '00': 11025 '01': 12000 '10': 8000 '11': Reserved G: 1bit - Padding bit '0': Frame is not padded '1': Frame is padded with one extra slot Layer I frame size ((12000 * Bitrate / Samplerate) + Padding) * 4 Layer II/III frame size (144000 * Bitrate / Samplerate) + Padding H: 1bit - Private bit I: 2bit - Channel mode '00': Stereo '01': Joint stereo (Stereo) '10': Dual channel (Stereo) '11': Single channel (Mono) J: 2bit - Mode extension (Only if joint stereo) Layer I/II '00': Bands 4 to 31 '01': Bands 8 to 31 '10': Bands 12 to 31 '11': Bands 16 to 31 Layer III '00': Intensity stereo off, MS stereo off '01': Intensity stereo on , MS stereo off '10': Intensity stereo off, MS stereo on '11': Intensity stereo on , MS stereo on K: 1bit - Copyright '0': Audio is not copyrighted '1': Audio is copyrighted L: 1bit - Original '0': Copy of original media '1': Original media M: 2bit - Emphasis '00': None '01': 50/15ms '10': Reserved '11': CCIT J.17 /* End of README *//* MPEG audio bitrate table Edit by JaeHyuk Cho <mailto:minzkn@infoeq.com> */ #define hint A: MPEG version 1.0, Layer I B: V1,Layer II C: V1,Layer III D: V2,Layer I E: V2, L2 & L3 -: Free format x: Not use (Invalid bitrate !) #define table [A] [B] [C] [D] [E] 0000 - - - - - 0001 32 32 32 32 8 0010 64 48 40 48 16 0011 96 56 48 56 24 0100 128 64 56 64 32 0101 160 80 64 80 40 0110 192 96 80 96 48 0111 224 112 96 112 56 1000 256 128 112 128 64 1001 288 160 128 144 80 1010 320 192 160 160 96 1011 352 224 192 176 112 1100 384 256 224 192 128 1101 416 320 256 224 144 1110 448 384 320 256 160 1111 x x x x x /* End of README */사용방법
코드
/* Copyright (c) 2002 Information Equipment co.,LTD. KOREA All Right Reserved. [ http://www.infoeq.com ] Code by JaeHyuk Cho < minzkn@infoeq.co.kr > 2002.10.15 */ #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> int main(int s_Argc, char **s_Argv); unsigned long MZ_MP3_Time(char *s_MP3_Name); int g_BitrateIndexTable[4][3][16] = { { // Version 2.5 { // Layer I 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, (-1) }, { // Layer II 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, (-1) }, { // Layer III 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, (-1) } }, { // Version reserved {0,},{0,},{0,} }, { // Version 2.0 (ISO / IEC 13818-3) { // Layer I 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, (-1) }, { // Layer II 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, (-1) }, { // Layer III 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, (-1) } }, { // Version 1.0 (ISO / IEC 11172-3) { // Layer I 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, (-1) }, { // Layer II 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, (-1) }, { // Layer III 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, (-1) } } }; int g_FrequencyTable[4][4] = { { // Version 2.5 11025, 12000, 8000, (-1) }, { // Version reserved (-1), }, { // Version 2.0 22050, 24000, 16000, (-1) }, { // Version 1.0 44100, 48000, 32000, (-1) } }; char *g_ChannelModeString[] = { "Stereo", "Joint steroeo", "Dual stereo", "Single stereo" }; char *g_LayerString[] = { "Layer I", "Layer II", "Layer III" }; int main(int s_Argc, char **s_Argv) { int s_Return = 0; if(s_Argc >= 2) { int s_Count; int s_Hour, s_Min, s_Sec; for(s_Count = 1;s_Count < s_Argc;s_Count++) { s_Return = MZ_MP3_Time(s_Argv[s_Count]); if(s_Return > 0) { s_Sec = s_Return % 60; s_Min = s_Return / 60; s_Hour = s_Return / 3600; fprintf(stdout, "\"%s\" - %02d:%02d:%02d\n", s_Argv[s_Count], s_Hour, s_Min, s_Sec); } else fprintf(stdout, "\"%s\" - Unknown MP3 format\n", s_Argv[s_Count]); } } else fprintf(stderr, "mp3_time <mp3 file>\n"); return(s_Return); } unsigned long MZ_MP3_Time(char *s_MP3_Name) { unsigned long s_Return = 0lu; if(s_MP3_Name) { int s_Handle; s_Handle = open(s_MP3_Name, O_RDONLY); if(s_Handle >= 0) { int s_ReadSize; unsigned long s_Header = 0lu; unsigned char s_Buffer; unsigned long s_VersionID = 0lu, s_Layer = 0lu, s_BitrateIndex = 0lu, s_FrequencyIndex = 0lu, s_Padding = 0lu; //unsigned long s_Protection = 0lu, s_ChannelMode = 0lu, s_ModeExtension = 0lu, s_Copyright = 0lu, s_Original = 0lu, s_Emphasis = 0lu; unsigned long s_FrameSize = 0lu, s_FrameCount = 0lu; do { s_ReadSize = read(s_Handle, &s_Buffer, sizeof(unsigned char)); if(s_ReadSize > 0) { s_Header = (s_Header << 8) | (unsigned long)(s_Buffer & 0xff); if((s_Header & 0xffe00000lu) == 0xffe00000lu) { s_VersionID = (s_Header >> 19) & 0x03; s_Layer = (s_Header >> 17) & 0x03; //s_Protection = (s_Header >> 16) & 0x01; s_BitrateIndex = (s_Header >> 12) & 0x0f; s_FrequencyIndex = (s_Header >> 10) & 0x03; s_Padding = (s_Header >> 9) & 0x01; //s_ChannelMode = (s_Header >> 6) & 0x03; //s_ModeExtension = (s_Header >> 4) & 0x03; //s_Copyright = (s_Header >> 3) & 0x01; //s_Original = (s_Header >> 2) & 0x01; //s_Emphasis = (s_Header >> 0) & 0x03; if(s_VersionID != 0x01 && s_Layer != 0x00 && s_BitrateIndex != 0x0f && s_BitrateIndex != 0 && s_FrequencyIndex != 0x03 ) { switch((3 - s_Layer)) { case 0: // Layer I s_FrameSize = 12000lu * g_BitrateIndexTable[s_VersionID][3 - s_Layer][s_BitrateIndex]; s_FrameSize /= g_FrequencyTable[s_VersionID][s_FrequencyIndex]; s_FrameSize = ((s_FrameSize + s_Padding)<<2) - 4; break; case 1: // Layer II s_FrameSize = 144000lu * g_BitrateIndexTable[s_VersionID][3 - s_Layer][s_BitrateIndex]; s_FrameSize /= g_FrequencyTable[s_VersionID][s_FrequencyIndex]; s_FrameSize += s_Padding - 4; case 2: // Layer III default: s_FrameSize = 144000lu * g_BitrateIndexTable[s_VersionID][3 - s_Layer][s_BitrateIndex]; s_FrameSize /= g_FrequencyTable[s_VersionID][s_FrequencyIndex] << (s_VersionID == 0x03 ? 0 : 1); s_FrameSize = s_FrameSize + s_Padding - 4; break; } s_Header = 0lu; if(s_FrameSize > 0) { s_FrameCount++; lseek(s_Handle, s_FrameSize, SEEK_CUR); } } } } }while(s_ReadSize > 0); close(s_Handle); s_Return = (((s_FrameCount * 1152) / g_FrequencyTable[s_VersionID][s_FrequencyIndex]) >> (s_VersionID == 0x03 ? 0 : 1)); } else fprintf(stderr, "mp3_time.c: MZ_MP3_Time - [ERROR] Can not open mp3 \"%s\" !!!\n", s_MP3_Name); } else fprintf(stderr, "mp3_time.c: MZ_MP3_Time - [ERROR] s_MP3_Name is null !!!\n"); return(s_Return); } /* End of source */변경사항
2005/05/14
Recent Posts
Archive Posts
Tags