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
, const 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 if(hdr
[0] == 'I' && hdr
[1] == 'D' && hdr
[2] == '3')
82 unsigned id3_size
= 0;
83 if(fread(FrameBuf
, 1, 6, fi
) < 6) break;
85 id3_size
= (FrameBuf
[5])
88 + (FrameBuf
[2] << 21);
89 fprintf(stderr
, "readMP3: skipping ID3 tag (10+%u bytes)\n", id3_size
);
90 if(fseek(fi
, id3_size
, SEEK_CUR
) < 0)
92 /* Cannot seek? Try reading. */
93 char* tmpbuf
= (char*)malloc(id3_size
);
97 fprintf(stderr
, "readMP3: fseek and malloc both failed?\n");
100 nread
= fread(tmpbuf
, 1, id3_size
, fi
);
102 if(nread
< id3_size
) break;
109 || (hdr
[1] & 0xE0) != 0xE0)
111 fprintf(stderr
, "readMP3: invalid header %02X %02X %02X %02X\n",
112 hdr
[0],hdr
[1],hdr
[2],hdr
[3]);
116 mpegver
= (hdr
[1] >> 3) & 0x03;
118 bitrate
= BR
[mpegver
][ (hdr
[2] >> 4) & 0x0F ] * 1000;
119 samprate
= SR
[mpegver
][ (hdr
[2] >> 2) & 0x03 ];
120 chanmode
= (hdr
[3] >> 6) & 0x03;
122 padding
= (hdr
[2] & 2) ? 1 : 0;
124 if(!bitrate
|| !samprate
)
129 if(!first_samprate
) first_samprate
= samprate
;
130 else if(first_samprate
!= samprate
)
132 /* Sampling rate changed?!? */
133 fprintf(stderr
, "readMP3: sampling rate changed?\n");
136 if(first_chanmode
<0) first_chanmode
= chanmode
;
137 else if(first_chanmode
!= chanmode
)
139 /* Channel mode changed?!? */
140 fprintf(stderr
, "readMP3: chanmode changed?\n");
144 framesize
= ((mpegver
== 3 ? 144 : 72) * bitrate
) / samprate
+ padding
;
147 fprintf(stderr, "%02X %02X %02X %02X - bitrate=%u,samprate=%u,chanmode=%u,padding=%u,framesize=%u\n",
148 hdr[0],hdr[1],hdr[2],hdr[3],bitrate,samprate,chanmode,padding,framesize);
150 if(framesize
> sizeof(FrameBuf
)) break;
151 if(fread(data
, 1, framesize
- 4, fi
) < framesize
-4)
153 fprintf(stderr
, "readMP3: short read at frame %u\n", nframes
);
157 if(!bitrate
|| !samprate
) continue;
159 frdata
= (unsigned char*)malloc(framesize
);
162 fprintf(stderr
, "readMP3: malloc failed\n");
166 *cur
= (struct MP3Frame
*)malloc(sizeof(*root
));
169 fprintf(stderr
, "readMP3: malloc failed\n");
175 (*cur
)->bitrate
= bitrate
;
176 (*cur
)->samprate
= samprate
;
177 (*cur
)->chanmode
= chanmode
;
178 (*cur
)->framesize
= framesize
;
179 (*cur
)->data
= frdata
;
181 memcpy(frdata
, FrameBuf
, framesize
);
184 totalsize
+= framesize
;
189 fprintf(stderr
, "readMP3: not a MP3 file\n");
195 fprintf(stderr, "readMP3: read %u frames (%u bytes)\n", nframes, totalsize);
198 mp3
->SampRate
= first_samprate
;
199 mp3
->Channels
= first_chanmode
== 3 ? 1 : 2;
200 mp3
->NumFrames
= nframes
;
201 mp3
->size
= totalsize
;
202 mp3
->data
= (unsigned char*)malloc(mp3
->size
);
207 for(it
=root
; it
; it
=it
->next
)
209 memcpy(mp3
->data
+ pos
, it
->data
, it
->framesize
);
210 pos
+= it
->framesize
;
215 fprintf(stderr
, "readMP3: malloc failed\n");
220 struct MP3Frame
* next
= root
->next
;
227 return mp3
->data
!= NULL
;
230 void mp3_clear(struct MP3
*mp3
)