== Sequencer ==

This fixes:
[#18007] Audio playback of a scene strip containing audio is broken.

(needed a different recursion protection than video render code, since
video and audio render can be called simultaneously because of SDL audio thread
callbacks)

Also: we don't display a wait cursor, if the scene strip has DOSEQ enabled.
(no need to wait, it is the sequencer which is realtime by definition :)
This commit is contained in:
Peter Schlaile 2009-05-21 10:25:40 +00:00
parent 3f584de8ec
commit 5fc6afe240
4 changed files with 139 additions and 43 deletions

@ -43,10 +43,10 @@
void audio_mixdown();
void audio_makestream(bSound *sound);
void audiostream_play(uint32_t startframe, uint32_t duration, int mixdown);
void audiostream_play(int startframe, uint32_t duration, int mixdown);
void audiostream_fill(uint8_t* mixdown, int len);
void audiostream_start(uint32_t frame);
void audiostream_scrub(uint32_t frame);
void audiostream_start(int frame);
void audiostream_scrub(int frame);
void audiostream_stop(void);
int audiostream_pos(void);

@ -668,6 +668,7 @@ typedef struct Scene {
#define R_STAMP_INFO 0x4000
#define R_FULL_SAMPLE 0x8000
#define R_COMP_RERENDER 0x10000
#define R_RECURS_PROTECTION 0x20000
/* r->stamp */
#define R_STAMP_TIME 0x0001

@ -95,6 +95,12 @@ static int audio_playing=0;
static int audio_initialised=0;
static int audio_startframe=0;
static double audio_starttime = 0.0;
static Scene * audio_scene = 0; /* we can't use G.scene, since
Sequence Scene strips can change G.scene
(and SDL-audio-fill callback can be
called while we have G.scene changed!)
*/
/////
//
/* local protos ------------------- */
@ -217,7 +223,7 @@ void audiostream_fill(uint8_t *mixdown, int len)
#ifndef DISABLE_SDL
for (i = 0; i < len; i += 64) {
CFRA = (int) ( ((float)(audio_pos-64)
/( G.scene->audio.mixrate*4 ))
/( audio_scene->audio.mixrate*4 ))
* FPS );
audio_fill(mixdown + i, NULL,
@ -238,7 +244,7 @@ static void audio_levels(uint8_t *buf, int len, float db, float facf, float pan)
if (pan>=0) { facr = 1.0; facl = 1.0-pan; }
else { facr = pan+1.0; facl = 1.0; }
fac = pow(10.0, ((-(db+G.scene->audio.main))/20.0)) / facf;
fac = pow(10.0, ((-(db+audio_scene->audio.main))/20.0)) / facf;
facl /= fac;
facr /= fac;
@ -294,7 +300,8 @@ void audio_makestream(bSound *sound)
#ifndef DISABLE_SDL
static void audio_fill_ram_sound(Sequence *seq, void * mixdown,
uint8_t * sstream, int len)
uint8_t * sstream, int len,
int cfra)
{
uint8_t* cvtbuf;
bSound* sound;
@ -303,10 +310,10 @@ static void audio_fill_ram_sound(Sequence *seq, void * mixdown,
sound = seq->sound;
audio_makestream(sound);
if ((seq->curpos<sound->streamlen -len) && (seq->curpos>=0) &&
(seq->startdisp <= CFRA) && ((seq->enddisp) > CFRA))
(seq->startdisp <= cfra) && ((seq->enddisp) > cfra))
{
if(seq->ipo && seq->ipo->curve.first) {
do_seq_ipo(seq, CFRA);
do_seq_ipo(seq, cfra);
facf = seq->facf0;
} else {
facf = 1.0;
@ -328,16 +335,16 @@ static void audio_fill_ram_sound(Sequence *seq, void * mixdown,
#ifndef DISABLE_SDL
static void audio_fill_hd_sound(Sequence *seq,
void * mixdown, uint8_t * sstream,
int len)
int len, int cfra)
{
uint8_t* cvtbuf;
float facf;
if ((seq->curpos >= 0) &&
(seq->startdisp <= CFRA) && ((seq->enddisp) > CFRA))
(seq->startdisp <= cfra) && ((seq->enddisp) > cfra))
{
if(seq->ipo && seq->ipo->curve.first) {
do_seq_ipo(seq, CFRA);
do_seq_ipo(seq, cfra);
facf = seq->facf0;
} else {
facf = 1.0;
@ -346,7 +353,7 @@ static void audio_fill_hd_sound(Sequence *seq,
sound_hdaudio_extract(seq->hdaudio, (short*) cvtbuf,
seq->curpos / 4,
G.scene->audio.mixrate,
audio_scene->audio.mixrate,
2,
len / 4);
audio_levels(cvtbuf, len, seq->level, facf, seq->pan);
@ -365,19 +372,66 @@ static void audio_fill_hd_sound(Sequence *seq,
#ifndef DISABLE_SDL
static void audio_fill_seq(Sequence * seq, void * mixdown,
uint8_t *sstream, int len, int advance_only)
uint8_t *sstream, int len, int cfra,
int advance_only);
static void audio_fill_scene_strip(Sequence * seq, void * mixdown,
uint8_t *sstream, int len, int cfra,
int advance_only)
{
Editing *ed;
/* prevent eternal loop */
seq->scene->r.scemode |= R_RECURS_PROTECTION;
ed = seq->scene->ed;
if (ed) {
int sce_cfra = seq->sfra + seq->anim_startofs
+ cfra - seq->startdisp;
audio_fill_seq(ed->seqbasep->first,
mixdown,
sstream, len, sce_cfra,
advance_only);
}
/* restore */
seq->scene->r.scemode &= ~R_RECURS_PROTECTION;
}
#endif
#ifndef DISABLE_SDL
static void audio_fill_seq(Sequence * seq, void * mixdown,
uint8_t *sstream, int len, int cfra,
int advance_only)
{
while(seq) {
if (seq->type == SEQ_META &&
(!(seq->flag & SEQ_MUTE))) {
if (seq->startdisp <= CFRA && seq->enddisp > CFRA) {
if (seq->startdisp <= cfra && seq->enddisp > cfra) {
audio_fill_seq(seq->seqbase.first,
mixdown, sstream, len,
advance_only);
cfra, advance_only);
} else {
audio_fill_seq(seq->seqbase.first,
mixdown, sstream, len,
1);
cfra, 1);
}
}
if (seq->type == SEQ_SCENE
&& (!(seq->flag & SEQ_MUTE))
&& seq->scene
&& (seq->scene->r.scemode & R_DOSEQ)
&& !(seq->scene->r.scemode & R_RECURS_PROTECTION)) {
if (seq->startdisp <= cfra && seq->enddisp > cfra) {
audio_fill_scene_strip(
seq, mixdown, sstream, len,
cfra, advance_only);
} else {
audio_fill_scene_strip(
seq, mixdown, sstream, len,
cfra, 1);
}
}
if ( (seq->type == SEQ_RAM_SOUND) &&
@ -387,7 +441,8 @@ static void audio_fill_seq(Sequence * seq, void * mixdown,
seq->curpos += len;
} else {
audio_fill_ram_sound(
seq, mixdown, sstream, len);
seq, mixdown, sstream, len,
cfra);
}
}
if ( (seq->type == SEQ_HD_SOUND) &&
@ -405,7 +460,8 @@ static void audio_fill_seq(Sequence * seq, void * mixdown,
}
if (seq->hdaudio) {
audio_fill_hd_sound(seq, mixdown,
sstream, len);
sstream, len,
cfra);
}
}
}
@ -420,10 +476,15 @@ static void audio_fill(void *mixdown, uint8_t *sstream, int len)
Editing *ed;
Sequence *seq;
ed = G.scene->ed;
if((ed) && (!(G.scene->audio.flag & AUDIO_MUTE))) {
if (!audio_scene) {
return;
}
ed = audio_scene->ed;
if((ed) && (!(audio_scene->audio.flag & AUDIO_MUTE))) {
seq = ed->seqbasep->first;
audio_fill_seq(seq, mixdown, sstream, len, 0);
audio_fill_seq(seq, mixdown, sstream, len,
audio_scene->r.cfra, 0);
}
audio_pos += len;
@ -463,7 +524,7 @@ static int audio_init(SDL_AudioSpec *desired)
}
#endif
static int audiostream_play_seq(Sequence * seq, uint32_t startframe)
static int audiostream_play_seq(Sequence * seq, int startframe)
{
char name[FILE_MAXDIR+FILE_MAXFILE];
int have_sound = 0;
@ -475,14 +536,38 @@ static int audiostream_play_seq(Sequence * seq, uint32_t startframe)
have_sound = 1;
}
}
if (seq->type == SEQ_SCENE
&& seq->scene
&& (seq->scene->r.scemode & R_DOSEQ)
&& !(seq->scene->r.scemode & R_RECURS_PROTECTION)) {
Editing *ed;
/* prevent eternal loop */
seq->scene->r.scemode |= R_RECURS_PROTECTION;
ed = seq->scene->ed;
if (ed) {
int sce_cfra = seq->sfra + seq->anim_startofs
+ startframe - seq->startdisp;
if (audiostream_play_seq(ed->seqbasep->first,
sce_cfra)) {
have_sound = 1;
}
}
/* restore */
seq->scene->r.scemode &= ~R_RECURS_PROTECTION;
}
if ((seq->type == SEQ_RAM_SOUND) && (seq->sound)) {
have_sound = 1;
seq->curpos = (int)( (FRA2TIME(
(double) startframe -
(double) seq->start +
(double)
seq->anim_startofs)
* ((float)G.scene->audio.mixrate)
seq->curpos = (int)( (FRA2TIME(((double) startframe) -
((double) seq->start) +
((double)
seq->anim_startofs))
* ((float)audio_scene
->audio.mixrate)
* 4 ));
}
if ((seq->type == SEQ_HD_SOUND)) {
@ -494,11 +579,13 @@ static int audiostream_play_seq(Sequence * seq, uint32_t startframe)
seq->hdaudio = sound_open_hdaudio(name);
}
seq->curpos = (int)( (FRA2TIME((double) startframe -
(double) seq->start +
(double)
seq->anim_startofs)
* ((float)G.scene->audio.mixrate)
seq->curpos = (int)( (FRA2TIME(((double) startframe) -
((double) seq->start) +
((double)
seq->anim_startofs))
* ((float)audio_scene
->audio.mixrate)
* 4 ));
}
seq= seq->next;
@ -506,14 +593,16 @@ static int audiostream_play_seq(Sequence * seq, uint32_t startframe)
return have_sound;
}
void audiostream_play(uint32_t startframe, uint32_t duration, int mixdown)
void audiostream_play(int startframe, uint32_t duration, int mixdown)
{
#ifndef DISABLE_SDL
static SDL_AudioSpec desired;
Editing *ed;
int have_sound = 0;
ed= G.scene->ed;
audio_scene = G.scene;
ed= audio_scene->ed;
if(ed) {
have_sound =
audiostream_play_seq(ed->seqbasep->first, startframe);
@ -525,7 +614,7 @@ void audiostream_play(uint32_t startframe, uint32_t duration, int mixdown)
}
if (U.mixbufsize && !audio_initialised && !mixdown) {
desired.freq=G.scene->audio.mixrate;
desired.freq=audio_scene->audio.mixrate;
desired.format=AUDIO_S16SYS;
desired.channels=2;
desired.samples=U.mixbufsize;
@ -538,7 +627,7 @@ void audiostream_play(uint32_t startframe, uint32_t duration, int mixdown)
audio_startframe = startframe;
audio_pos = ( ((int)( FRA2TIME(startframe)
*(G.scene->audio.mixrate)*4 )) & (~3) );
*(audio_scene->audio.mixrate)*4 )) & (~3) );
audio_starttime = PIL_check_seconds_timer();
/* if audio already is playing, just reseek, otherwise
@ -553,12 +642,12 @@ void audiostream_play(uint32_t startframe, uint32_t duration, int mixdown)
#endif
}
void audiostream_start(uint32_t frame)
void audiostream_start(int frame)
{
audiostream_play(frame, 0, 0);
}
void audiostream_scrub(uint32_t frame)
void audiostream_scrub(int frame)
{
if (U.mixbufsize) audiostream_play(frame, 4096/U.mixbufsize, 0);
}
@ -568,6 +657,7 @@ void audiostream_stop(void)
#ifndef DISABLE_SDL
SDL_PauseAudio(1);
audio_playing=0;
audio_scene=0;
#endif
}
@ -575,9 +665,9 @@ int audiostream_pos(void)
{
int pos;
if (U.mixbufsize) {
if (U.mixbufsize && audio_scene) {
pos = (int) (((double)(audio_pos-U.mixbufsize)
/ ( G.scene->audio.mixrate*4 ))
/ ( audio_scene->audio.mixrate*4 ))
* FPS );
} else { /* fallback to seconds_timer when no audio available */
pos = (int) ((PIL_check_seconds_timer() - audio_starttime)

@ -1884,7 +1884,10 @@ static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra,
if (!sce_valid) {
se->ok = STRIPELEM_FAILED;
} else if (se->ibuf==NULL && sce_valid) {
waitcursor(1);
/* no need to display a waitcursor on sequencer
scene strips */
if (!(sce->r.scemode & R_DOSEQ))
waitcursor(1);
/* Hack! This function can be called from do_render_seq(), in that case
the seq->scene can already have a Render initialized with same name,
@ -1935,7 +1938,9 @@ static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra,
/* restore */
G.scene->r.scemode |= doseq;
if((G.f & G_PLAYANIM)==0) /* bad, is set on do_render_seq */
if((G.f & G_PLAYANIM)==0 /* bad, is set on do_render_seq */
&& !(sce->r.scemode & R_DOSEQ))
waitcursor(0);
CFRA = oldcfra;
set_last_seq(oldseq);