+ rfx_free(buf);
+}
+#endif
+
+void swf_SetSoundDefineRaw(TAG*tag, S16*samples, int numsamples)
+{
+ swf_SetU8(tag,(/*compression*/0<<4)|(/*rate*/3<<2)|(/*size*/1<<1)|/*mono*/0);
+ swf_SetU32(tag, numsamples); // 44100 -> 11025
+ swf_SetBlock(tag, (U8*)samples, numsamples*2);
+}
+
+/* TODO: find a better way to set these from the outside */
+
+int swf_mp3_in_samplerate = 44100;
+int swf_mp3_out_samplerate = 11025;
+int swf_mp3_channels = 1;
+int swf_mp3_bitrate = 32;
+
+#ifdef HAVE_LAME
+#define HAVE_SOUND
+
+#include <stdarg.h>
+#include <lame.h>
+
+static lame_global_flags*lame_flags;
+
+void null_errorf(const char *format, va_list ap)
+{
+}
+
+static void initlame()
+{
+ unsigned char buf[4096];
+ int bufsize = 1152*2;
+
+ lame_flags = lame_init();
+
+ lame_set_in_samplerate(lame_flags, swf_mp3_in_samplerate);
+ lame_set_num_channels(lame_flags, swf_mp3_channels);
+ lame_set_scale(lame_flags, 0);
+
+ // MPEG1 32, 44.1, 48khz
+ // MPEG2 16, 22.05, 24
+ // MPEG2.5 8, 11.025, 12
+ lame_set_out_samplerate(lame_flags, swf_mp3_out_samplerate);
+
+ lame_set_quality(lame_flags, 0);
+ lame_set_mode(lame_flags, MONO/*3*/);
+ lame_set_brate(lame_flags, swf_mp3_bitrate);
+ //lame_set_compression_ratio(lame_flags, 11.025);
+ lame_set_bWriteVbrTag(lame_flags, 0);
+
+ lame_init_params(lame_flags);
+ lame_init_bitstream(lame_flags);
+
+ lame_set_errorf(lame_flags, null_errorf);
+ /* The first two flush calls to lame always fail, for
+ some reason. Do them here where they cause no damage. */
+ lame_encode_flush_nogap(lame_flags, buf, bufsize);
+ //printf("init:flush_nogap():%d\n", len);
+ lame_encode_flush(lame_flags, buf, bufsize);
+ //printf("init:flush():%d\n", len);
+ lame_set_errorf(lame_flags, 0);
+}
+
+void swf_SetSoundStreamHead(TAG*tag, int avgnumsamples)
+{
+ int len;
+
+ U8 playbackrate = 1; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
+ U8 playbacksize = 1; // 0 = 8 bit, 1 = 16 bit
+ U8 playbacktype = 0; // 0 = mono, 1 = stereo
+ U8 compression = 2; // 0 = raw, 1 = ADPCM, 2 = mp3, 3 = raw le, 6 = nellymoser
+ U8 rate = 1; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
+ U8 size = 1; // 0 = 8 bit, 1 = 16 bit
+ U8 type = 0; // 0 = mono, 1 = stereo
+
+ if(swf_mp3_out_samplerate == 5512) playbackrate = rate = 0; // lame doesn't support this
+ else if(swf_mp3_out_samplerate == 11025) playbackrate = rate = 1;
+ else if(swf_mp3_out_samplerate == 22050) playbackrate = rate = 2;
+ else if(swf_mp3_out_samplerate == 44100) playbackrate = rate = 3;
+ else fprintf(stderr, "Invalid samplerate: %d\n", swf_mp3_out_samplerate);
+
+ initlame();
+
+ swf_SetU8(tag,(playbackrate<<2)|(playbacksize<<1)|playbacktype);
+ swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type);
+ swf_SetU16(tag,avgnumsamples);
+}
+
+void swf_SetSoundStreamBlock(TAG*tag, S16*samples, int seek, char first)
+{
+ char*buf;
+ int len = 0;
+ int bufsize = 16384;
+ int numsamples = (int)(((swf_mp3_out_samplerate > 22050) ? 1152 : 576) * ((double)swf_mp3_in_samplerate/swf_mp3_out_samplerate));
+ int fs = 0;
+
+ buf = rfx_alloc(bufsize);
+ if(!buf)
+ return;
+
+ if(first) {
+ fs = lame_get_framesize(lame_flags);
+ swf_SetU16(tag, fs * first); // samples per mp3 frame
+ swf_SetU16(tag, seek); // seek
+ }
+
+ len += lame_encode_buffer(lame_flags, samples, samples, numsamples, &buf[len], bufsize-len);
+ len += lame_encode_flush_nogap(lame_flags, &buf[len], bufsize-len);
+ swf_SetBlock(tag, buf, len);
+ if(len == 0) {
+ fprintf(stderr, "error: mp3 empty block, %d samples, first:%d, framesize:%d\n",
+ numsamples, first, fs);
+ }/* else {
+ fprintf(stderr, "ok: mp3 nonempty block, %d samples, first:%d, framesize:%d\n",
+ numsamples, first, fs);
+ }*/
+ rfx_free(buf);
+}
+
+void swf_SetSoundStreamEnd(TAG*tag)
+{
+ lame_close (lame_flags);
+}
+
+void swf_SetSoundDefine(TAG*tag, S16*samples, int num)
+{
+ char*buf;
+ int oldlen=0,len = 0;
+ int bufsize = 16384;
+ int blocksize = (int)(((swf_mp3_out_samplerate > 22050) ? 1152 : 576) * ((double)swf_mp3_in_samplerate/swf_mp3_out_samplerate));
+ int t;
+ int blocks;
+
+ U8 compression = 2; // 0 = raw, 1 = ADPCM, 2 = mp3, 3 = raw le, 6 = nellymoser
+ U8 rate = 1; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
+ U8 size = 1; // 0 = 8 bit, 1 = 16 bit
+ U8 type = 0; // 0 = mono, 1 = stereo
+
+ if(swf_mp3_out_samplerate == 5512) rate = 0;
+ else if(swf_mp3_out_samplerate == 11025) rate = 1;
+ else if(swf_mp3_out_samplerate == 22050) rate = 2;
+ else if(swf_mp3_out_samplerate == 44100) rate = 3;
+ else fprintf(stderr, "Invalid samplerate: %d\n", swf_mp3_out_samplerate);
+
+ blocks = num / (blocksize);
+
+ swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type);
+
+ swf_SetU32(tag, (int)(tag,blocks*blocksize /
+ ((double)swf_mp3_in_samplerate/swf_mp3_out_samplerate)) // account for resampling
+ );
+
+ buf = rfx_alloc(bufsize);
+ if(!buf)
+ return;
+
+ initlame();
+
+ swf_SetU16(tag, 0); //delayseek
+ for(t=0;t<blocks;t++) {
+ int s;
+ U16*pos;
+ pos= &samples[t*blocksize];
+ len += lame_encode_buffer(lame_flags, pos, pos, blocksize, &buf[len], bufsize-len);
+ len += lame_encode_flush_nogap(lame_flags, &buf[len], bufsize-len);
+ swf_SetBlock(tag, buf, len);
+ len = 0;
+ }
+
+ rfx_free(buf);
+}
+
+#endif
+
+#endif
+
+#ifndef HAVE_SOUND
+
+// supply stubs
+
+void swf_SetSoundStreamHead(TAG*tag, int avgnumsamples)
+{
+ fprintf(stderr, "Error: no mp3 soundstream support compiled in.\n");exit(1);
+}
+void swf_SetSoundStreamBlock(TAG*tag, S16*samples, int seek, char first)
+{
+ fprintf(stderr, "Error: no mp3 soundstream support compiled in.\n");exit(1);
+}
+void swf_SetSoundStreamEnd(TAG*tag)
+{
+ fprintf(stderr, "Error: no mp3 soundstream support compiled in.\n");exit(1);