Today I happened to write a program that simply reads an MP3 file
and spurts out an SWF file. I accidentally lost its source code,
which led me to find swftools.
So in an hour's work, I wrote MP3 support to swftools.
By MP3 support I mean that it's now possible to say this:
.sound sound1 "mp3file.mp3"
And it will work. It won't try to re-encode the MP3 file.
This way, you can specify your favourite MP3 encoding options
to LAME instead of hoping that SWFC gets it right. Or, use
your existing MP3 files without having to re-encode them.
Attached is the patch to swftools-2005-09-25-1334 source code.
--
Joel Yliluoma
http://iki.fi/bisqwit/
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/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 <[EMAIL PROTECTED]>
+
+ 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#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 <[EMAIL PROTECTED]>
+
+ 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)
_______________________________________________
Swftools-common mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/swftools-common