enhanced samplerate support.
[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 file is distributed under the GPL, see file COPYING for details 
11
12 */
13
14 #ifndef RFXSWF_DISABLESOUND
15
16 #include "../rfxswf.h"
17
18 #ifdef BLADEENC
19 fjokjklj
20 CodecInitOut * init = 0;
21 void swf_SetSoundStreamHead(TAG*tag, U16 avgnumsamples)
22 {
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
30
31     CodecInitIn params;
32     memset(&params, 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(&params);
38
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);
42
43     printf("numSamples:%d\n",init->nSamples);
44     printf("bufferSize:%d\n",init->bufferSize);
45 }
46
47 void swf_SetSoundStreamBlock(TAG*tag, S16*samples, int numsamples, char first)
48 {
49     char*buf;
50     int len = 0;
51
52     buf = malloc(init->bufferSize);
53     if(!buf)
54         return;
55     
56     len = codecEncodeChunk (numsamples, samples, buf);
57     len += codecFlush (&buf[len]);
58     len += codecExit (&buf[len]);
59
60     if(first) {
61         swf_SetU16(tag, numsamples); // number of samples
62         swf_SetU16(tag, 0); // seek
63     }
64     swf_SetBlock(tag, buf, len);
65     free(buf);
66 }
67 #endif
68
69
70 #ifdef LAME
71
72 #include "../lame/lame.h"
73
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;
79
80 static lame_global_flags*lame_flags;
81
82 static void initlame()
83 {
84     unsigned char buf[4096];
85     int bufsize = 1152*2;
86
87     lame_flags = lame_init();
88
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);
92
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);
97
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);
103
104     lame_init_params(lame_flags);
105     lame_init_bitstream(lame_flags);
106
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);
113 }
114
115 void swf_SetSoundStreamHead(TAG*tag, int avgnumsamples)
116 {
117     int len;
118
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
126
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);
132     
133     initlame();
134
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);
138 }
139
140 void swf_SetSoundStreamBlock(TAG*tag, S16*samples, int seek, char first)
141 {
142     char*buf;
143     int len = 0;
144     int bufsize = 16384;
145     int numsamples = 576*(swf_mp3_in_samplerate/swf_mp3_out_samplerate);
146     int fs;
147
148     buf = malloc(bufsize);
149     if(!buf)
150         return;
151
152     if(first) {
153         fs = lame_get_framesize(lame_flags);
154         swf_SetU16(tag, fs * first); // samples per mp3 frame
155         swf_SetU16(tag, seek); // seek
156     }
157
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);
161     if(len == 0) {
162         fprintf(stderr, "error: mp3 empty block, %d samples, first:%d, framesize:%d\n",
163                 numsamples, first, fs);
164     }/* else {
165         fprintf(stderr, "ok: mp3 nonempty block, %d samples, first:%d, framesize:%d\n",
166                 numsamples, first, fs);
167     }*/
168     free(buf);
169 }
170
171 void swf_SetSoundStreamEnd(TAG*tag)
172 {
173     lame_close (lame_flags);
174 }
175
176 void swf_SetSoundDefineRaw(TAG*tag, S16*samples, int num, int samplerate)
177 {
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);
181 }
182 void swf_SetSoundDefine(TAG*tag, S16*samples, int num)
183 {
184     char*buf;
185     int oldlen=0,len = 0;
186     int bufsize = 16384;
187     int blocksize = 576*(swf_mp3_in_samplerate/swf_mp3_out_samplerate);
188     int t;
189     int blocks;
190
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
195     
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);
201
202     blocks = num / (blocksize);
203
204     swf_SetU8(tag,(compression<<4)|(rate<<2)|(size<<1)|type);
205
206     swf_SetU32(tag,blocks*blocksize / 
207             (swf_mp3_in_samplerate/swf_mp3_out_samplerate) // account for resampling
208             );
209
210     buf = malloc(bufsize);
211     if(!buf)
212         return;
213
214     initlame();
215
216     swf_SetU16(tag, 0); //delayseek
217     for(t=0;t<blocks;t++) {
218         int s;
219         U16*pos;
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);
224         len = 0;
225     }
226
227     free(buf);
228 }
229
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
236
237 void swf_SetSoundInfo(TAG*tag, SOUNDINFO*info)
238 {
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) {
253         int t;
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]);
259         }
260     }
261 }
262
263 #endif
264
265 #endif // RFXSWF_DISABLESOUND