3 SWF Sound handling routines
5 Extension module for the rfxswf library.
6 Part of the swftools package.
8 Copyright (c) 2001, 2002 Matthias Kramm <kramm@quiss.org>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
26 #include "../rfxswf.h"
31 CodecInitOut * init = 0;
32 void swf_SetSoundStreamHead(TAG*tag, U16 avgnumsamples)
34 U8 playbackrate = 3; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
35 U8 playbacksize = 1; // 0 = 8 bit, 1 = 16 bit
36 U8 playbacktype = 0; // 0 = mono, 1 = stereo
37 U8 compression = 2; // 0 = raw, 1 = ADPCM, 2 = mp3, 3 = raw le, 6 = nellymoser
38 U8 rate = 3; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
39 U8 size = 1; // 0 = 8 bit, 1 = 16 bit
40 U8 type = 0; // 0 = mono, 1 = stereo
43 memset(¶ms, 0, sizeof(params));
44 params.frequency = 44100; //48000, 44100 or 32000
45 params.mode = 3; //0 = Stereo, 2 = Dual Channel, 3 = Mono
46 params.emphasis = 0; //0 = None, 1 = 50/15 microsec, 3 = CCITT J.17
47 params.bitrate = 128; //default is 128 (64 for mono)
48 init = codecInit(¶ms);
50 swf_SetU8(tag,(playbackrate<<2)|(playbacksize<<1)|playbacktype);
51 swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type);
52 swf_SetU16(tag,avgnumsamples);
54 printf("numSamples:%d\n",init->nSamples);
55 printf("bufferSize:%d\n",init->bufferSize);
58 void swf_SetSoundStreamBlock(TAG*tag, S16*samples, int numsamples, char first)
63 buf = malloc(init->bufferSize);
67 len = codecEncodeChunk (numsamples, samples, buf);
68 len += codecFlush (&buf[len]);
69 len += codecExit (&buf[len]);
72 swf_SetU16(tag, numsamples); // number of samples
73 swf_SetU16(tag, 0); // seek
75 swf_SetBlock(tag, buf, len);
80 /* TODO: find a better way to set these from the outside */
82 int swf_mp3_in_samplerate = 44100;
83 int swf_mp3_out_samplerate = 11025;
84 int swf_mp3_channels = 1;
85 int swf_mp3_bitrate = 32;
90 #include "../lame/lame.h"
92 static lame_global_flags*lame_flags;
94 static void initlame()
96 unsigned char buf[4096];
99 lame_flags = lame_init();
101 lame_set_in_samplerate(lame_flags, swf_mp3_in_samplerate);
102 lame_set_num_channels(lame_flags, swf_mp3_channels);
103 lame_set_scale(lame_flags, 0);
105 // MPEG1 32, 44.1, 48khz
106 // MPEG2 16, 22.05, 24
107 // MPEG2.5 8, 11.025, 12
108 lame_set_out_samplerate(lame_flags, swf_mp3_out_samplerate);
110 lame_set_quality(lame_flags, 0);
111 lame_set_mode(lame_flags, MONO/*3*/);
112 lame_set_brate(lame_flags, swf_mp3_bitrate);
113 //lame_set_compression_ratio(lame_flags, 11.025);
114 lame_set_bWriteVbrTag(lame_flags, 0);
116 lame_init_params(lame_flags);
117 lame_init_bitstream(lame_flags);
119 /* The first two flush calls to lame always fail, for
120 some reason. Do them here where they cause no damage. */
121 lame_encode_flush_nogap(lame_flags, buf, bufsize);
122 //printf("init:flush_nogap():%d\n", len);
123 lame_encode_flush(lame_flags, buf, bufsize);
124 //printf("init:flush():%d\n", len);
127 void swf_SetSoundStreamHead(TAG*tag, int avgnumsamples)
131 U8 playbackrate = 1; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
132 U8 playbacksize = 1; // 0 = 8 bit, 1 = 16 bit
133 U8 playbacktype = 0; // 0 = mono, 1 = stereo
134 U8 compression = 2; // 0 = raw, 1 = ADPCM, 2 = mp3, 3 = raw le, 6 = nellymoser
135 U8 rate = 1; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
136 U8 size = 1; // 0 = 8 bit, 1 = 16 bit
137 U8 type = 0; // 0 = mono, 1 = stereo
139 if(swf_mp3_out_samplerate == 5512) playbackrate = rate = 0; // lame doesn't support this
140 else if(swf_mp3_out_samplerate == 11025) playbackrate = rate = 1;
141 else if(swf_mp3_out_samplerate == 22050) playbackrate = rate = 2;
142 else if(swf_mp3_out_samplerate == 44100) playbackrate = rate = 3;
143 else fprintf(stderr, "Invalid samplerate: %d\n", swf_mp3_out_samplerate);
147 swf_SetU8(tag,(playbackrate<<2)|(playbacksize<<1)|playbacktype);
148 swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type);
149 swf_SetU16(tag,avgnumsamples);
152 void swf_SetSoundStreamBlock(TAG*tag, S16*samples, int seek, char first)
157 int numsamples = (int)(((swf_mp3_out_samplerate > 22050) ? 1152 : 576) * ((double)swf_mp3_in_samplerate/swf_mp3_out_samplerate));
160 buf = malloc(bufsize);
165 fs = lame_get_framesize(lame_flags);
166 swf_SetU16(tag, fs * first); // samples per mp3 frame
167 swf_SetU16(tag, seek); // seek
170 len += lame_encode_buffer(lame_flags, samples, samples, numsamples, &buf[len], bufsize-len);
171 len += lame_encode_flush_nogap(lame_flags, &buf[len], bufsize-len);
172 swf_SetBlock(tag, buf, len);
174 fprintf(stderr, "error: mp3 empty block, %d samples, first:%d, framesize:%d\n",
175 numsamples, first, fs);
177 fprintf(stderr, "ok: mp3 nonempty block, %d samples, first:%d, framesize:%d\n",
178 numsamples, first, fs);
183 void swf_SetSoundStreamEnd(TAG*tag)
185 lame_close (lame_flags);
188 void swf_SetSoundDefineRaw(TAG*tag, S16*samples, int num, int samplerate)
190 //swf_SetU8(tag,(/*compression*/0<<4)|(/*rate*/3<<2)|(/*size*/1<<1)|/*mono*/0);
191 //swf_SetU32(tag, numsamples); // 44100 -> 11025
192 //swf_SetBlock(tag, wav2.data, numsamples*2);
194 void swf_SetSoundDefine(TAG*tag, S16*samples, int num)
197 int oldlen=0,len = 0;
199 int blocksize = (int)(((swf_mp3_out_samplerate > 22050) ? 1152 : 576) * ((double)swf_mp3_in_samplerate/swf_mp3_out_samplerate));
203 U8 compression = 2; // 0 = raw, 1 = ADPCM, 2 = mp3, 3 = raw le, 6 = nellymoser
204 U8 rate = 1; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
205 U8 size = 1; // 0 = 8 bit, 1 = 16 bit
206 U8 type = 0; // 0 = mono, 1 = stereo
208 if(swf_mp3_out_samplerate == 5512) rate = 0;
209 else if(swf_mp3_out_samplerate == 11025) rate = 1;
210 else if(swf_mp3_out_samplerate == 22050) rate = 2;
211 else if(swf_mp3_out_samplerate == 44100) rate = 3;
212 else fprintf(stderr, "Invalid samplerate: %d\n", swf_mp3_out_samplerate);
214 blocks = num / (blocksize);
216 swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type);
218 swf_SetU32(tag, (int)(tag,blocks*blocksize /
219 ((double)swf_mp3_in_samplerate/swf_mp3_out_samplerate)) // account for resampling
222 buf = malloc(bufsize);
228 swf_SetU16(tag, 0); //delayseek
229 for(t=0;t<blocks;t++) {
232 pos= &samples[t*blocksize];
233 len += lame_encode_buffer(lame_flags, pos, pos, blocksize, &buf[len], bufsize-len);
234 len += lame_encode_flush_nogap(lame_flags, &buf[len], bufsize-len);
235 swf_SetBlock(tag, buf, len);
250 void swf_SetSoundStreamHead(TAG*tag, int avgnumsamples)
252 fprintf(stderr, "Error: no sound support compiled in.\n");exit(1);
254 void swf_SetSoundStreamBlock(TAG*tag, S16*samples, int seek, char first)
256 fprintf(stderr, "Error: no sound support compiled in.\n");exit(1);
258 void swf_SetSoundStreamEnd(TAG*tag)
260 fprintf(stderr, "Error: no sound support compiled in.\n");exit(1);
262 void swf_SetSoundDefineRaw(TAG*tag, S16*samples, int num, int samplerate)
264 fprintf(stderr, "Error: no sound support compiled in.\n");exit(1);
266 void swf_SetSoundDefine(TAG*tag, S16*samples, int num)
268 fprintf(stderr, "Error: no sound support compiled in.\n");exit(1);
273 #define SOUNDINFO_STOP 32
274 #define SOUNDINFO_NOMULTIPLE 16
275 #define SOUNDINFO_HASENVELOPE 8
276 #define SOUNDINFO_HASLOOPS 4
277 #define SOUNDINFO_HASOUTPOINT 2
278 #define SOUNDINFO_HASINPOINT 1
281 void swf_SetSoundInfo(TAG*tag, SOUNDINFO*info)
283 U8 flags = (info->stop?SOUNDINFO_STOP:0)
284 |(info->nomultiple?SOUNDINFO_NOMULTIPLE:0)
285 |(info->envelopes?SOUNDINFO_HASENVELOPE:0)
286 |(info->loops?SOUNDINFO_HASLOOPS:0)
287 |(info->outpoint?SOUNDINFO_HASOUTPOINT:0)
288 |(info->inpoint?SOUNDINFO_HASINPOINT:0);
289 swf_SetU8(tag, flags);
290 if(flags&SOUNDINFO_HASINPOINT)
291 swf_SetU32(tag, info->inpoint);
292 if(flags&SOUNDINFO_HASOUTPOINT)
293 swf_SetU32(tag, info->outpoint);
294 if(flags&SOUNDINFO_HASLOOPS)
295 swf_SetU16(tag, info->loops);
296 if(flags&SOUNDINFO_HASENVELOPE) {
298 swf_SetU8(tag, info->envelopes);
299 for(t=0;t<info->envelopes;t++) {
300 swf_SetU32(tag, info->pos[t]);
301 swf_SetU16(tag, info->left[t]);
302 swf_SetU16(tag, info->right[t]);