/* * XmNap A Motif napster client * * Copyright (C) 2000 Mats Peterson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Please send any comments/bug reports to * mats_peterson@swipnet.se (Mats Peterson) */ #include #include #include #include #include "mp3info.h" #include "msgbox.h" #include "util.h" static int bitrateTbl[2][3][16] = { { /* MPEG 2 & 2.5 */ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0}, /* Layer III */ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0}, /* Layer II */ {0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256,0} /* Layer I */ }, { /* MPEG 1 */ {0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,0}, /* Layer III */ {0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384,0}, /* Layer II */ {0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448,0} /* Layer I */ } }; static int freqTbl[4][3] = { {32000, 16000, 8000}, /* MPEG 2.5 */ { 0, 0, 0}, /* reserved */ {22050, 24000, 16000}, /* MPEG 2 */ {44100, 48000, 32000} /* MPEG 1 */ }; MP3INFO* MP3Info(String fileName) { static MP3INFO *info = NULL; FILE *fd; char tmp[128], hdrSize[4]; unsigned long bitHeader; int tryCount = 0, skip, fileSize, hdrSkip; float frameSize; if (! (fd = fopen(fileName, "r"))) { ErrMsg(strerror(errno)); return NULL; } if (info) XtFree((char*)info); info = XtNew(MP3INFO); fseek(fd, 0, SEEK_END); fileSize = ftell(fd); fseek(fd, 0, SEEK_SET); fread(&tmp[1], 1, 3, fd); do { tmp[0]=tmp[1]; tmp[1]=tmp[2]; tmp[2]=tmp[3]; fread(&tmp[3], 1, 1, fd); /* check for ID3v2 tag */ if ((tryCount == 0) && (! strncmp(tmp, "ID3", 3))) { /* skip id3v2 version and flags */ fread(tmp, 1, 2, fd); /* read id3v2 header size */ fread(hdrSize, 1, 4, fd); /* compute bytes to skip */ hdrSkip = ((int)hdrSize[3] | ((int)hdrSize[2] << (8 - 1)) | ((int)hdrSize[1] << (16 - 2)) | ((int)hdrSize[0] << (24 - 3))) + 10; /* skip */ fseek(fd, hdrSkip, SEEK_SET); /* and get (hopefully) the first frame header */ fread(tmp, 1, 4, fd); } bitHeader = (unsigned long)( ( (tmp[0] & 255) << 24) | ( (tmp[1] & 255) << 16) | ( (tmp[2] & 255) << 8) | ( (tmp[3] & 255) ) ); info->sync = (bitHeader >> 21)&0x7ff; info->version = ((bitHeader >> 19)&0x3); info->layer = ((bitHeader >> 17)&0x3); info->bitrate = ((bitHeader >> 12)&0xf); info->freq = ((bitHeader >> 10)&0x3); tryCount++; if (tryCount >= 500) return NULL; } while (info->sync!=0x7ff || info->version==1 || info->layer==0 || info->bitrate==0xf || info->freq==3); info->protect = ((bitHeader >> 16)&0x1); /* get index & calc brate from it */ info->bitrate = bitrateTbl[info->version & 1][info->layer - 1][info->bitrate]; info->freq = freqTbl[info->version][info->freq]; info->padding = ((bitHeader >> 9)&0x1); info->channels = ((bitHeader >> 6)&0x3); info->ext = ((bitHeader >> 4)&0x3); info->copyright = ((bitHeader >> 3)&0x1); info->original = ((bitHeader >> 2)&0x1); info->emphasis = (bitHeader & 0x3); skip=0; /* is there a variable bit rate bit */ if (info->version == 3 ) { /* mpeg version 1 */ if (info->channels == 3) skip = 17; /* Single Channel */ else skip = 32; } else { /* mpeg version 2 or 2.5 */ if (info->channels==3 ) skip = 9; /* Single Channel */ else skip = 17; } /* read next twelve bits in */ fread(tmp, 1, skip, fd); fread(tmp, 1, 12, fd); if (! strncmp("Xing", tmp, 4)) { /* Got a varible bitrate */ bitHeader = (unsigned long) ( (tmp[4] << 24) | (tmp[5] << 16) | (tmp[6] << 8) | (tmp[7] ) ); if (bitHeader & 1) { /* there is frame data */ /* get the num of frames */ bitHeader = (unsigned long)( (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | (tmp[11] ) ); frameSize = (float)fileSize / (float)bitHeader; info->bitrate = (int)(( frameSize * (float)info->freq) / ( 1000.0 * ( (info->layer==3) ? 12.0 : 144.0)) ); } } info->seconds = (8 * fileSize) / 1000; if (info->bitrate) info->seconds = info->seconds/info->bitrate; else info->seconds=0; fclose(fd); return info; } .