diff -NaHudr swftools-2005-09-25-1334/lib/modules/swfsound.c swftools-updated/lib/modules/swfsound.c --- swftools-2005-09-25-1334/lib/modules/swfsound.c 2005-08-16 17:43:14.000000000 +0300 +++ swftools-updated/lib/modules/swfsound.c 2005-10-11 23:50:49.643820000 +0300 @@ -312,3 +312,25 @@ } +void swf_SetSoundDefineMP3(TAG*tag, U8* data, unsigned length, + unsigned SampRate, + unsigned Channels, + unsigned NumFrames) +{ + U8 compression = 2; // 0 = raw, 1 = ADPCM, 2 = mp3, 3 = raw le, 6 = nellymoser + U8 rate; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz + U8 size = 1; // 0 = 8 bit, 1 = 16 bit + U8 type = Channels==2; // 0=mono, 1=stereo + + rate = (SampRate >= 40000) ? 3 + : (SampRate >= 19000) ? 2 + : (SampRate >= 8000) ? 1 + : 0; + + swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type); + + swf_SetU32(tag, NumFrames * 576); + + swf_SetU16(tag, 0); //delayseek + swf_SetBlock(tag, data, length); +} diff -NaHudr swftools-2005-09-25-1334/lib/rfxswf.h swftools-updated/lib/rfxswf.h --- swftools-2005-09-25-1334/lib/rfxswf.h 2005-09-18 16:26:03.000000000 +0300 +++ swftools-updated/lib/rfxswf.h 2005-10-11 23:40:06.175642032 +0300 @@ -746,6 +746,10 @@ void swf_SetSoundStreamHead(TAG*tag, int avgnumsamples); void swf_SetSoundStreamBlock(TAG*tag, S16*samples, int seek, char first); /* expects 2304 samples */ void swf_SetSoundDefine(TAG*tag, S16*samples, int num); +void swf_SetSoundDefineMP3(TAG*tag, U8* data, unsigned length, + unsigned SampRate, + unsigned Channels, + unsigned NumFrames); void swf_SetSoundInfo(TAG*tag, SOUNDINFO*info); // swftools.c diff -NaHudr swftools-2005-09-25-1334/mp3.c swftools-updated/mp3.c --- swftools-2005-09-25-1334/mp3.c 1970-01-01 02:00:00.000000000 +0200 +++ swftools-updated/mp3.c 2005-10-12 01:52:35.393177280 +0300 @@ -0,0 +1,197 @@ +/* mp3.c + Routines for handling .mp3 files + + Part of the swftools package. + + Copyright (c) 2005 Joel Yliluoma + + 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; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include +#include +#include + +#include "mp3.h" + +struct MP3Frame +{ + unsigned bitrate; + unsigned samprate; + unsigned chanmode; + unsigned framesize; + unsigned char* data; + struct MP3Frame* next; +}; + +// 0 4 8 C +static const unsigned BR_mpeg1[16] = {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}; +static const unsigned BR_mpeg2[16] = {0,8, 16,24,32,40,48,56, 64, 80, 96,112,128,144,160,0}; +static const unsigned BR_reserved[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; +static const unsigned*const BR[4] = {BR_mpeg2, BR_reserved, BR_mpeg2, BR_mpeg1}; + +static const unsigned SR_mpeg1[4] = {44100,48000,32000,0}; +static const unsigned SR_mpeg2[4] = {22050,24000,16000,0}; +static const unsigned SR_mpeg25[4] = {11025,12000,8000,0}; +static const unsigned SR_reserved[4] = {0,0,0,0}; +static const unsigned*const SR[4] = {SR_mpeg25, SR_reserved, SR_mpeg2, SR_mpeg1}; + +int readMP3(char* filename, struct MP3*mp3) +{ + struct MP3Frame* root = 0; + struct MP3Frame** cur = &root; + + unsigned totalsize = 0; + unsigned first_samprate = 0; + unsigned nframes = 0; + int first_chanmode = -1; + + FILE*fi = fopen(filename, "rb"); + if(!fi) return 0; + + for(;;) + { + unsigned char FrameBuf[2048]; + unsigned char* hdr = FrameBuf; + unsigned char* data = FrameBuf+4; + unsigned char* frdata; + + unsigned char mpegver; + unsigned padding; + unsigned bitrate; + unsigned samprate; + unsigned framesize; + int chanmode; + + if(fread(hdr,1,4,fi) < 4) break; + if(hdr[0] != 0xFF + || (hdr[1] & 0xE0) != 0xE0) + { + fprintf(stderr, "readMP3: invalid header %02X %02X %02X %02X\n", + hdr[0],hdr[1],hdr[2],hdr[3]); + break; + } + + mpegver = (hdr[1] >> 3) & 0x03; + + bitrate = BR[mpegver][ (hdr[2] >> 4) & 0x0F ] * 1000; + samprate = SR[mpegver][ (hdr[2] >> 2) & 0x03 ]; + chanmode = (hdr[3] >> 6) & 0x03; + + padding = (hdr[2] & 2) ? 1 : 0; + + if(!bitrate || !samprate) + { + /* Invalid frame */ + /*break;*/ + } + if(!first_samprate) first_samprate = samprate; + else if(first_samprate != samprate) + { + /* Sampling rate changed?!? */ + fprintf(stderr, "readMP3: sampling rate changed?\n"); + /*break;*/ + } + if(first_chanmode<0) first_chanmode = chanmode; + else if(first_chanmode != chanmode) + { + /* Channel mode changed?!? */ + fprintf(stderr, "readMP3: chanmode changed?\n"); + /*break;*/ + } + + framesize = ((mpegver == 3 ? 144 : 72) * bitrate) / samprate + padding; + +/* + fprintf(stderr, "%02X %02X %02X %02X - bitrate=%u,samprate=%u,chanmode=%u,padding=%u,framesize=%u\n", + hdr[0],hdr[1],hdr[2],hdr[3],bitrate,samprate,chanmode,padding,framesize); +*/ + if(framesize > sizeof(FrameBuf)) break; + if(fread(data, 1, framesize - 4, fi) < framesize-4) + { + fprintf(stderr, "readMP3: short read at frame %u\n", nframes); + break; + } + + if(!bitrate || !samprate) continue; + + frdata = (unsigned char*)malloc(framesize); + if(!frdata) + { + fprintf(stderr, "readMP3: malloc failed\n"); + break; + } + + *cur = (struct MP3Frame*)malloc(sizeof(*root)); + if(!*cur) + { + fprintf(stderr, "readMP3: malloc failed\n"); + free(frdata); + break; + } + + (*cur)->next = 0; + (*cur)->bitrate = bitrate; + (*cur)->samprate = samprate; + (*cur)->chanmode = chanmode; + (*cur)->framesize = framesize; + (*cur)->data = frdata; + + memcpy(frdata, FrameBuf, framesize); + cur = &(*cur)->next; + + totalsize += framesize; + ++nframes; + } + if(!root) + { + fprintf(stderr, "readMP3: not a MP3 file\n"); + return 0; + } + + /* + fprintf(stderr, "readMP3: read %u frames (%u bytes)\n", nframes, totalsize); + */ + + mp3->SampRate = first_samprate; + mp3->Channels = first_chanmode == 3 ? 1 : 2; + mp3->NumFrames = nframes; + mp3->size = totalsize; + mp3->data = (unsigned char*)malloc(mp3->size); + if(mp3->data) + { + unsigned pos=0; + struct MP3Frame* it; + for(it=root; it; it=it->next) + { + memcpy(mp3->data + pos, it->data, it->framesize); + pos += it->framesize; + } + } + else + { + fprintf(stderr, "readMP3: malloc failed\n"); + } + + while(root) + { + struct MP3Frame* next = root->next; + free(root->data); + free(root); + root = next; + } + + return mp3->data != NULL; +} + diff -NaHudr swftools-2005-09-25-1334/mp3.h swftools-updated/mp3.h --- swftools-2005-09-25-1334/mp3.h 1970-01-01 02:00:00.000000000 +0200 +++ swftools-updated/mp3.h 2005-10-12 01:52:35.393177280 +0300 @@ -0,0 +1,18 @@ +/* mp3.h + Header file for mp3.c + + Part of the swftools package. + + Copyright (c) 2005 Joel Yliluoma + + This file is distributed under the GPL, see file COPYING for details */ + +struct MP3 { + unsigned short SampRate; + unsigned char Channels; + unsigned int NumFrames; + unsigned char* data; + unsigned long size; +}; + +int readMP3(char* filename, struct MP3*mp3); diff -NaHudr swftools-2005-09-25-1334/src/Makefile.in swftools-updated/src/Makefile.in --- swftools-2005-09-25-1334/src/Makefile.in 2005-07-23 11:11:16.000000000 +0300 +++ swftools-updated/src/Makefile.in 2005-10-11 23:23:28.582299272 +0300 @@ -11,6 +11,8 @@ $(C) wav2swf.c -o $@ wav.$(O): wav.c wav.h $(C) wav.c -o $@ +mp3.$(O): mp3.c mp3.h + $(C) mp3.c -o $@ png2swf.$(O): png2swf.c $(C) png2swf.c -o $@ gif2swf.$(O): gif2swf.c @@ -81,8 +83,8 @@ jpeg2swf$(E): jpeg2swf.$(O) ../lib/librfxswf$(A) $(L) jpeg2swf.$(O) -o $@ ../lib/librfxswf$(A) $(LIBS) $(STRIP) $@ -swfc$(E): parser.$(O) swfc.$(O) ../lib/q.$(O) wav.$(O) ../lib/png.$(O) ../lib/librfxswf$(A) - $(L) parser.$(O) swfc.$(O) ../lib/q.$(O) wav.$(O) ../lib/png.$(O) -o $@ ../lib/librfxswf$(A) $(LIBS) +swfc$(E): parser.$(O) swfc.$(O) ../lib/q.$(O) wav.$(O) mp3.$(O) ../lib/png.$(O) ../lib/librfxswf$(A) + $(L) parser.$(O) swfc.$(O) ../lib/q.$(O) wav.$(O) mp3.$(O) ../lib/png.$(O) -o $@ ../lib/librfxswf$(A) $(LIBS) $(STRIP) $@ install: diff -NaHudr swftools-2005-09-25-1334/src/mp3.c swftools-updated/src/mp3.c --- swftools-2005-09-25-1334/src/mp3.c 1970-01-01 02:00:00.000000000 +0200 +++ swftools-updated/src/mp3.c 2005-10-11 23:51:35.882790608 +0300 @@ -0,0 +1,167 @@ +/* mp3.c + Routines for handling .mp3 files + + Part of the swftools package. + + Copyright (c) 2005 Joel Yliluoma + + 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; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include +#include +#include + +#include "mp3.h" + +struct MP3Frame +{ + unsigned bitrate; + unsigned samprate; + unsigned chanmode; + unsigned framesize; + unsigned char* data; + struct MP3Frame* next; +}; + +static const unsigned BR_mpeg1[16] = {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}; +static const unsigned BR_mpeg2[16] = {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0}; +static const unsigned BR_reserved[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; +static const unsigned*const BR[4] = {BR_mpeg2, BR_reserved, BR_mpeg2, BR_mpeg1}; + +static const unsigned SR_mpeg1[4] = {44100,48000,32000,0}; +static const unsigned SR_mpeg2[4] = {22050,24000,16000,0}; +static const unsigned SR_mpeg25[4] = {11025,12000,8000,0}; +static const unsigned SR_reserved[4] = {0,0,0,0}; +static const unsigned*const SR[4] = {SR_mpeg25, SR_reserved, SR_mpeg2, SR_mpeg1}; + +int readMP3(char* filename, struct MP3*mp3) +{ + struct MP3Frame* root = 0; + struct MP3Frame** cur = &root; + + unsigned totalsize = 0; + unsigned first_samprate = 0; + unsigned nframes = 0; + int first_chanmode = -1; + + FILE*fi = fopen(filename, "rb"); + if(!fi) return 0; + + for(;;) + { + unsigned char FrameBuf[2048]; + unsigned char* hdr = FrameBuf; + unsigned char* data = FrameBuf+4; + unsigned char* frdata; + + unsigned char mpegver; + unsigned padding; + unsigned bitrate; + unsigned samprate; + unsigned framesize; + int chanmode; + + if(fread(hdr,1,4,fi) < 4) break; + + if(hdr[0] != 0xFF) break; + + if((hdr[1] & 0xE0) != 0xE0) break; + + mpegver = (hdr[1] >> 3) & 2; + + bitrate = BR[mpegver][ (hdr[2] >> 4) & 0x0F ] * 1000; + samprate = SR[mpegver][ (hdr[2] >> 2) & 0x03 ]; + chanmode = (hdr[3] >> 6) & 0x03; + + padding = (hdr[2] & 2) ? 1 : 0; + + if(!bitrate || !samprate) + { + /* Invalid frame */ + break; + } + if(!first_samprate) first_samprate = samprate; + else if(first_samprate != samprate) + { + /* Sampling rate changed?!? */ + break; + } + if(first_chanmode<0) first_chanmode = chanmode; + else if(first_chanmode != chanmode) + { + /* Channel mode changed?!? */ + break; + } + + framesize = ((mpegver == 3 ? 144 : 72) * bitrate) / samprate + padding; + + if(framesize > sizeof(FrameBuf)) break; + if(fread(data, 1, framesize - 4, fi) < framesize-4) break; + + frdata = (unsigned char*)malloc(framesize); + if(!frdata) break; + + *cur = (struct MP3Frame*)malloc(sizeof(*root)); + if(!*cur) + { + free(frdata); + break; + } + + (*cur)->next = 0; + (*cur)->bitrate = bitrate; + (*cur)->samprate = samprate; + (*cur)->chanmode = chanmode; + (*cur)->framesize = framesize; + (*cur)->data = frdata; + + memcpy(frdata, FrameBuf, framesize); + cur = &(*cur)->next; + + totalsize += framesize; + ++nframes; + } + if(!root) + { + fprintf(stderr, "readMP3: not a MP3 file\n"); + return 0; + } + + mp3->SampRate = first_samprate; + mp3->Channels = first_chanmode == 3 ? 1 : 2; + mp3->NumFrames = nframes; + mp3->size = totalsize; + mp3->data = (unsigned char*)malloc(mp3->size); + if(mp3->data) + { + unsigned pos=0; + struct MP3Frame* it; + for(it=root; it; it=it->next) + { + memcpy(mp3->data + pos, it->data, it->framesize); + pos += it->framesize; + } + } + while(root) + { + struct MP3Frame* next = root->next; + free(root->data); + free(root); + root = next; + } + + return mp3->data != NULL; +} + diff -NaHudr swftools-2005-09-25-1334/src/mp3.h swftools-updated/src/mp3.h --- swftools-2005-09-25-1334/src/mp3.h 1970-01-01 02:00:00.000000000 +0200 +++ swftools-updated/src/mp3.h 2005-10-11 23:24:14.225360472 +0300 @@ -0,0 +1,18 @@ +/* mp3.h + Header file for mp3.c + + Part of the swftools package. + + Copyright (c) 2005 Joel Yliluoma + + This file is distributed under the GPL, see file COPYING for details */ + +struct MP3 { + unsigned short SampRate; + unsigned char Channels; + unsigned int NumFrames; + unsigned char* data; + unsigned long size; +}; + +int readMP3(char* filename, struct MP3*mp3); diff -NaHudr swftools-2005-09-25-1334/src/swfc.c swftools-updated/src/swfc.c --- swftools-2005-09-25-1334/src/swfc.c 2005-05-16 15:23:01.000000000 +0300 +++ swftools-updated/src/swfc.c 2005-10-11 23:51:20.282162264 +0300 @@ -34,6 +34,7 @@ #include "../lib/q.h" #include "parser.h" #include "wav.h" +#include "mp3.h" #include "../lib/png.h" //#define DEBUG @@ -1201,17 +1202,15 @@ void s_sound(char*name, char*filename) { struct WAV wav, wav2; + struct MP3 mp3; sound_t* sound; - U16*samples; - int numsamples; - int t; - int blocksize = 1152; + U16*samples = NULL; + unsigned numsamples; + unsigned blocksize = 1152; + int is_mp3 = 0; - if(!readWAV(filename, &wav)) { - warning("Couldn't read wav file \"%s\"", filename); - samples = 0; - numsamples = 0; - } else { + if(readWAV(filename, &wav)) { + int t; convertWAV2mono(&wav, &wav2, 44100); samples = (U16*)wav2.data; numsamples = wav2.size/2; @@ -1222,6 +1221,16 @@ samples[t] = (samples[t]>>8)&0xff | (samples[t]<<8)&0xff00; } #endif + } else if(readMP3(filename, &mp3)) { + fprintf(stderr, "\"%s\" seems to work as a MP3 file...\n", filename); + blocksize = 1; + is_mp3 = 1; + } + else + { + warning("Couldn't read WAV/MP3 file \"%s\"", filename); + samples = 0; + numsamples = 0; } if(numsamples%blocksize != 0) @@ -1240,7 +1249,18 @@ tag = swf_InsertTag(tag, ST_DEFINESOUND); swf_SetU16(tag, id); //id - swf_SetSoundDefine(tag, samples, numsamples); + if(is_mp3) + { + swf_SetSoundDefineMP3( + tag, mp3.data, mp3.size, + mp3.SampRate, + mp3.Channels, + mp3.NumFrames); + } + else + { + swf_SetSoundDefine(tag, samples, numsamples); + } sound = (sound_t*)malloc(sizeof(sound_t)); /* mem leak */ sound->tag = tag; diff -NaHudr swftools-2005-09-25-1334/src/wav.c swftools-updated/src/wav.c --- swftools-2005-09-25-1334/src/wav.c 2004-05-09 12:25:40.000000000 +0300 +++ swftools-updated/src/wav.c 2005-10-11 23:46:38.705968352 +0300 @@ -63,7 +63,7 @@ if(!getWAVBlock (fi, &block)) return 0; if(strncmp(block.id,"RIFF",4)) { - fprintf(stderr, "readWAV: not a wav file\n"); + fprintf(stderr, "readWAV: not a WAV file\n"); return 0; } if(block.size + 8 < filesize)