resolve some compiler warnings with intel c/c++ compiler
[blender-staging.git] / source / blender / src / seqaudio.c
1 /*
2  *  $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): intrr, Peter Schlaile
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30
31 #include <math.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #ifndef WIN32
36 #define __USE_XOPEN /* Needed for swab on linux */
37 #include <unistd.h>
38 #undef __USE_XOPEN
39 #else
40 #include <io.h>
41 #endif   
42
43 #include <fcntl.h>
44 #include <stdio.h>
45
46 #include "MEM_guardedalloc.h"
47
48 #include "PIL_time.h"
49
50 #include "BMF_Api.h"
51
52 #include "BLI_blenlib.h"
53 #include "BLI_arithb.h"
54
55 #include "DNA_screen_types.h"
56 #include "DNA_sound_types.h"
57 #include "DNA_userdef_types.h"
58 #include "DNA_sequence_types.h"
59 #include "DNA_scene_types.h"
60 #include "DNA_ipo_types.h"
61
62 #include "BKE_utildefines.h"
63 #include "BKE_global.h"
64 #include "BKE_library.h" 
65 #include "BKE_blender.h" 
66 #include "BKE_main.h"    
67 #include "BKE_ipo.h"
68
69 #include "BIF_gl.h"
70 #include "BIF_graphics.h"
71 #include "BIF_keyval.h"
72 #include "BIF_mainqueue.h"
73 #include "BIF_resources.h"
74 #include "BIF_screen.h"
75 #include "BIF_toolbox.h"
76 #include "BIF_mywindow.h"
77 #include "BIF_space.h"
78 #include "BIF_glutil.h"
79 #include "BIF_interface.h"
80
81 #include "BSE_view.h"
82 #include "BSE_seqaudio.h"
83 #include "BIF_editsound.h"
84
85 #include "mydevice.h"
86 #include "blendef.h"
87
88
89 static void audio_fill(void *mixdown, Uint8 *sstream, int len);
90 /* ************ GLOBALS ************* */
91
92 static int audio_pos;
93 static int audio_scrub=0;
94 static int audio_playing=0;
95 static int audio_initialised=0;
96 static int audio_startframe=0;
97 static double audio_starttime = 0.0;
98 /////
99 //
100 /* local protos ------------------- */
101 void audio_mixdown(void);
102
103 void makewavstring (char *string) 
104 {
105         char txt[64];
106
107         if (string==0) return;
108
109         strcpy(string, G.scene->r.pic);
110         BLI_convertstringcode(string, G.sce);
111
112         BLI_make_existing_file(string);
113
114         if (BLI_strcasecmp(string + strlen(string) - 4, ".wav")) {
115                 sprintf(txt, "%04d_%04d.wav", (G.scene->r.sfra) , (G.scene->r.efra) );
116                 strcat(string, txt);
117         }
118 }
119
120 void audio_mixdown()
121 {
122 #ifndef DISABLE_SDL
123         int file, c, totlen, totframe, i, oldcfra;
124         char *buf;
125
126         buf = MEM_mallocN(65536, "audio_mixdown");
127         makewavstring(buf);
128
129         file = open(buf, O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
130
131         if(file == -1) 
132         {
133                 error("Can't open output file");
134                 return;
135         }
136         
137         waitcursor(1);
138         
139         printf("Saving: %s ", buf);
140
141         strcpy(buf, "RIFFlengWAVEfmt fmln01ccRATEbsecBP16dataDLEN");
142         totframe = (EFRA - SFRA + 1);
143         totlen = (int) ( FRA2TIME(totframe) * (float)G.scene->audio.mixrate * 4.0);
144         printf(" totlen %d\n", totlen+36+8);
145         
146         totlen+= 36;    /* len is filesize-8 in WAV spec, total header is 44 bytes */
147         memcpy(buf+4, &totlen, 4);
148         totlen-= 36;
149         
150         buf[16] = 0x10; buf[17] = buf[18] = buf[19] = 0; buf[20] = 1; buf[21] = 0;
151         buf[22] = 2; buf[23]= 0;
152         memcpy(buf+24, &G.scene->audio.mixrate, 4);
153         i = G.scene->audio.mixrate * 4;
154         memcpy(buf+28, &i, 4);
155         buf[32] = 4; buf[33] = 0; buf[34] = 16; buf[35] = 0;
156         i = totlen;
157         memcpy(buf+40, &i, 4);
158
159         if (G.order == B_ENDIAN) {
160                 /* swap the four ints to little endian */
161                 
162                 /* length */
163                 SWITCH_INT(buf[4]);
164                 
165                 /* audio rate */
166                 SWITCH_INT(buf[24]);
167
168                 /* audio mixrate * 4 */
169                 SWITCH_INT(buf[28]);
170                 
171                 /* length */
172                 SWITCH_INT(buf[40]);
173         }
174         
175         c = write(file, buf, 44);
176         
177         oldcfra = CFRA;
178         audiostream_play(SFRA, 0, 1);
179         
180         i= 0;
181         while ( totlen > 0 ) {
182                 totlen -= 64;
183                 
184                 memset(buf+i, 0, 64);
185                 
186                 CFRA=(int) ( ((float)(audio_pos-64)/( G.scene->audio.mixrate*4 ))*FPS );
187                         
188                 audio_fill(buf+i, NULL, 64);
189                 if (G.order == B_ENDIAN) {
190                         char tbuf[64];
191                         memcpy(tbuf, buf+i, 64);
192                         swab(tbuf, buf+i, 64);
193                 }
194                 if (i == (65536-64)) {
195                         i=0;
196                         write(file, buf, 65536);                        
197                 } 
198                 else i+=64;
199         }
200         write(file, buf, i);
201         
202         waitcursor(0);
203         CFRA = oldcfra;
204         close(file);
205         MEM_freeN(buf);
206
207         return;
208 #endif
209 }
210
211 void audiostream_fill(Uint8 *mixdown, int len)
212 {    
213         int oldcfra = CFRA;
214         int i;
215
216         memset(mixdown, 0, len);
217 #ifndef DISABLE_SDL
218         for (i = 0; i < len; i += 64) {
219                 CFRA = (int) ( ((float)(audio_pos-64)
220                                 /( G.scene->audio.mixrate*4 ))
221                                * FPS );
222
223                 audio_fill(mixdown + i, NULL, 
224                            (len - i) > 64 ? 64 : (len - i));
225         }
226
227         CFRA = oldcfra;
228 #endif
229 }
230
231
232 static void audio_levels(Uint8 *buf, int len, float db, float facf, float pan)
233 {
234         int i;
235         float facl, facr, fac;
236         signed short *sample;
237         
238         if (pan>=0) { facr = 1.0; facl = 1.0-pan; }
239                else { facr = pan+1.0; facl = 1.0; }
240         
241         fac = pow(10.0, ((-(db+G.scene->audio.main))/20.0)) / facf;
242         facl /= fac;
243         facr /= fac;
244         
245         for (i=0; i<len; i+=4) {
246                 sample = (signed short*)(buf+i);
247                 sample[0] = (short) ((float)sample[0] * facl);
248                 sample[1] = (short) ((float)sample[1] * facr);
249         }
250 }
251
252 /* convert mono/stereo and sampling rate, alloc a buffer for
253  * sound->stream to contain the new sample, and set sound->streamlen
254  * accordingly.
255  */
256 void audio_makestream(bSound *sound)
257 {
258         signed short *source, *dest;
259         float ratio;
260         int i;
261
262         if ( (!sound)||(sound->stream)||(!sound->sample)||(!G.scene) ) {
263                 return;
264         }
265         ratio = (float)G.scene->audio.mixrate / (float)sound->sample->rate;
266         sound->streamlen = (int) ( (float)sound->sample->len * ratio * 2.0/((float)sound->sample->channels) );
267         sound->stream = malloc((int) ((float)sound->streamlen * 1.05));
268         if (sound->sample->rate == G.scene->audio.mixrate) {
269                 if (sound->sample->channels == 2) {
270                         memcpy(sound->stream, sound->sample->data, sound->streamlen);
271                         return;
272                 } else {
273                         for (source = (signed short*)(sound->sample->data),
274                              dest = (signed short*)(sound->stream),
275                                  i=0;
276                                  i<sound->streamlen/4;
277                                  dest += 2, source++, i++) dest[0] = dest[1] = source[0];
278                         return;
279                 }
280         }
281         if (sound->sample->channels == 1) {
282                 for (dest=(signed short*)(sound->stream), i=0, source=(signed short*)(sound->sample->data); 
283                      i<(sound->streamlen/4); dest+=2, i++)
284                         dest[0] = dest[1] = source[(int)((float)i/ratio)];
285         }
286         else if (sound->sample->channels == 2) {
287                 for (dest=(signed short*)(sound->stream), i=0, source=(signed short*)(sound->sample->data); 
288                      i<(sound->streamlen/2); dest+=2, i+=2) {
289                         dest[1] = source[(int)((float)i/ratio)];
290                         dest[0] = source[(int)((float)i/ratio)+1];                      
291                 }
292         }       
293 }
294
295 #ifndef DISABLE_SDL
296 static void audio_fill_ram_sound(Sequence *seq, void * mixdown, 
297                                  Uint8 * sstream, int len)
298 {
299         Uint8* cvtbuf;
300         bSound* sound;
301         float facf;
302
303         sound = seq->sound;
304         audio_makestream(sound);
305         if ((seq->curpos<sound->streamlen -len) && (seq->curpos>=0) &&
306             (seq->startdisp <= CFRA) && ((seq->enddisp) > CFRA))
307         {
308                 if(seq->ipo && seq->ipo->curve.first) {
309                         do_seq_ipo(seq, CFRA);
310                         facf = seq->facf0;
311                 } else {
312                         facf = 1.0;
313                 }
314                 cvtbuf = malloc(len);                                   
315                 memcpy(cvtbuf, ((Uint8*)sound->stream)+(seq->curpos & (~3)), len);
316                 audio_levels(cvtbuf, len, seq->level, facf, seq->pan);
317                 if (!mixdown) {
318                         SDL_MixAudio(sstream, cvtbuf, len, SDL_MIX_MAXVOLUME);
319                 } else {
320                         SDL_MixAudio((Uint8*)mixdown, cvtbuf, len, SDL_MIX_MAXVOLUME);
321                 }
322                 free(cvtbuf);
323         }
324         seq->curpos += len;
325 }
326 #endif
327
328 #ifndef DISABLE_SDL
329 static void audio_fill_hd_sound(Sequence *seq, 
330                                 void * mixdown, Uint8 * sstream, 
331                                 int len)
332 {
333         Uint8* cvtbuf;
334         float facf;
335
336         if ((seq->curpos >= 0) &&
337             (seq->startdisp <= CFRA) && ((seq->enddisp) > CFRA))
338         {
339                 if(seq->ipo && seq->ipo->curve.first) {
340                         do_seq_ipo(seq, CFRA);
341                         facf = seq->facf0; 
342                 } else {
343                         facf = 1.0;
344                 }
345                 cvtbuf = malloc(len);
346                 
347                 sound_hdaudio_extract(seq->hdaudio, (short*) cvtbuf,
348                                       seq->curpos / 4,
349                                       G.scene->audio.mixrate,
350                                       2,
351                                       len / 4);
352                 audio_levels(cvtbuf, len, seq->level, facf, seq->pan);
353                 if (!mixdown) {
354                         SDL_MixAudio(sstream, 
355                                      cvtbuf, len, SDL_MIX_MAXVOLUME);
356                 } else {
357                         SDL_MixAudio((Uint8*)mixdown, 
358                                      cvtbuf, len, SDL_MIX_MAXVOLUME);
359                 }
360                 free(cvtbuf);
361         }
362         seq->curpos += len;
363 }
364 #endif
365
366 #ifndef DISABLE_SDL
367 static void audio_fill_seq(Sequence * seq, void * mixdown,
368                            Uint8 *sstream, int len, int advance_only)
369 {
370         while(seq) {
371                 if (seq->type == SEQ_META &&
372                     (!(seq->flag & SEQ_MUTE))) {
373                         if (seq->startdisp <= CFRA && seq->enddisp > CFRA) {
374                                 audio_fill_seq(seq->seqbase.first,
375                                                mixdown, sstream, len, 
376                                                advance_only);
377                         } else {
378                                 audio_fill_seq(seq->seqbase.first,
379                                                mixdown, sstream, len, 
380                                                1);
381                         }
382                 }
383                 if ( (seq->type == SEQ_RAM_SOUND) &&
384                      (seq->sound) &&
385                      (!(seq->flag & SEQ_MUTE))) {
386                         if (advance_only) {
387                                 seq->curpos += len;
388                         } else {
389                                 audio_fill_ram_sound(
390                                         seq, mixdown, sstream, len);
391                         }
392                 }
393                 if ( (seq->type == SEQ_HD_SOUND) &&
394                      (!(seq->flag & SEQ_MUTE))) {
395                         if (advance_only) {
396                                 seq->curpos += len;
397                         } else {
398                                 if (!seq->hdaudio) {
399                                         char name[FILE_MAXDIR+FILE_MAXFILE];
400
401                                         strncpy(name, seq->strip->dir, 
402                                                 FILE_MAXDIR-1);
403                                         strncat(name, 
404                                                 seq->strip->stripdata->name, 
405                                                 FILE_MAXFILE-1);
406                                         BLI_convertstringcode(name, G.sce);
407                                 
408                                         seq->hdaudio= sound_open_hdaudio(name);
409                                 }
410                                 if (seq->hdaudio) {
411                                         audio_fill_hd_sound(seq, mixdown, 
412                                                             sstream, len);
413                                 }
414                         }
415                 }
416                 seq = seq->next;
417         }
418 }
419 #endif
420
421 #ifndef DISABLE_SDL
422 static void audio_fill(void *mixdown, Uint8 *sstream, int len)
423 {    
424         Editing *ed;
425         Sequence *seq;
426
427         ed = G.scene->ed;
428         if((ed) && (!(G.scene->audio.flag & AUDIO_MUTE))) {
429                 seq = ed->seqbasep->first;
430                 audio_fill_seq(seq, mixdown, sstream, len, 0);
431         }
432        
433         audio_pos += len;    
434         if (audio_scrub) { 
435                 audio_scrub--;
436                 if (!audio_scrub) {
437                         audiostream_stop();
438                 }
439         }
440 }    
441 #endif
442
443 #ifndef DISABLE_SDL
444 static int audio_init(SDL_AudioSpec *desired)
445 {
446         SDL_AudioSpec *obtained, *hardware_spec;
447
448         SDL_CloseAudio();
449
450         obtained = (SDL_AudioSpec*)MEM_mallocN(sizeof(SDL_AudioSpec), 
451                                                "SDL_AudioSpec");
452
453         desired->callback=audio_fill;
454
455         if ( SDL_OpenAudio(desired, obtained) < 0 ) {
456                 fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
457                 if (obtained) MEM_freeN(obtained);
458                 return 0;
459         }
460         audio_initialised = 1;
461         hardware_spec=obtained;
462         
463         MEM_freeN(obtained);
464
465         SDL_PauseAudio(0);
466         return 1;
467 }
468 #endif
469
470 static int audiostream_play_seq(Sequence * seq, Uint32 startframe)
471 {
472         char name[FILE_MAXDIR+FILE_MAXFILE];
473         int have_sound = 0;
474
475         while(seq) {
476                 if (seq->type == SEQ_META) {
477                         if (audiostream_play_seq(
478                                     seq->seqbase.first, startframe)) {
479                                 have_sound = 1;
480                         }
481                 }
482                 if ((seq->type == SEQ_RAM_SOUND) && (seq->sound)) {
483                         have_sound = 1;
484                         seq->curpos = (int)( (FRA2TIME(
485                                                       (double) startframe -
486                                                       (double) seq->start +
487                                                       (double) 
488                                                       seq->anim_startofs)
489                                               * ((float)G.scene->audio.mixrate)
490                                               * 4 ));
491                 }
492                 if ((seq->type == SEQ_HD_SOUND)) {
493                         have_sound = 1;
494                         if (!seq->hdaudio) {
495                                 strncpy(name, seq->strip->dir, FILE_MAXDIR-1);
496                                 strncat(name, seq->strip->stripdata->name, 
497                                         FILE_MAXFILE-1);
498                                 
499                                 seq->hdaudio = sound_open_hdaudio(name);
500                         }
501                         seq->curpos = (int)( (FRA2TIME((double) startframe - 
502                                                        (double) seq->start +
503                                                        (double)
504                                                        seq->anim_startofs)
505                                               * ((float)G.scene->audio.mixrate)
506                                               * 4 ));
507                 }
508                 seq= seq->next;
509         }
510         return have_sound;
511 }
512
513 void audiostream_play(Uint32 startframe, Uint32 duration, int mixdown)
514 {
515 #ifndef DISABLE_SDL
516         static SDL_AudioSpec desired;
517         Editing *ed;
518         int have_sound = 0;
519
520         ed= G.scene->ed;
521         if(ed) {
522                 have_sound = 
523                         audiostream_play_seq(ed->seqbasep->first, startframe);
524         }
525
526         if(have_sound) {
527                 /* this call used to be in startup */
528                 sound_init_audio();
529         }
530
531         if (U.mixbufsize && !audio_initialised && !mixdown) {
532                 desired.freq=G.scene->audio.mixrate;
533                 desired.format=AUDIO_S16SYS;
534                 desired.channels=2;
535                 desired.samples=U.mixbufsize;
536                 desired.userdata=0;
537
538                 if (audio_init(&desired)==0) {
539                         U.mixbufsize = 0;       /* no audio */
540                 }
541         }
542
543         audio_startframe = startframe;
544         audio_pos = ( ((int)( FRA2TIME(startframe)
545                               *(G.scene->audio.mixrate)*4 )) & (~3) );
546         audio_starttime = PIL_check_seconds_timer();
547
548         /* if audio already is playing, just reseek, otherwise
549            remember scrub-duration */
550         if (!(audio_playing && !audio_scrub)) {
551                 audio_scrub = duration;
552         }
553         if (!mixdown) {
554                 SDL_PauseAudio(0);
555                 audio_playing++;
556         }
557 #endif
558 }
559
560 void audiostream_start(Uint32 frame)
561 {
562         audiostream_play(frame, 0, 0);
563 }
564
565 void audiostream_scrub(Uint32 frame)
566 {
567         if (U.mixbufsize) audiostream_play(frame, 4096/U.mixbufsize, 0);
568 }
569
570 void audiostream_stop(void)
571 {
572 #ifndef DISABLE_SDL
573         SDL_PauseAudio(1);
574         audio_playing=0;
575 #endif
576 }
577
578 int audiostream_pos(void) 
579 {
580         int pos;
581
582         if (U.mixbufsize) {
583                 pos = (int) (((double)(audio_pos-U.mixbufsize)
584                               / ( G.scene->audio.mixrate*4 ))
585                              * FPS );
586         } else { /* fallback to seconds_timer when no audio available */
587                 pos = (int) ((PIL_check_seconds_timer() - audio_starttime) 
588                              * FPS);
589         }
590
591         if (pos < audio_startframe) pos = audio_startframe;
592         return ( pos );
593 }
594