Possible fix for bug #3094 - use normal malloc/free for stuff that gets
[blender.git] / source / blender / src / seqaudio.c
1 /**
2  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. The Blender
8  * Foundation also sells licenses for use in proprietary software under
9  * the Blender License.  See http://www.blender.org/BL/ for information
10  * about this.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
22  * All rights reserved.
23  *
24  * The Original Code is: all of this file.
25  *
26  * Contributor(s): intrr
27  *
28  * ***** END GPL/BL DUAL LICENSE BLOCK *****
29  */
30
31 #include <math.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #ifndef WIN32
36 #include <unistd.h>
37 #else
38 #include <io.h>
39 #endif   
40
41 #include <fcntl.h>
42 #include <stdio.h>
43
44 #include "MEM_guardedalloc.h"
45
46 #include "PIL_time.h"
47
48 #include "BMF_Api.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
52
53 #include "DNA_screen_types.h"
54 #include "DNA_sound_types.h"
55 #include "DNA_userdef_types.h"
56 #include "DNA_sequence_types.h"
57 #include "DNA_scene_types.h"
58 #include "DNA_ipo_types.h"
59
60 #include "BKE_utildefines.h"
61 #include "BKE_global.h"
62 #include "BKE_library.h" 
63 #include "BKE_blender.h" 
64 #include "BKE_main.h"    
65 #include "BKE_ipo.h"
66
67 #include "BIF_gl.h"
68 #include "BIF_graphics.h"
69 #include "BIF_keyval.h"
70 #include "BIF_mainqueue.h"
71 #include "BIF_resources.h"
72 #include "BIF_screen.h"
73 #include "BIF_toolbox.h"
74 #include "BIF_mywindow.h"
75 #include "BIF_space.h"
76 #include "BIF_glutil.h"
77 #include "BIF_interface.h"
78
79 #include "BSE_view.h"
80 #include "BSE_seqaudio.h"
81 #include "BIF_editsound.h"
82
83 #include "mydevice.h"
84 #include "blendef.h"
85 #include "render.h"     // RE_make_existing_file()
86
87
88 void audio_fill(void *mixdown, Uint8 *sstream, int len);
89 /* ************ GLOBALS ************* */
90
91 int audio_pos;
92 SDL_AudioSpec wav_spec;
93 int audio_scrub=0;
94 int audio_playing=0;
95 /////
96 //
97 /* local protos ------------------- */
98 void audio_mixdown(void);
99
100 static void makewavstring (char *string) 
101 {
102         char txt[64];
103
104         if (string==0) return;
105
106         strcpy(string, G.scene->r.pic);
107         BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
108
109         RE_make_existing_file(string);
110
111         if (BLI_strcasecmp(string + strlen(string) - 4, ".wav")) {
112                 sprintf(txt, "%04d_%04d.wav", (G.scene->r.sfra) , (G.scene->r.efra) );
113                 strcat(string, txt);
114         }
115 }
116
117 void audio_mixdown()
118 {
119         int file, c, totlen, totframe, i, oldcfra, cfra2=0;
120         char *buf;
121         Editing *ed;
122         Sequence *seq;
123
124         buf = MEM_mallocN(65536, "audio_mixdown");
125         makewavstring(buf);
126
127         file = open(buf, O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
128
129         if(file == -1) 
130         {
131                 error("Can't open output file");
132                 return;
133         }
134
135         strcpy(buf, "RIFFlengWAVEfmt fmln01ccRATEbsecBP16dataDLEN");
136         totframe = (EFRA - SFRA + 1);
137         totlen = (int) ( ((float)totframe / (float)G.scene->r.frs_sec) * (float)G.scene->audio.mixrate * 4.0);
138         printf("totlen %x\n", totlen);
139         memcpy(buf+4, &totlen, 4);
140         buf[16] = 0x10; buf[17] = buf[18] = buf[19] = 0; buf[20] = 1; buf[21] = 0;
141         buf[22] = 2; buf[23]= 0;
142         memcpy(buf+24, &G.scene->audio.mixrate, 4);
143         i = G.scene->audio.mixrate * 4;
144         memcpy(buf+28, &i, 4);
145         buf[32] = 4; buf[33] = 0; buf[34] = 16; buf[35] = 0;
146         i = totlen;
147         memcpy(buf+40, &i, 4);
148
149         if (G.order == B_ENDIAN) {
150                 /* swap the four ints to little endian */
151                 
152                 /* length */
153                 SWITCH_INT(buf[4]);
154
155                 /* audio rate */
156                 SWITCH_INT(buf[24]);
157
158                 /* audio mixrate * 4 */
159                 SWITCH_INT(buf[28]);
160                 
161                 /* length */
162                 SWITCH_INT(buf[40]);
163         }
164         
165         c = write(file, buf, 44);
166         
167         oldcfra = CFRA;
168         audiostream_play(SFRA, 0, 1);
169         for (CFRA = SFRA, i = 0; (CFRA<=EFRA); 
170              CFRA=(int) ( ((float)(audio_pos-64)/( G.scene->audio.mixrate*4 ))*(float)G.scene->r.frs_sec )) {
171                 if (cfra2 != CFRA) {
172                         cfra2 = CFRA;
173                         set_timecursor(CFRA);
174                 }
175                 memset(buf+i, 0, 64);
176                 ed= G.scene->ed;
177                 if (ed) {
178                         seq= ed->seqbasep->first;
179                         while(seq) {
180                                 if ((seq->type == SEQ_SOUND) && (seq->ipo)
181                                   &&(seq->startdisp<=G.scene->r.cfra+2) && (seq->enddisp>G.scene->r.cfra)) do_seq_ipo(seq);
182                                 seq= seq->next;
183                         }
184                 }               
185                 audio_fill(buf+i, NULL, 64);
186                 if (G.order == B_ENDIAN) {
187                         swab(buf+i, buf+i, 64);
188                 }
189                 if (i == (65536-64)) {
190                         i=0;
191                         write(file, buf, 65536);                        
192                 } else i+=64;
193         }
194         write(file, buf, i);
195         waitcursor(0);
196         CFRA = oldcfra;
197         close(file);
198         MEM_freeN(buf);
199
200         return;
201 }
202
203 static void audio_levels(Uint8 *buf, int len, float db, float facf, float pan)
204 {
205         int i;
206         float facl, facr, fac;
207         signed short *sample;
208         
209         if (pan>=0) { facr = 1.0; facl = 1.0-pan; }
210                else { facr = pan+1.0; facl = 1.0; }
211         
212         fac = pow(10.0, ((-(db+G.scene->audio.main))/20.0)) / facf;
213         facl /= fac;
214         facr /= fac;
215         
216         for (i=0; i<len; i+=4) {
217                 sample = (signed short*)(buf+i);
218                 sample[0] = (short) ((float)sample[0] * facl);
219                 sample[1] = (short) ((float)sample[1] * facr);
220         }
221 }
222
223 /* convert mono/stereo and sampling rate, alloc a buffer for
224  * sound->stream to contain the new sample, and set sound->streamlen
225  * accordingly.
226  */
227 void audio_makestream(bSound *sound)
228 {
229         signed short *source, *dest;
230         float ratio;
231         int i;
232
233         if ( (!sound)||(sound->stream)||(!sound->sample)||(!G.scene) ) {
234                 return;
235         }
236         ratio = (float)G.scene->audio.mixrate / (float)sound->sample->rate;
237         sound->streamlen = (int) ( (float)sound->sample->len * ratio * 2.0/((float)sound->sample->channels) );
238         sound->stream = malloc((int) ((float)sound->streamlen * 1.05));
239         if (sound->sample->rate == G.scene->audio.mixrate) {
240                 if (sound->sample->channels == 2) {
241                         memcpy(sound->stream, sound->sample->data, sound->streamlen);
242                         return;
243                 } else {
244                         for (source = (signed short*)(sound->sample->data),
245                              dest = (signed short*)(sound->stream),
246                                  i=0;
247                                  i<sound->streamlen/4;
248                                  dest += 2, source++, i++) dest[0] = dest[1] = source[0];
249                         return;
250                 }
251         }
252         if (sound->sample->channels == 1) {
253                 for (dest=(signed short*)(sound->stream), i=0, source=(signed short*)(sound->sample->data); 
254                      i<(sound->streamlen/4); dest+=2, i++)
255                         dest[0] = dest[1] = source[(int)((float)i/ratio)];
256         }
257         else if (sound->sample->channels == 2) {
258                 for (dest=(signed short*)(sound->stream), i=0, source=(signed short*)(sound->sample->data); 
259                      i<(sound->streamlen/2); dest+=2, i+=2) {
260                         dest[1] = source[(int)((float)i/ratio)];
261                         dest[0] = source[(int)((float)i/ratio)+1];                      
262                 }
263         }       
264 }
265
266 void audio_fill(void *mixdown, Uint8 *sstream, int len)
267 {    
268         static Editing *ed;
269         static Sequence *seq;
270         static Uint8* cvtbuf;
271         static bSound* sound;
272         static float facf;
273
274
275         ed= G.scene->ed;
276         if((ed) && (!(G.scene->audio.flag & AUDIO_MUTE))) {
277                 seq= ed->seqbasep->first;
278                 while(seq) {
279                         if ( (seq->type == SEQ_SOUND) &&
280                              (seq->sound) &&
281                              (!(seq->flag & SEQ_MUTE)))
282                         {
283                                 sound = seq->sound;
284                                 audio_makestream(sound);
285                                 if ((seq->curpos<sound->streamlen -len) && (seq->curpos>=0) &&
286                                     (seq->startdisp <= CFRA) && ((seq->enddisp) > CFRA))
287                                 {
288                                         if(seq->ipo && seq->ipo->curve.first) facf = seq->facf0; else facf = 1.0;
289                                         cvtbuf = malloc(len);                                   
290                                         memcpy(cvtbuf, ((Uint8*)sound->stream)+(seq->curpos & (~3)), len);
291                                         audio_levels(cvtbuf, len, seq->level, facf, seq->pan);
292                                         if (!mixdown) {
293                                                 SDL_MixAudio(sstream, cvtbuf, len, SDL_MIX_MAXVOLUME);
294                                         } else {
295                                                 SDL_MixAudio((Uint8*)mixdown, cvtbuf, len, SDL_MIX_MAXVOLUME);                                  
296                                         }
297                                         free(cvtbuf);                                           
298                                 }
299                         seq->curpos += len;
300                         }
301                         seq= seq->next;
302                 }       
303         }
304
305        
306     audio_pos += len;    
307     if (audio_scrub) { 
308         audio_scrub--;
309         if (!audio_scrub) {
310                 audiostream_stop();
311         }
312     }
313 }    
314
315 static int audio_init(SDL_AudioSpec *desired)
316 {
317         SDL_AudioSpec *obtained, *hardware_spec;
318
319         SDL_CloseAudio();
320
321         obtained = (SDL_AudioSpec*)MEM_mallocN(sizeof(SDL_AudioSpec), "SDL_AudioSpec");
322
323         desired->callback=audio_fill;
324
325         if ( SDL_OpenAudio(desired, obtained) < 0 ){
326           fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
327           if (obtained) MEM_freeN(obtained);
328           return 0;
329         }
330         hardware_spec=obtained;
331         
332         MEM_freeN(obtained);
333
334         SDL_PauseAudio(1);
335         return 1;
336 }
337
338 void audiostream_play(Uint32 startframe, Uint32 duration, int mixdown)
339 {
340         static SDL_AudioSpec desired;
341         Editing *ed;
342         Sequence *seq;
343         bSound *sound=NULL;
344
345         ed= G.scene->ed;
346         if(ed) {
347                 seq= ed->seqbasep->first;
348                 while(seq) {
349                         if ((seq->type == SEQ_SOUND) && (seq->sound)) {
350                                 sound = ((bSound*)seq->sound);
351                                 seq->curpos = (int)( (((float)((float)startframe-(float)seq->start)/(float)G.scene->r.frs_sec)*((float)G.scene->audio.mixrate)*4 ));
352                         }
353                         seq= seq->next;
354                 }       
355         }
356
357         if(sound) {
358                 /* this call used to be in startup */
359                 sound_init_audio();
360         }
361
362         if (!(duration + mixdown)) {
363                 desired.freq=G.scene->audio.mixrate;
364                 desired.format=AUDIO_S16SYS;
365                 desired.channels=2;
366                 desired.samples=U.mixbufsize;
367                 desired.userdata=0;     
368                 if (audio_init(&desired)==0) {
369                         U.mixbufsize = 0;       /* no audio */
370                 }
371         }
372     audio_pos = ( ((int)( (((float)startframe)/(float)G.scene->r.frs_sec)*(G.scene->audio.mixrate)*4 )) & (~3) );               
373
374     audio_scrub = duration;
375     if (!mixdown) {
376         SDL_PauseAudio(0);
377             audio_playing++;
378         }
379 }
380
381 void audiostream_start(Uint32 frame)
382 {
383         audiostream_play(frame, 0, 0);
384 }
385
386 void audiostream_scrub(Uint32 frame)
387 {
388         if (U.mixbufsize) audiostream_play(frame, 4096/U.mixbufsize, 0);
389 }
390
391 void audiostream_stop(void)
392 {
393     SDL_PauseAudio(1);
394     audio_playing=0;
395 }
396
397 int audiostream_pos(void) 
398 {
399         int pos;
400         
401         pos = (int) ( ((float)(audio_pos-U.mixbufsize)/( G.scene->audio.mixrate*4 ))*(float)G.scene->r.frs_sec );
402         if (pos<1) pos=1;
403         return ( pos );
404 }
405