== Sequencer ==
[plumiferos.git] / source / blender / src / seqaudio.c
blobbf9686f470de0d085f1b4d50a4be009e07bd9104
1 /*
2 * $Id: seqaudio.c 12979 2007-12-23 17:01:44Z schlaile $
4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
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. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
12 * about this.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): intrr, Peter Schlaile
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
33 #include <math.h>
34 #include <stdlib.h>
35 #include <string.h>
37 #ifndef WIN32
38 #define __USE_XOPEN /* Needed for swab on linux */
39 #include <unistd.h>
40 #undef __USE_XOPEN
41 #else
42 #include <io.h>
43 #endif
45 #include <fcntl.h>
46 #include <stdio.h>
48 #include "MEM_guardedalloc.h"
50 #include "PIL_time.h"
52 #include "BMF_Api.h"
54 #include "BLI_blenlib.h"
55 #include "BLI_arithb.h"
57 #include "DNA_screen_types.h"
58 #include "DNA_sound_types.h"
59 #include "DNA_userdef_types.h"
60 #include "DNA_sequence_types.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_ipo_types.h"
64 #include "BKE_utildefines.h"
65 #include "BKE_global.h"
66 #include "BKE_library.h"
67 #include "BKE_blender.h"
68 #include "BKE_main.h"
69 #include "BKE_ipo.h"
71 #include "BIF_gl.h"
72 #include "BIF_graphics.h"
73 #include "BIF_keyval.h"
74 #include "BIF_mainqueue.h"
75 #include "BIF_resources.h"
76 #include "BIF_screen.h"
77 #include "BIF_toolbox.h"
78 #include "BIF_mywindow.h"
79 #include "BIF_space.h"
80 #include "BIF_glutil.h"
81 #include "BIF_interface.h"
83 #include "BSE_view.h"
84 #include "BSE_seqaudio.h"
85 #include "BIF_editsound.h"
87 #include "mydevice.h"
88 #include "blendef.h"
91 void audio_fill(void *mixdown, Uint8 *sstream, int len);
92 /* ************ GLOBALS ************* */
94 static int audio_pos;
95 static int audio_scrub=0;
96 static int audio_playing=0;
97 static int audio_initialised=0;
98 static int audio_startframe=0;
99 static double audio_starttime = 0.0;
100 /////
102 /* local protos ------------------- */
103 void audio_mixdown(void);
105 void makewavstring (char *string)
107 char txt[64];
109 if (string==0) return;
111 strcpy(string, G.scene->r.pic);
112 BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
114 BLI_make_existing_file(string);
116 if (BLI_strcasecmp(string + strlen(string) - 4, ".wav")) {
117 sprintf(txt, "%04d_%04d.wav", (G.scene->r.sfra) , (G.scene->r.efra) );
118 strcat(string, txt);
122 void audio_mixdown()
124 int file, c, totlen, totframe, i, oldcfra;
125 char *buf;
127 buf = MEM_mallocN(65536, "audio_mixdown");
128 makewavstring(buf);
130 file = open(buf, O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
132 if(file == -1)
134 error("Can't open output file");
135 return;
138 waitcursor(1);
140 printf("Saving: %s ", buf);
142 strcpy(buf, "RIFFlengWAVEfmt fmln01ccRATEbsecBP16dataDLEN");
143 totframe = (EFRA - SFRA + 1);
144 totlen = (int) ( FRA2TIME(totframe) * (float)G.scene->audio.mixrate * 4.0);
145 printf(" totlen %d\n", totlen+36+8);
147 totlen+= 36; /* len is filesize-8 in WAV spec, total header is 44 bytes */
148 memcpy(buf+4, &totlen, 4);
149 totlen-= 36;
151 buf[16] = 0x10; buf[17] = buf[18] = buf[19] = 0; buf[20] = 1; buf[21] = 0;
152 buf[22] = 2; buf[23]= 0;
153 memcpy(buf+24, &G.scene->audio.mixrate, 4);
154 i = G.scene->audio.mixrate * 4;
155 memcpy(buf+28, &i, 4);
156 buf[32] = 4; buf[33] = 0; buf[34] = 16; buf[35] = 0;
157 i = totlen;
158 memcpy(buf+40, &i, 4);
160 if (G.order == B_ENDIAN) {
161 /* swap the four ints to little endian */
163 /* length */
164 SWITCH_INT(buf[4]);
166 /* audio rate */
167 SWITCH_INT(buf[24]);
169 /* audio mixrate * 4 */
170 SWITCH_INT(buf[28]);
172 /* length */
173 SWITCH_INT(buf[40]);
176 c = write(file, buf, 44);
178 oldcfra = CFRA;
179 audiostream_play(SFRA, 0, 1);
181 i= 0;
182 while ( totlen > 0 ) {
183 totlen -= 64;
185 memset(buf+i, 0, 64);
187 CFRA=(int) ( ((float)(audio_pos-64)/( G.scene->audio.mixrate*4 ))*FPS );
189 audio_fill(buf+i, NULL, 64);
190 if (G.order == B_ENDIAN) {
191 char tbuf[64];
192 memcpy(tbuf, buf+i, 64);
193 swab(tbuf, buf+i, 64);
195 if (i == (65536-64)) {
196 i=0;
197 write(file, buf, 65536);
199 else i+=64;
201 write(file, buf, i);
203 waitcursor(0);
204 CFRA = oldcfra;
205 close(file);
206 MEM_freeN(buf);
208 return;
211 void audiostream_fill(Uint8 *mixdown, int len)
213 int oldcfra = CFRA;
214 int i;
216 memset(mixdown, 0, len);
218 for (i = 0; i < len; i += 64) {
219 CFRA = (int) ( ((float)(audio_pos-64)
220 /( G.scene->audio.mixrate*4 ))
221 * FPS );
223 audio_fill(mixdown + i, NULL,
224 (len - i) > 64 ? 64 : (len - i));
227 CFRA = oldcfra;
231 static void audio_levels(Uint8 *buf, int len, float db, float facf, float pan)
233 int i;
234 float facl, facr, fac;
235 signed short *sample;
237 if (pan>=0) { facr = 1.0; facl = 1.0-pan; }
238 else { facr = pan+1.0; facl = 1.0; }
240 fac = pow(10.0, ((-(db+G.scene->audio.main))/20.0)) / facf;
241 facl /= fac;
242 facr /= fac;
244 for (i=0; i<len; i+=4) {
245 sample = (signed short*)(buf+i);
246 sample[0] = (short) ((float)sample[0] * facl);
247 sample[1] = (short) ((float)sample[1] * facr);
251 /* convert mono/stereo and sampling rate, alloc a buffer for
252 * sound->stream to contain the new sample, and set sound->streamlen
253 * accordingly.
255 void audio_makestream(bSound *sound)
257 signed short *source, *dest;
258 float ratio;
259 int i;
261 if ( (!sound)||(sound->stream)||(!sound->sample)||(!G.scene) ) {
262 return;
264 ratio = (float)G.scene->audio.mixrate / (float)sound->sample->rate;
265 sound->streamlen = (int) ( (float)sound->sample->len * ratio * 2.0/((float)sound->sample->channels) );
266 sound->stream = malloc((int) ((float)sound->streamlen * 1.05));
267 if (sound->sample->rate == G.scene->audio.mixrate) {
268 if (sound->sample->channels == 2) {
269 memcpy(sound->stream, sound->sample->data, sound->streamlen);
270 return;
271 } else {
272 for (source = (signed short*)(sound->sample->data),
273 dest = (signed short*)(sound->stream),
274 i=0;
275 i<sound->streamlen/4;
276 dest += 2, source++, i++) dest[0] = dest[1] = source[0];
277 return;
280 if (sound->sample->channels == 1) {
281 for (dest=(signed short*)(sound->stream), i=0, source=(signed short*)(sound->sample->data);
282 i<(sound->streamlen/4); dest+=2, i++)
283 dest[0] = dest[1] = source[(int)((float)i/ratio)];
285 else if (sound->sample->channels == 2) {
286 for (dest=(signed short*)(sound->stream), i=0, source=(signed short*)(sound->sample->data);
287 i<(sound->streamlen/2); dest+=2, i+=2) {
288 dest[1] = source[(int)((float)i/ratio)];
289 dest[0] = source[(int)((float)i/ratio)+1];
294 static void audio_fill_ram_sound(Sequence *seq, void * mixdown,
295 Uint8 * sstream, int len)
297 Uint8* cvtbuf;
298 bSound* sound;
299 float facf;
301 sound = seq->sound;
302 audio_makestream(sound);
303 if ((seq->curpos<sound->streamlen -len) && (seq->curpos>=0) &&
304 (seq->startdisp <= CFRA) && ((seq->enddisp) > CFRA))
306 if(seq->ipo && seq->ipo->curve.first) {
307 do_seq_ipo(seq);
308 facf = seq->facf0;
309 } else {
310 facf = 1.0;
312 cvtbuf = malloc(len);
313 memcpy(cvtbuf, ((Uint8*)sound->stream)+(seq->curpos & (~3)), len);
314 audio_levels(cvtbuf, len, seq->level, facf, seq->pan);
315 if (!mixdown) {
316 SDL_MixAudio(sstream, cvtbuf, len, SDL_MIX_MAXVOLUME);
317 } else {
318 SDL_MixAudio((Uint8*)mixdown, cvtbuf, len, SDL_MIX_MAXVOLUME);
320 free(cvtbuf);
322 seq->curpos += len;
325 static void audio_fill_hd_sound(Sequence *seq,
326 void * mixdown, Uint8 * sstream,
327 int len)
329 Uint8* cvtbuf;
330 float facf;
332 if ((seq->curpos >= 0) &&
333 (seq->startdisp <= CFRA) && ((seq->enddisp) > CFRA))
335 if(seq->ipo && seq->ipo->curve.first) {
336 do_seq_ipo(seq);
337 facf = seq->facf0;
338 } else {
339 facf = 1.0;
341 cvtbuf = malloc(len);
343 sound_hdaudio_extract(seq->hdaudio, (short*) cvtbuf,
344 seq->curpos / 4,
345 G.scene->audio.mixrate,
347 len / 4);
348 audio_levels(cvtbuf, len, seq->level, facf, seq->pan);
349 if (!mixdown) {
350 SDL_MixAudio(sstream,
351 cvtbuf, len, SDL_MIX_MAXVOLUME);
352 } else {
353 SDL_MixAudio((Uint8*)mixdown,
354 cvtbuf, len, SDL_MIX_MAXVOLUME);
356 free(cvtbuf);
358 seq->curpos += len;
361 static void audio_fill_seq(Sequence * seq, void * mixdown,
362 Uint8 *sstream, int len, int advance_only)
364 while(seq) {
365 if (seq->type == SEQ_META &&
366 (!(seq->flag & SEQ_MUTE))) {
367 if (seq->startdisp <= CFRA && seq->enddisp > CFRA) {
368 audio_fill_seq(seq->seqbase.first,
369 mixdown, sstream, len,
370 advance_only);
371 } else {
372 audio_fill_seq(seq->seqbase.first,
373 mixdown, sstream, len,
377 if ( (seq->type == SEQ_RAM_SOUND) &&
378 (seq->sound) &&
379 (!(seq->flag & SEQ_MUTE))) {
380 if (advance_only) {
381 seq->curpos += len;
382 } else {
383 audio_fill_ram_sound(
384 seq, mixdown, sstream, len);
387 if ( (seq->type == SEQ_HD_SOUND) &&
388 (!(seq->flag & SEQ_MUTE))) {
389 if (advance_only) {
390 seq->curpos += len;
391 } else {
392 if (!seq->hdaudio) {
393 char name[FILE_MAXDIR+FILE_MAXFILE];
395 strncpy(name, seq->strip->dir,
396 FILE_MAXDIR-1);
397 strncat(name,
398 seq->strip->stripdata->name,
399 FILE_MAXFILE-1);
400 BLI_convertstringcode(name, G.sce,
401 G.scene->r.cfra);
403 seq->hdaudio= sound_open_hdaudio(name);
405 if (seq->hdaudio) {
406 audio_fill_hd_sound(seq, mixdown,
407 sstream, len);
411 seq = seq->next;
415 void audio_fill(void *mixdown, Uint8 *sstream, int len)
417 Editing *ed;
418 Sequence *seq;
420 ed = G.scene->ed;
421 if((ed) && (!(G.scene->audio.flag & AUDIO_MUTE))) {
422 seq = ed->seqbasep->first;
423 audio_fill_seq(seq, mixdown, sstream, len, 0);
426 audio_pos += len;
427 if (audio_scrub) {
428 audio_scrub--;
429 if (!audio_scrub) {
430 audiostream_stop();
435 static int audio_init(SDL_AudioSpec *desired)
437 SDL_AudioSpec *obtained, *hardware_spec;
439 SDL_CloseAudio();
441 obtained = (SDL_AudioSpec*)MEM_mallocN(sizeof(SDL_AudioSpec),
442 "SDL_AudioSpec");
444 desired->callback=audio_fill;
446 if ( SDL_OpenAudio(desired, obtained) < 0 ) {
447 fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
448 if (obtained) MEM_freeN(obtained);
449 return 0;
451 audio_initialised = 1;
452 hardware_spec=obtained;
454 MEM_freeN(obtained);
456 SDL_PauseAudio(0);
457 return 1;
460 static int audiostream_play_seq(Sequence * seq, Uint32 startframe)
462 char name[FILE_MAXDIR+FILE_MAXFILE];
463 int have_sound = 0;
465 while(seq) {
466 if (seq->type == SEQ_META) {
467 if (audiostream_play_seq(
468 seq->seqbase.first, startframe)) {
469 have_sound = 1;
472 if ((seq->type == SEQ_RAM_SOUND) && (seq->sound)) {
473 have_sound = 1;
474 seq->curpos = (int)( (FRA2TIME((double) startframe -
475 (double) seq->start)
476 * ((float)G.scene->audio.mixrate)
477 * 4 ));
479 if ((seq->type == SEQ_HD_SOUND)) {
480 have_sound = 1;
481 if (!seq->hdaudio) {
482 strncpy(name, seq->strip->dir, FILE_MAXDIR-1);
483 strncat(name, seq->strip->stripdata->name,
484 FILE_MAXFILE-1);
486 seq->hdaudio = sound_open_hdaudio(name);
488 seq->curpos = (int)( (FRA2TIME((double) startframe -
489 (double) seq->start)
490 * ((float)G.scene->audio.mixrate)
491 * 4 ));
493 seq= seq->next;
495 return have_sound;
498 void audiostream_play(Uint32 startframe, Uint32 duration, int mixdown)
500 static SDL_AudioSpec desired;
501 Editing *ed;
502 int have_sound = 0;
504 ed= G.scene->ed;
505 if(ed) {
506 have_sound =
507 audiostream_play_seq(ed->seqbasep->first, startframe);
510 if(have_sound) {
511 /* this call used to be in startup */
512 sound_init_audio();
515 if (U.mixbufsize && !audio_initialised && !mixdown) {
516 desired.freq=G.scene->audio.mixrate;
517 desired.format=AUDIO_S16SYS;
518 desired.channels=2;
519 desired.samples=U.mixbufsize;
520 desired.userdata=0;
522 fprintf(stderr, "freq: %d, samples: %d\n",
523 G.scene->audio.mixrate, U.mixbufsize);
525 if (audio_init(&desired)==0) {
526 U.mixbufsize = 0; /* no audio */
530 audio_startframe = startframe;
531 audio_pos = ( ((int)( FRA2TIME(startframe)
532 *(G.scene->audio.mixrate)*4 )) & (~3) );
534 /* if audio already is playing, just reseek, otherwise
535 remember scrub-duration */
536 if (!(audio_playing && !audio_scrub)) {
537 audio_scrub = duration;
539 if (!mixdown) {
540 SDL_PauseAudio(0);
541 audio_playing++;
545 void audiostream_start(Uint32 frame)
547 audiostream_play(frame, 0, 0);
550 void audiostream_scrub(Uint32 frame)
552 if (U.mixbufsize) audiostream_play(frame, 4096/U.mixbufsize, 0);
555 void audiostream_stop(void)
557 SDL_PauseAudio(1);
558 audio_playing=0;
561 int audiostream_pos(void)
563 int pos;
565 if (U.mixbufsize) {
566 pos = (int) (((double)(audio_pos-U.mixbufsize)
567 / ( G.scene->audio.mixrate*4 ))
568 * FPS );
569 } else { /* fallback to seconds_timer when no audio available */
570 pos = (int) ((PIL_check_seconds_timer() - audio_starttime)
571 * FPS);
574 if (pos < audio_startframe) pos = audio_startframe;
575 return ( pos );