fixed a typecast bug.
[swftools.git] / lib / modules / swfsound.c
1 /* swfaction.c
2
3    SWF Sound handling routines
4    
5    Extension module for the rfxswf library.
6    Part of the swftools package.
7
8    Copyright (c) 2001, 2002 Matthias Kramm <kramm@quiss.org>
9  
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.
14
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.
19
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 */
23
24 #ifndef RFXSWF_DISABLESOUND
25
26 #include "../rfxswf.h"
27
28 #ifdef BLADEENC
29 fjokjklj
30 CodecInitOut * init = 0;
31 void swf_SetSoundStreamHead(TAG*tag, U16 avgnumsamples)
32 {
33     U8 playbackrate = 3; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
34     U8 playbacksize = 1; // 0 = 8 bit, 1 = 16 bit
35     U8 playbacktype = 0; // 0 = mono, 1 = stereo
36     U8 compression = 2; // 0 = raw, 1 = ADPCM, 2 = mp3, 3 = raw le, 6 = nellymoser
37     U8 rate = 3; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
38     U8 size = 1; // 0 = 8 bit, 1 = 16 bit
39     U8 type = 0; // 0 = mono, 1 = stereo
40
41     CodecInitIn params;
42     memset(&params, 0, sizeof(params));
43     params.frequency = 44100;  //48000, 44100 or 32000
44     params.mode = 3;      //0 = Stereo, 2 = Dual Channel, 3 = Mono
45     params.emphasis = 0;  //0 = None, 1 = 50/15 microsec, 3 = CCITT J.17
46     params.bitrate = 128;         //default is 128 (64 for mono)
47     init = codecInit(&params);
48
49     swf_SetU8(tag,(playbackrate<<2)|(playbacksize<<1)|playbacktype);
50     swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type);
51     swf_SetU16(tag,avgnumsamples);
52
53     printf("numSamples:%d\n",init->nSamples);
54     printf("bufferSize:%d\n",init->bufferSize);
55 }
56
57 void swf_SetSoundStreamBlock(TAG*tag, S16*samples, int numsamples, char first)
58 {
59     char*buf;
60     int len = 0;
61
62     buf = malloc(init->bufferSize);
63     if(!buf)
64         return;
65     
66     len = codecEncodeChunk (numsamples, samples, buf);
67     len += codecFlush (&buf[len]);
68     len += codecExit (&buf[len]);
69
70     if(first) {
71         swf_SetU16(tag, numsamples); // number of samples
72         swf_SetU16(tag, 0); // seek
73     }
74     swf_SetBlock(tag, buf, len);
75     free(buf);
76 }
77 #endif
78
79
80 #ifdef LAME
81
82 #include "../lame/lame.h"
83
84 /* TODO: find a way to set these from the outside */
85 int swf_mp3_in_samplerate = 44100;
86 int swf_mp3_out_samplerate = 11025;
87 int swf_mp3_channels = 1;
88 int swf_mp3_bitrate = 32;
89
90 static lame_global_flags*lame_flags;
91
92 static void initlame()
93 {
94     unsigned char buf[4096];
95     int bufsize = 1152*2;
96
97     lame_flags = lame_init();
98
99     lame_set_in_samplerate(lame_flags, swf_mp3_in_samplerate);
100     lame_set_num_channels(lame_flags, swf_mp3_channels);
101     lame_set_scale(lame_flags, 0);
102
103     // MPEG1    32, 44.1,   48khz
104     // MPEG2    16, 22.05,  24
105     // MPEG2.5   8, 11.025, 12
106     lame_set_out_samplerate(lame_flags, swf_mp3_out_samplerate);
107
108     lame_set_quality(lame_flags, 0);
109     lame_set_mode(lame_flags, MONO/*3*/);
110     lame_set_brate(lame_flags, swf_mp3_bitrate);
111     //lame_set_compression_ratio(lame_flags, 11.025);
112     lame_set_bWriteVbrTag(lame_flags, 0);
113
114     lame_init_params(lame_flags);
115     lame_init_bitstream(lame_flags);
116
117     /* The first two flush calls to lame always fail, for
118        some reason. Do them here where they cause no damage. */
119     lame_encode_flush_nogap(lame_flags, buf, bufsize);
120     //printf("init:flush_nogap():%d\n", len);
121     lame_encode_flush(lame_flags, buf, bufsize);
122     //printf("init:flush():%d\n", len);
123 }
124
125 void swf_SetSoundStreamHead(TAG*tag, int avgnumsamples)
126 {
127     int len;
128
129     U8 playbackrate = 1; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
130     U8 playbacksize = 1; // 0 = 8 bit, 1 = 16 bit
131     U8 playbacktype = 0; // 0 = mono, 1 = stereo
132     U8 compression = 2; // 0 = raw, 1 = ADPCM, 2 = mp3, 3 = raw le, 6 = nellymoser
133     U8 rate = 1; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
134     U8 size = 1; // 0 = 8 bit, 1 = 16 bit
135     U8 type = 0; // 0 = mono, 1 = stereo
136
137     if(swf_mp3_out_samplerate == 5512) playbackrate = rate = 0; // lame doesn't support this
138     else if(swf_mp3_out_samplerate == 11025) playbackrate = rate = 1;
139     else if(swf_mp3_out_samplerate == 22050) playbackrate = rate = 2;
140     else if(swf_mp3_out_samplerate == 44100) playbackrate = rate = 3;
141     else fprintf(stderr, "Invalid samplerate: %d\n", swf_mp3_out_samplerate);
142     
143     initlame();
144
145     swf_SetU8(tag,(playbackrate<<2)|(playbacksize<<1)|playbacktype);
146     swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type);
147     swf_SetU16(tag,avgnumsamples);
148 }
149
150 void swf_SetSoundStreamBlock(TAG*tag, S16*samples, int seek, char first)
151 {
152     char*buf;
153     int len = 0;
154     int bufsize = 16384;
155     int numsamples = (int)(((swf_mp3_out_samplerate > 22050) ? 1152 : 576) * ((double)swf_mp3_in_samplerate/swf_mp3_out_samplerate));
156     int fs = 0;
157
158     buf = malloc(bufsize);
159     if(!buf)
160         return;
161
162     if(first) {
163         fs = lame_get_framesize(lame_flags);
164         swf_SetU16(tag, fs * first); // samples per mp3 frame
165         swf_SetU16(tag, seek); // seek
166     }
167
168     len += lame_encode_buffer(lame_flags, samples, samples, numsamples, &buf[len], bufsize-len);
169     len += lame_encode_flush_nogap(lame_flags, &buf[len], bufsize-len);
170     swf_SetBlock(tag, buf, len);
171     if(len == 0) {
172         fprintf(stderr, "error: mp3 empty block, %d samples, first:%d, framesize:%d\n",
173                 numsamples, first, fs);
174     }/* else {
175         fprintf(stderr, "ok: mp3 nonempty block, %d samples, first:%d, framesize:%d\n",
176                 numsamples, first, fs);
177     }*/
178     free(buf);
179 }
180
181 void swf_SetSoundStreamEnd(TAG*tag)
182 {
183     lame_close (lame_flags);
184 }
185
186 void swf_SetSoundDefineRaw(TAG*tag, S16*samples, int num, int samplerate)
187 {
188     //swf_SetU8(tag,(/*compression*/0<<4)|(/*rate*/3<<2)|(/*size*/1<<1)|/*mono*/0);
189     //swf_SetU32(tag, numsamples); // 44100 -> 11025
190     //swf_SetBlock(tag, wav2.data, numsamples*2);
191 }
192 void swf_SetSoundDefine(TAG*tag, S16*samples, int num)
193 {
194     char*buf;
195     int oldlen=0,len = 0;
196     int bufsize = 16384;
197     int blocksize = (int)(((swf_mp3_out_samplerate > 22050) ? 1152 : 576) * ((double)swf_mp3_in_samplerate/swf_mp3_out_samplerate));
198     int t;
199     int blocks;
200
201     U8 compression = 2; // 0 = raw, 1 = ADPCM, 2 = mp3, 3 = raw le, 6 = nellymoser
202     U8 rate = 1; // 0 = 5.5 Khz, 1 = 11 Khz, 2 = 22 Khz, 3 = 44 Khz
203     U8 size = 1; // 0 = 8 bit, 1 = 16 bit
204     U8 type = 0; // 0 = mono, 1 = stereo
205     
206     if(swf_mp3_out_samplerate == 5512) rate = 0;
207     else if(swf_mp3_out_samplerate == 11025) rate = 1;
208     else if(swf_mp3_out_samplerate == 22050) rate = 2;
209     else if(swf_mp3_out_samplerate == 44100) rate = 3;
210     else fprintf(stderr, "Invalid samplerate: %d\n", swf_mp3_out_samplerate);
211
212     blocks = num / (blocksize);
213
214     swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type);
215
216     swf_SetU32(tag, (int)(tag,blocks*blocksize / 
217             ((double)swf_mp3_in_samplerate/swf_mp3_out_samplerate)) // account for resampling
218             );
219
220     buf = malloc(bufsize);
221     if(!buf)
222         return;
223
224     initlame();
225
226     swf_SetU16(tag, 0); //delayseek
227     for(t=0;t<blocks;t++) {
228         int s;
229         U16*pos;
230         pos= &samples[t*blocksize];
231         len += lame_encode_buffer(lame_flags, pos, pos, blocksize, &buf[len], bufsize-len);
232         len += lame_encode_flush_nogap(lame_flags, &buf[len], bufsize-len);
233         swf_SetBlock(tag, buf, len);
234         len = 0;
235     }
236
237     free(buf);
238 }
239
240 #define SOUNDINFO_STOP 32
241 #define SOUNDINFO_NOMULTIPLE 16
242 #define SOUNDINFO_HASENVELOPE 8
243 #define SOUNDINFO_HASLOOPS 4
244 #define SOUNDINFO_HASOUTPOINT 2
245 #define SOUNDINFO_HASINPOINT 1
246
247 void swf_SetSoundInfo(TAG*tag, SOUNDINFO*info)
248 {
249     U8 flags = (info->stop?SOUNDINFO_STOP:0)
250               |(info->nomultiple?SOUNDINFO_NOMULTIPLE:0)
251               |(info->envelopes?SOUNDINFO_HASENVELOPE:0)
252               |(info->loops?SOUNDINFO_HASLOOPS:0)
253               |(info->outpoint?SOUNDINFO_HASOUTPOINT:0)
254               |(info->inpoint?SOUNDINFO_HASINPOINT:0);
255     swf_SetU8(tag, flags);
256     if(flags&SOUNDINFO_HASINPOINT)
257         swf_SetU32(tag, info->inpoint);
258     if(flags&SOUNDINFO_HASOUTPOINT)
259         swf_SetU32(tag, info->outpoint);
260     if(flags&SOUNDINFO_HASLOOPS)
261         swf_SetU16(tag, info->loops);
262     if(flags&SOUNDINFO_HASENVELOPE) {
263         int t;
264         swf_SetU8(tag, info->envelopes);
265         for(t=0;t<info->envelopes;t++) {
266             swf_SetU32(tag, info->pos[t]);
267             swf_SetU16(tag, info->left[t]);
268             swf_SetU16(tag, info->right[t]);
269         }
270     }
271 }
272
273 #endif
274
275 #endif // RFXSWF_DISABLESOUND