~diresu/blender/blender-command-port

« back to all changes in this revision

Viewing changes to source/blender/src/seqaudio.c

  • Committer: theeth
  • Date: 2008-10-14 16:52:04 UTC
  • Revision ID: vcs-imports@canonical.com-20081014165204-r32w2gm6s0osvdhn
copy back trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  $Id: seqaudio.c 16941 2008-10-06 01:59:11Z campbellbarton $
 
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_t *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_t *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_t *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_t * sstream, int len)
 
298
{
 
299
        uint8_t* 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_t*)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_t*)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_t * sstream, 
 
331
                                int len)
 
332
{
 
333
        uint8_t* 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_t*)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_t *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_t *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_t 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_t startframe, uint32_t 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_t frame)
 
561
{
 
562
        audiostream_play(frame, 0, 0);
 
563
}
 
564
 
 
565
void audiostream_scrub(uint32_t 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