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 file is distributed under the GPL, see file COPYING for details
14 #ifndef RFXSWF_DISABLESOUND
16 #include "../rfxswf.h"
20 CodecInitOut * init = 0;
21 void swf_SetSoundStreamHead(TAG*tag, U16 avgnumsamples)
23 U8 playbackrate = 3; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
24 U8 playbacksize = 1; // 0 = 8 bit, 1 = 16 bit
25 U8 playbacktype = 0; // 0 = mono, 1 = stereo
26 U8 compression = 2; // 0 = raw, 1 = ADPCM, 2 = mp3, 3 = raw le, 6 = nellymoser
27 U8 rate = 3; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
28 U8 size = 1; // 0 = 8 bit, 1 = 16 bit
29 U8 type = 0; // 0 = mono, 1 = stereo
32 memset(¶ms, 0, sizeof(params));
33 params.frequency = 44100; //48000, 44100 or 32000
34 params.mode = 3; //0 = Stereo, 2 = Dual Channel, 3 = Mono
35 params.emphasis = 0; //0 = None, 1 = 50/15 microsec, 3 = CCITT J.17
36 params.bitrate = 128; //default is 128 (64 for mono)
37 init = codecInit(¶ms);
39 swf_SetU8(tag,(playbackrate<<2)|(playbacksize<<1)|playbacktype);
40 swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type);
41 swf_SetU16(tag,avgnumsamples);
43 printf("numSamples:%d\n",init->nSamples);
44 printf("bufferSize:%d\n",init->bufferSize);
47 void swf_SetSoundStreamBlock(TAG*tag, S16*samples, int numsamples, char first)
52 buf = malloc(init->bufferSize);
56 len = codecEncodeChunk (numsamples, samples, buf);
57 len += codecFlush (&buf[len]);
58 len += codecExit (&buf[len]);
61 swf_SetU16(tag, numsamples); // number of samples
62 swf_SetU16(tag, 0); // seek
64 swf_SetBlock(tag, buf, len);
72 #include "../lame/lame.h"
74 /* TODO: find a way to set these from the outside */
75 int swf_mp3_in_samplerate = 44100;
76 int swf_mp3_out_samplerate = 11025;
77 int swf_mp3_channels = 1;
78 int swf_mp3_bitrate = 32;
80 static lame_global_flags*lame_flags;
82 static void initlame()
84 unsigned char buf[4096];
87 lame_flags = lame_init();
89 lame_set_in_samplerate(lame_flags, swf_mp3_in_samplerate);
90 lame_set_num_channels(lame_flags, swf_mp3_channels);
91 lame_set_scale(lame_flags, 0);
93 // MPEG1 32, 44.1, 48khz
94 // MPEG2 16, 22.05, 24
95 // MPEG2.5 8, 11.025, 12
96 lame_set_out_samplerate(lame_flags, swf_mp3_out_samplerate);
98 lame_set_quality(lame_flags, 0);
99 lame_set_mode(lame_flags, MONO/*3*/);
100 lame_set_brate(lame_flags, swf_mp3_bitrate);
101 //lame_set_compression_ratio(lame_flags, 11.025);
102 lame_set_bWriteVbrTag(lame_flags, 0);
104 lame_init_params(lame_flags);
105 lame_init_bitstream(lame_flags);
107 /* The first two flush calls to lame always fail, for
108 some reason. Do them here where they cause no damage. */
109 lame_encode_flush_nogap(lame_flags, buf, bufsize);
110 //printf("init:flush_nogap():%d\n", len);
111 lame_encode_flush(lame_flags, buf, bufsize);
112 //printf("init:flush():%d\n", len);
115 void swf_SetSoundStreamHead(TAG*tag, int avgnumsamples)
119 U8 playbackrate = 1; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
120 U8 playbacksize = 1; // 0 = 8 bit, 1 = 16 bit
121 U8 playbacktype = 0; // 0 = mono, 1 = stereo
122 U8 compression = 2; // 0 = raw, 1 = ADPCM, 2 = mp3, 3 = raw le, 6 = nellymoser
123 U8 rate = 1; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
124 U8 size = 1; // 0 = 8 bit, 1 = 16 bit
125 U8 type = 0; // 0 = mono, 1 = stereo
127 if(swf_mp3_out_samplerate == 5512) playbackrate = rate = 0; // lame doesn't support this
128 else if(swf_mp3_out_samplerate == 11025) playbackrate = rate = 1;
129 else if(swf_mp3_out_samplerate == 22050) playbackrate = rate = 2;
130 else if(swf_mp3_out_samplerate == 44100) playbackrate = rate = 3;
131 else fprintf(stderr, "Invalid samplerate: %d\n", swf_mp3_out_samplerate);
135 swf_SetU8(tag,(playbackrate<<2)|(playbacksize<<1)|playbacktype);
136 swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type);
137 swf_SetU16(tag,avgnumsamples);
140 void swf_SetSoundStreamBlock(TAG*tag, S16*samples, int seek, char first)
145 int numsamples = 576*(swf_mp3_in_samplerate/swf_mp3_out_samplerate);
148 buf = malloc(bufsize);
153 fs = lame_get_framesize(lame_flags);
154 swf_SetU16(tag, fs * first); // samples per mp3 frame
155 swf_SetU16(tag, seek); // seek
158 len += lame_encode_buffer(lame_flags, samples, samples, numsamples, &buf[len], bufsize-len);
159 len += lame_encode_flush_nogap(lame_flags, &buf[len], bufsize-len);
160 swf_SetBlock(tag, buf, len);
162 fprintf(stderr, "error: mp3 empty block, %d samples, first:%d, framesize:%d\n",
163 numsamples, first, fs);
165 fprintf(stderr, "ok: mp3 nonempty block, %d samples, first:%d, framesize:%d\n",
166 numsamples, first, fs);
171 void swf_SetSoundStreamEnd(TAG*tag)
173 lame_close (lame_flags);
176 void swf_SetSoundDefineRaw(TAG*tag, S16*samples, int num, int samplerate)
178 //swf_SetU8(tag,(/*compression*/0<<4)|(/*rate*/3<<2)|(/*size*/1<<1)|/*mono*/0);
179 //swf_SetU32(tag, numsamples); // 44100 -> 11025
180 //swf_SetBlock(tag, wav2.data, numsamples*2);
182 void swf_SetSoundDefine(TAG*tag, S16*samples, int num)
185 int oldlen=0,len = 0;
187 int blocksize = 576*(swf_mp3_in_samplerate/swf_mp3_out_samplerate);
191 U8 compression = 2; // 0 = raw, 1 = ADPCM, 2 = mp3, 3 = raw le, 6 = nellymoser
192 U8 rate = 1; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
193 U8 size = 1; // 0 = 8 bit, 1 = 16 bit
194 U8 type = 0; // 0 = mono, 1 = stereo
196 if(swf_mp3_out_samplerate == 5512) rate = 0;
197 else if(swf_mp3_out_samplerate == 11025) rate = 1;
198 else if(swf_mp3_out_samplerate == 22050) rate = 2;
199 else if(swf_mp3_out_samplerate == 44100) rate = 3;
200 else fprintf(stderr, "Invalid samplerate: %d\n", swf_mp3_out_samplerate);
202 blocks = num / (blocksize);
204 swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type);
206 swf_SetU32(tag,blocks*blocksize /
207 (swf_mp3_in_samplerate/swf_mp3_out_samplerate) // account for resampling
210 buf = malloc(bufsize);
216 swf_SetU16(tag, 0); //delayseek
217 for(t=0;t<blocks;t++) {
220 pos= &samples[t*blocksize];
221 len += lame_encode_buffer(lame_flags, pos, pos, blocksize, &buf[len], bufsize-len);
222 len += lame_encode_flush_nogap(lame_flags, &buf[len], bufsize-len);
223 swf_SetBlock(tag, buf, len);
230 #define SOUNDINFO_STOP 32
231 #define SOUNDINFO_NOMULTIPLE 16
232 #define SOUNDINFO_HASENVELOPE 8
233 #define SOUNDINFO_HASLOOPS 4
234 #define SOUNDINFO_HASOUTPOINT 2
235 #define SOUNDINFO_HASINPOINT 1
237 void swf_SetSoundInfo(TAG*tag, SOUNDINFO*info)
239 U8 flags = (info->stop?SOUNDINFO_STOP:0)
240 |(info->nomultiple?SOUNDINFO_NOMULTIPLE:0)
241 |(info->envelopes?SOUNDINFO_HASENVELOPE:0)
242 |(info->loops?SOUNDINFO_HASLOOPS:0)
243 |(info->outpoint?SOUNDINFO_HASOUTPOINT:0)
244 |(info->inpoint?SOUNDINFO_HASINPOINT:0);
245 swf_SetU8(tag, flags);
246 if(flags&SOUNDINFO_HASINPOINT)
247 swf_SetU32(tag, info->inpoint);
248 if(flags&SOUNDINFO_HASOUTPOINT)
249 swf_SetU32(tag, info->outpoint);
250 if(flags&SOUNDINFO_HASLOOPS)
251 swf_SetU16(tag, info->loops);
252 if(flags&SOUNDINFO_HASENVELOPE) {
254 swf_SetU8(tag, info->envelopes);
255 for(t=0;t<info->envelopes;t++) {
256 swf_SetU32(tag, info->pos[t]);
257 swf_SetU16(tag, info->left[t]);
258 swf_SetU16(tag, info->right[t]);
265 #endif // RFXSWF_DISABLESOUND