2 Routines for handling .mp3 files
4 Part of the swftools package.
6 Copyright (c) 2005 Joel Yliluoma <bisqwit@iki.fi>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
35 struct MP3Frame* next;
39 static const unsigned BR_mpeg1[16] = {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0};
40 static const unsigned BR_mpeg2[16] = {0,8, 16,24,32,40,48,56, 64, 80, 96,112,128,144,160,0};
41 static const unsigned BR_reserved[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
42 static const unsigned*const BR[4] = {BR_mpeg2, BR_reserved, BR_mpeg2, BR_mpeg1};
44 static const unsigned SR_mpeg1[4] = {44100,48000,32000,0};
45 static const unsigned SR_mpeg2[4] = {22050,24000,16000,0};
46 static const unsigned SR_mpeg25[4] = {11025,12000,8000,0};
47 static const unsigned SR_reserved[4] = {0,0,0,0};
48 static const unsigned*const SR[4] = {SR_mpeg25, SR_reserved, SR_mpeg2, SR_mpeg1};
50 int mp3_read(struct MP3*mp3, char* filename)
52 struct MP3Frame* root = 0;
53 struct MP3Frame** cur = &root;
55 unsigned totalsize = 0;
56 unsigned first_samprate = 0;
58 int first_chanmode = -1;
60 FILE*fi = fopen(filename, "rb");
65 unsigned char FrameBuf[2048];
66 unsigned char* hdr = FrameBuf;
67 unsigned char* data = FrameBuf+4;
68 unsigned char* frdata;
70 unsigned char mpegver;
77 if(fread(hdr,1,4,fi) < 4) break;
79 || (hdr[1] & 0xE0) != 0xE0)
81 fprintf(stderr, "readMP3: invalid header %02X %02X %02X %02X\n",
82 hdr[0],hdr[1],hdr[2],hdr[3]);
86 mpegver = (hdr[1] >> 3) & 0x03;
88 bitrate = BR[mpegver][ (hdr[2] >> 4) & 0x0F ] * 1000;
89 samprate = SR[mpegver][ (hdr[2] >> 2) & 0x03 ];
90 chanmode = (hdr[3] >> 6) & 0x03;
92 padding = (hdr[2] & 2) ? 1 : 0;
94 if(!bitrate || !samprate)
99 if(!first_samprate) first_samprate = samprate;
100 else if(first_samprate != samprate)
102 /* Sampling rate changed?!? */
103 fprintf(stderr, "readMP3: sampling rate changed?\n");
106 if(first_chanmode<0) first_chanmode = chanmode;
107 else if(first_chanmode != chanmode)
109 /* Channel mode changed?!? */
110 fprintf(stderr, "readMP3: chanmode changed?\n");
114 framesize = ((mpegver == 3 ? 144 : 72) * bitrate) / samprate + padding;
117 fprintf(stderr, "%02X %02X %02X %02X - bitrate=%u,samprate=%u,chanmode=%u,padding=%u,framesize=%u\n",
118 hdr[0],hdr[1],hdr[2],hdr[3],bitrate,samprate,chanmode,padding,framesize);
120 if(framesize > sizeof(FrameBuf)) break;
121 if(fread(data, 1, framesize - 4, fi) < framesize-4)
123 fprintf(stderr, "readMP3: short read at frame %u\n", nframes);
127 if(!bitrate || !samprate) continue;
129 frdata = (unsigned char*)malloc(framesize);
132 fprintf(stderr, "readMP3: malloc failed\n");
136 *cur = (struct MP3Frame*)malloc(sizeof(*root));
139 fprintf(stderr, "readMP3: malloc failed\n");
145 (*cur)->bitrate = bitrate;
146 (*cur)->samprate = samprate;
147 (*cur)->chanmode = chanmode;
148 (*cur)->framesize = framesize;
149 (*cur)->data = frdata;
151 memcpy(frdata, FrameBuf, framesize);
154 totalsize += framesize;
159 fprintf(stderr, "readMP3: not a MP3 file\n");
164 fprintf(stderr, "readMP3: read %u frames (%u bytes)\n", nframes, totalsize);
167 mp3->SampRate = first_samprate;
168 mp3->Channels = first_chanmode == 3 ? 1 : 2;
169 mp3->NumFrames = nframes;
170 mp3->size = totalsize;
171 mp3->data = (unsigned char*)malloc(mp3->size);
176 for(it=root; it; it=it->next)
178 memcpy(mp3->data + pos, it->data, it->framesize);
179 pos += it->framesize;
184 fprintf(stderr, "readMP3: malloc failed\n");
189 struct MP3Frame* next = root->next;
195 return mp3->data != NULL;
198 void mp3_clear(struct MP3*mp3)