diff options
25 files changed, 956 insertions, 123 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 3f274aafb90..5aecd18b231 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2244,6 +2244,13 @@ static void lib_link_scene(FileData *fd, Main *main) WHILE_SEQ(ed->seqbasep) { if(seq->ipo) seq->ipo= newlibadr_us(fd, sce->id.lib, seq->ipo); if(seq->scene) seq->scene= newlibadr(fd, sce->id.lib, seq->scene); + if(seq->sound) { + seq->sound= newlibadr(fd, sce->id.lib, seq->sound); + if (seq->sound) { + seq->sound->id.us++; + seq->sound->flags |= SOUND_FLAGS_SEQUENCE; + } + } seq->anim= 0; } END_SEQ @@ -2350,6 +2357,24 @@ static void direct_link_scene(FileData *fd, Scene *sce) } } } + else if(seq->type==SEQ_SOUND) { + /* only first stripelem is in file */ + se= newdataadr(fd, seq->strip->stripdata); + + if(se) { + seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + *seq->strip->stripdata= *se; + MEM_freeN(se); + + se= seq->strip->stripdata; + + for(a=0; a<seq->strip->len; a++, se++) { + se->ok= 2; /* why? */ + se->ibuf= 0; + se->nr= a + 1; + } + } + } else if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); @@ -2576,11 +2601,11 @@ static void lib_link_sound(FileData *fd, Main *main) if(sound->id.flag & LIB_NEEDLINK) { sound->id.flag -= LIB_NEEDLINK; sound->ipo= newlibadr_us(fd, sound->id.lib, sound->ipo); + sound->stream = 0; } sound= sound->id.next; } } - /* ***************** READ GROUP *************** */ static void direct_link_group(FileData *fd, Group *group) @@ -3669,6 +3694,14 @@ static void do_versions(Main *main) } } } + if(main->versionfile <= 227) { + Scene *sce; + + for (sce= main->scene.first; sce; sce= sce->id.next) { + sce->audio.mixrate = 44100; + sce->audio.flag |= (AUDIO_SYNC + AUDIO_SCRUB); + } + } /* don't forget to set version number in blender.c! */ } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 640e5333023..9845899c7d9 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1147,7 +1147,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) if(seq->type==SEQ_IMAGE) writestruct(wd, DATA, "StripElem", strip->len, strip->stripdata); - else if(seq->type==SEQ_MOVIE) + else if(seq->type==SEQ_MOVIE || seq->type==SEQ_SOUND) writestruct(wd, DATA, "StripElem", 1, strip->stripdata); strip->done= 1; diff --git a/source/blender/include/BSE_seqaudio.h b/source/blender/include/BSE_seqaudio.h new file mode 100644 index 00000000000..f395ac4b90e --- /dev/null +++ b/source/blender/include/BSE_seqaudio.h @@ -0,0 +1,52 @@ +/** + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2003 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ + +#ifndef BSE_SEQAUDIO_H +#define BSE_SEQAUDIO_H + +#include "SDL.h" +/* muha, we don't init (no SDL_main)! */ +#ifdef main +# undef main +#endif + +#include "DNA_sound_types.h" + +void audio_mixdown(); +void audio_makestream(bSound *sound); +void audiostream_play(Uint32 startframe, Uint32 duration, int mixdown); +void audiostream_start(Uint32 frame); +void audiostream_scrub(Uint32 frame); +void audiostream_stop(void); +int audiostream_pos(void); + +#endif + diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index c15b34def92..7ce8447da6a 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -92,6 +92,12 @@ typedef struct QuicktimeCodecData { char qtcodecname[128]; } QuicktimeCodecData; +typedef struct AudioData { + int mixrate; + float main; /* Main mix in dB */ + short flag; + short pad[3]; +} AudioData; typedef struct RenderData { struct AviCodecData *avicodecdata; @@ -243,6 +249,7 @@ typedef struct Scene { /* migrate or replace? depends on some internal things... */ /* no, is on the right place (ton) */ struct RenderData r; + struct AudioData audio; ScriptLink scriptlink; } Scene; @@ -354,6 +361,11 @@ typedef struct Scene { #define F_SET 2 #define F_DUPLI 3 +/* audio->flag */ +#define AUDIO_MUTE 1 +#define AUDIO_SYNC 2 +#define AUDIO_SCRUB 4 + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index f3827f5e0b2..efc145da8f6 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -36,6 +36,9 @@ #include "DNA_listBase.h" +/* needed for sound support */ +#include "DNA_sound_types.h" + struct Ipo; struct Scene; @@ -111,9 +114,12 @@ typedef struct Sequence { /* meta */ ListBase seqbase; + struct bSound *sound; /* the linked "bSound" object */ + float level, pan; /* level in dB (0=full), pan -1..1 */ + int curpos; /* last sample position in audio_fill() */ + int pad; + } Sequence; - - # # typedef struct MetaStack { @@ -137,12 +143,14 @@ typedef struct Editing { #define SEQ_RIGHTSEL 4 #define SEQ_OVERLAP 8 #define SEQ_FILTERY 16 +#define SEQ_MUTE 32 /* seq->type WATCH IT: BIT 3!!! */ #define SEQ_IMAGE 0 #define SEQ_META 1 #define SEQ_SCENE 2 #define SEQ_MOVIE 3 +#define SEQ_SOUND 4 #define SEQ_EFFECT 8 #define SEQ_CROSS 8 diff --git a/source/blender/makesdna/DNA_sound_types.h b/source/blender/makesdna/DNA_sound_types.h index 41429a0217e..8f91cb81e47 100644 --- a/source/blender/makesdna/DNA_sound_types.h +++ b/source/blender/makesdna/DNA_sound_types.h @@ -73,6 +73,7 @@ typedef struct bSound { ID id; char name[160]; struct bSample *sample; + void *stream; struct PackedFile *packedfile; struct PackedFile *newpackedfile; void *snd_sound; @@ -101,12 +102,12 @@ typedef struct bSound { */ float distance; int flags; + int streamlen; // unsigned int loopstart; // unsigned int loopend; char channels; char highprio; - char pad[6]; - + char pad[10]; } bSound; typedef struct bSoundListener { @@ -169,7 +170,8 @@ enum SOUND_FLAGS_BITS { SOUND_FLAGS_FIXED_PANNING_BIT, SOUND_FLAGS_3D_BIT, SOUND_FLAGS_BIDIRECTIONAL_LOOP_BIT, - SOUND_FLAGS_PRIORITY_BIT + SOUND_FLAGS_PRIORITY_BIT, + SOUND_FLAGS_SEQUENCE_BIT }; #define SOUND_FLAGS_LOOP (1 << SOUND_FLAGS_LOOP_BIT) @@ -178,6 +180,7 @@ enum SOUND_FLAGS_BITS { #define SOUND_FLAGS_3D (1 << SOUND_FLAGS_3D_BIT) #define SOUND_FLAGS_BIDIRECTIONAL_LOOP (1 << SOUND_FLAGS_BIDIRECTIONAL_LOOP_BIT) #define SOUND_FLAGS_PRIORITY (1 << SOUND_FLAGS_PRIORITY_BIT) +#define SOUND_FLAGS_SEQUENCE (1 << SOUND_FLAGS_SEQUENCE_BIT) enum SAMPLE_FLAGS_BITS { SAMPLE_NEEDS_SAVE_BIT = 0 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 59fa9e07604..a3b2e857417 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -396,6 +396,7 @@ typedef struct SpaceImaSel { #define MOVIEFILE 32 #define PYSCRIPTFILE 64 #define FTFONTFILE 128 +#define SOUNDFILE 256 #define SCROLLH 16 /* height scrollbar */ #define SCROLLB 16 /* width scrollbar */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 2d2ba593513..5a329749708 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -53,6 +53,7 @@ typedef struct UserDef { int userpref; short console_buffer; //console vars here for tuhopuu compat, --phase short console_out; + int mixbufsize; int fontsize; short encoding; short transopts; diff --git a/source/blender/src/Makefile b/source/blender/src/Makefile index 35c29a8571e..6737d942eed 100644 --- a/source/blender/src/Makefile +++ b/source/blender/src/Makefile @@ -86,6 +86,7 @@ CPPFLAGS += -I$(NAN_BSP)/include CPPFLAGS += -I../readstreamglue CPPFLAGS += -I../include +CPPFLAGS += -I$(NAN_SDL)/include/SDL ifdef NAN_BUILDINFO CPPFLAGS += -DNAN_BUILDINFO diff --git a/source/blender/src/buttons.c b/source/blender/src/buttons.c index 2f3efded788..c6eef4b906f 100644 --- a/source/blender/src/buttons.c +++ b/source/blender/src/buttons.c @@ -128,6 +128,7 @@ #include "BSE_trans_types.h" #include "BSE_view.h" #include "BSE_buttons.h" +#include "BSE_seqaudio.h" #include "BIF_gl.h" #include "BIF_editarmature.h" @@ -542,7 +543,10 @@ enum B_SOUND_BUTTONS { B_SOUND_COPY_SOUND, B_SOUND_LOOPSTART, B_SOUND_LOOPEND, - B_SOUND_BIDIRECTIONAL + B_SOUND_BIDIRECTIONAL, + B_SOUND_RECALC, + B_SOUND_RATECHANGED, + B_SOUND_MIXDOWN }; /* *********************** */ @@ -4543,6 +4547,32 @@ void do_soundbuts(unsigned short event) } break; } + case B_SOUND_RECALC: + { + waitcursor(1); + sound = G.main->sound.first; + while (sound) + { + MEM_freeN(sound->stream); + sound->stream = 0; + audio_makestream(sound); + sound = (bSound *) sound->id.next; + } + waitcursor(0); + allqueue(REDRAWSEQ, 0); + break; + } + case B_SOUND_RATECHANGED: + { + allqueue(REDRAWBUTSSOUND, 0); + allqueue(REDRAWSEQ, 0); + break; + } + case B_SOUND_MIXDOWN: + { + audio_mixdown(); + break; + } case B_SOUND_LOOPSTART: { #ifdef SOUND_UNDER_DEVELOPMENT @@ -4590,23 +4620,24 @@ void soundbuts(void) int mixrate; sound = G.buts->lockpoin; + if ((sound) && (sound->flags & SOUND_FLAGS_SEQUENCE)) sound = 0; yco = 195; + xco = xcostart; + sprintf(str, "buttonswin %d", curarea->win); + block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win); + if (sound) { sound_initialize_sample(sound); sample = sound->sample; - xco = xcostart; - sprintf(str, "buttonswin %d", curarea->win); - block= uiNewBlock(&curarea->uiblocks, str, UI_EMBOSSX, UI_HELV, curarea->win); - uiSetButLock(sound->id.lib!=0, "Can't edit library data"); /* sound settings ------------------------------------------------------------------ */ - uiDefBut(block, LABEL, 0, "Sound settings:",xco,yco,195,20, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Game sounds",xco,yco,195,20, 0, 0, 0, 0, 0, ""); yco -= 30; uiBlockSetCol(block, BUTGREEN); @@ -4627,7 +4658,7 @@ void soundbuts(void) uiDefBut(block, LABEL, 0, "Sample: ",xco,yco,195,20, 0, 0, 0, 0, 0, ""); xco +=55; - sprintf(sampleinfo, "%s, %d bit, %d Hz, %d samples", ch, sound->sample->bits, sound->sample->rate, sound->sample->len); + sprintf(sampleinfo, "%s, %d bit, %d Hz, %d samples", ch, sound->sample->bits, sound->sample->rate, (sound->sample->len/(sound->sample->bits/8)/sound->sample->channels)); uiDefBut(block, LABEL, 0, sampleinfo,xco,yco,295,20, 0, 0, 0, 0, 0, ""); } else @@ -4691,7 +4722,7 @@ void soundbuts(void) xco = xcostart; yco -= 45; - uiDefBut(block, LABEL, 0, "Parameter settings:",xco,yco,195,20, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Game sound settings:",xco,yco,195,20, 0, 0, 0, 0, 0, ""); yco -= 30; uiBlockSetCol(block, BUTGREY); @@ -4776,19 +4807,19 @@ void soundbuts(void) yco = 195; uiBlockSetCol(block, BUTGREY); mixrate = sound_get_mixrate(); - sprintf(mixrateinfo, "Mixrate: %d Hz", mixrate); + sprintf(mixrateinfo, "Game Mixrate: %d Hz", mixrate); uiDefBut(block, LABEL, 0, mixrateinfo, xco,yco,295,20, 0, 0, 0, 0, 0, ""); yco -= 30; - uiDefBut(block, LABEL, 0, "Listener settings:",xco,yco,195,20, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Game listener settings:",xco,yco,195,20, 0, 0, 0, 0, 0, ""); yco -= 30; uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Volume: ", xco,yco,195,24,&G.listener->gain, 0.0, 1.0, 1.0, 0, "Sets the maximum volume for the overall sound"); yco -= 30; - uiDefBut(block, LABEL, 0, "Doppler effect settings:",xco,yco,195,20, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Game Doppler effect settings:",xco,yco,195,20, 0, 0, 0, 0, 0, ""); /* yco -= 30; uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Scale: ", @@ -4820,6 +4851,47 @@ void soundbuts(void) */ uiDrawBlock(block); } + /* audio sequence engine settings ------------------------------------------------------------------ */ + + draw_buttons_edge(curarea->win, 1000); + + xco = xcostart + 1010; + yco = 195; + + uiDefBut(block, LABEL, 0, "Audio sequencer settings", xco,yco,295,20, 0, 0, 0, 0, 0, ""); + + yco -= 25; + sprintf(mixrateinfo, "Mixing/Sync (latency: %d ms)", (int)( (((float)U.mixbufsize)/(float)G.scene->audio.mixrate)*1000.0 ) ); + uiDefBut(block, LABEL, 0, mixrateinfo, xco,yco,295,20, 0, 0, 0, 0, 0, ""); + + yco -= 25; + uiBlockSetCol(block, BUTGREY); + uiDefButI(block, ROW, B_SOUND_RATECHANGED, "44.1 kHz", xco,yco,75,20, &G.scene->audio.mixrate, 2.0, 44100.0, 0, 0, "Mix at 44.1 kHz"); + uiDefButI(block, ROW, B_SOUND_RATECHANGED, "48.0 kHz", xco+80,yco,75,20, &G.scene->audio.mixrate, 2.0, 48000.0, 0, 0, "Mix at 48 kHz"); + uiBlockSetCol(block, BUTSALMON); + uiDefBut(block, BUT, B_SOUND_RECALC, "Recalc", xco+160,yco,75,20, 0, 0, 0, 0, 0, "Recalculate samples"); + + yco -= 25; + uiBlockSetCol(block, BUTGREEN); + uiDefButS(block, TOG|BIT|1, B_SOUND_CHANGED, "Sync", xco,yco,115,20, &G.scene->audio.flag, 0, 0, 0, 0, "Use sample clock for animation sync"); + uiDefButS(block, TOG|BIT|2, B_SOUND_CHANGED, "Scrub", xco+120,yco,115,20, &G.scene->audio.flag, 0, 0, 0, 0, "Scrub when changing frames"); + + yco -= 25; + uiDefBut(block, LABEL, 0, "Main mix", xco,yco,295,20, 0, 0, 0, 0, 0, ""); + + yco -= 25; + uiBlockSetCol(block, BUTGREY); + uiDefButF(block, NUMSLI, B_SOUND_CHANGED, "Main (dB): ", + xco,yco,235,24,&G.scene->audio.main, -24.0, 6.0, 0, 0, "Set the audio master gain/attenuation in dB"); + + yco -= 25; + uiDefButS(block, TOG|BIT|0, 0, "Mute", xco,yco,235,24, &G.scene->audio.flag, 0, 0, 0, 0, "Mute audio from sequencer"); + + yco -= 35; + uiBlockSetCol(block, BUTSALMON); + uiDefBut(block, BUT, B_SOUND_MIXDOWN, "MIXDOWN", xco,yco,235,24, 0, 0, 0, 0, 0, "Create WAV file from sequenced audio"); + + uiDrawBlock(block); } /* ************************ LAMP *************************** */ diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c index aa863e4b992..bba768a894b 100644 --- a/source/blender/src/drawseq.c +++ b/source/blender/src/drawseq.c @@ -70,6 +70,7 @@ #include "BSE_view.h" #include "BSE_drawipo.h" #include "BSE_sequence.h" +#include "BSE_seqaudio.h" int no_rightbox=0, no_leftbox= 0; @@ -99,6 +100,7 @@ static char *give_seqname(Sequence *seq) } else if(seq->type==SEQ_SCENE) return "SCENE"; else if(seq->type==SEQ_MOVIE) return "MOVIE"; + else if(seq->type==SEQ_SOUND) return "AUDIO"; else if(seq->type<SEQ_EFFECT) return seq->strip->dir; else if(seq->type==SEQ_CROSS) return "CROSS"; else if(seq->type==SEQ_GAMCROSS) return "GAMMA CROSS"; @@ -115,7 +117,6 @@ static char *give_seqname(Sequence *seq) else return "EFFECT"; } - static void draw_cfra_seq(void) { glColor3ub(0x30, 0x90, 0x50); @@ -155,12 +156,13 @@ static unsigned int seq_color(Sequence *seq) return 0x5080B0; case SEQ_PLUGIN: return 0x906000; + case SEQ_SOUND: + if(seq->flag & SEQ_MUTE) return 0x707060; else return 0x787850; default: return 0x906060; } } - static void drawmeta_contents(Sequence *seqm, float x1, float y1, float x2, float y2) { Sequence *seq; @@ -184,6 +186,32 @@ static void drawmeta_contents(Sequence *seqm, float x1, float y1, float x2, floa END_SEQ } +void drawseqwave(Sequence *seq, float x1, float y1, float x2, float y2) +{ + float f, height, midy; + int offset, sofs, eofs; + signed short* s; + bSound *sound; + + audio_makestream(seq->sound); + if (seq->flag & SEQ_MUTE) glColor3ub(0x70, 0x80, 0x80); else glColor3ub(0x70, 0xc0, 0xc0); + sound = seq->sound; + sofs = ((int)( (((float)(seq->startdisp-seq->start))/(float)G.scene->r.frs_sec)*(float)G.scene->audio.mixrate*4.0 )) & (~3); + eofs = ((int)( (((float)(seq->enddisp-seq->start))/(float)G.scene->r.frs_sec)*(float)G.scene->audio.mixrate*4.0 )) & (~3); + + for (f=x1; f<=x2; f+=0.2) { + offset = (int) ((float)sofs + ((f-x1)/(x2-x1)) * (float)(eofs-sofs)) & (~3); + if (offset >= sound->streamlen) offset = sound->streamlen-1; + s = (signed short*)(((Uint8*)sound->stream) + offset); + midy = (y1+y2)/2; + height = ( ( ((float)s[0]/32768 + (float)s[1]/32768)/2 ) * (y2-y1) )/2; + glBegin(GL_LINES); + glVertex2f(f, midy-height); + glVertex2f(f, midy+height); + glEnd(); + } +} + void drawseq(Sequence *seq) { float v1[2], v2[2], x1, x2, y1, y2; @@ -217,6 +245,7 @@ void drawseq(Sequence *seq) cpack(body); glRectf(x1, y1, x2, y2); + if (seq->type == SEQ_SOUND) drawseqwave(seq, x1, y1, x2, y2); EmbossBoxf(x1, y1, x2, y2, seq->flag & 1, dark, light); v1[1]= y1; @@ -288,7 +317,13 @@ void drawseq(Sequence *seq) sprintf(str, "%d %s: %d-%d", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine); } else if(seq->name[2]) sprintf(str, "%s", seq->name+2); - else sprintf(str, "%d %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name); + else { + if (seq->type == SEQ_SOUND) { + sprintf(str, "%d %s", seq->len, seq->strip->stripdata->name); + } else { + sprintf(str, "%d %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name); + } + } strp= str; @@ -309,17 +344,15 @@ void drawseq(Sequence *seq) } if(seq->type < SEQ_EFFECT) { - /* decoration: triangles */ x1= seq->startdisp; x2= seq->enddisp; - + body+= 0x101010; dark= 0x202020; light= 0xB0B0B0; /* left triangle */ - if(seq->flag & SEQ_LEFTSEL) { cpack(body+0x20); if(G.moving) { @@ -346,16 +379,17 @@ void drawseq(Sequence *seq) cpack(dark); glVertex2fv(v1); glEnd(); + } - if(G.moving || (seq->flag & SEQ_LEFTSEL)) { - cpack(0xFFFFFF); - glRasterPos3f(x1, y1+0.2, 0.0); - sprintf(str, "%d", seq->startdisp); - BMF_DrawString(G.font, str); - } + if(G.moving || (seq->flag & SEQ_LEFTSEL)) { + cpack(0xFFFFFF); + glRasterPos3f(x1, y1+0.2, 0.0); + sprintf(str, "%d", seq->startdisp); + BMF_DrawString(G.font, str); + } /* right triangle */ - + if(seq->type < SEQ_EFFECT) { dark= 0x202020; light= 0xB0B0B0; @@ -383,15 +417,13 @@ void drawseq(Sequence *seq) cpack(light); glVertex2fv(v2); glEnd(); + } - if(G.moving || (seq->flag & SEQ_RIGHTSEL)) { - cpack(0xFFFFFF); - glRasterPos3f(x2-seq->handsize/2, y1+0.2, 0.0); - sprintf(str, "%d", seq->enddisp-1); - BMF_DrawString(G.font, str); - } - - + if(G.moving || (seq->flag & SEQ_RIGHTSEL)) { + cpack(0xFFFFFF); + glRasterPos3f(x2-seq->handsize/2, y1+0.2, 0.0); + sprintf(str, "%d", seq->enddisp-1); + BMF_DrawString(G.font, str); } } @@ -530,6 +562,19 @@ static void draw_extra_seqinfo(void) glRasterPos3f(xco, 0.3, 0.0); BMF_DrawString(G.font, str); } + else if(last_seq->type==SEQ_SOUND) { + + sta= last_seq->startofs; + end= last_seq->len-1-last_seq->endofs; + + sprintf(str, "%s %s%s First: %d at %d Last: %d at %d Cur: %d Gain: %.2f dB Pan: %.2f", + last_seq->name+2, last_seq->strip->dir, last_seq->strip->stripdata->name, + sta, last_seq->startdisp, end, last_seq->enddisp-1, (G.scene->r.cfra)-last_seq->startdisp, + last_seq->level, last_seq->pan); + + glRasterPos3f(xco, 0.3, 0.0); + BMF_DrawString(G.font, str); + } } void drawseqspace(ScrArea *sa, void *spacedata) diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 01fba8eb27f..a963285bb27 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -97,6 +97,8 @@ #include "BSE_view.h" #include "BSE_drawview.h" #include "BSE_headerbuttons.h" +#include "BSE_seqaudio.h" + #include "RE_renderconverter.h" @@ -1192,6 +1194,8 @@ int update_time(void) static double ltime; double time; + if ((U.mixbufsize)&&(audiostream_pos() != CFRA)&&(G.scene->audio.flag & AUDIO_SYNC)) return 0; + time = PIL_check_seconds_timer(); tottime += (time - ltime); @@ -1566,12 +1570,17 @@ void inner_play_anim_loop(int init, int mode) tottime -= swaptime; while (update_time()) PIL_sleep_ms(1); - if(CFRA==EFRA) { + if(CFRA>=EFRA) { if (tottime > 0.0) tottime = 0.0; CFRA= SFRA; + audiostream_stop(); + audiostream_start( CFRA ); } - else CFRA++; - + else + { + if (U.mixbufsize && (G.scene->audio.flag & AUDIO_SYNC)) CFRA = audiostream_pos(); + else CFRA++; + }; } int play_anim(int mode) @@ -1594,6 +1603,8 @@ int play_anim(int mode) cfraont= CFRA; oldsa= curarea; + + audiostream_start( CFRA ); inner_play_anim_loop(1, mode); /* 1==init */ @@ -1649,6 +1660,7 @@ int play_anim(int mode) do_all_actions(); do_all_ikas(); + audiostream_stop(); if(oldsa!=curarea) areawinset(oldsa->win); @@ -1668,7 +1680,7 @@ int play_anim(int mode) allqueue(REDRAWNLA, 0); allqueue (REDRAWACTION, 0); /* for the time being */ - update_for_newframe(); + update_for_newframe_muted(); #ifdef NAN_LINEAR_PHYSICS end_anim_sumo(); #endif diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index f8b34269eac..b0cf75ff7da 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -1915,12 +1915,12 @@ static Ipo *get_ipo(ID *from, short type, int make) else if( type==ID_SEQ) { seq= (Sequence *)from; - if(seq->type & SEQ_EFFECT) { + if((seq->type & SEQ_EFFECT)||(seq->type == SEQ_SOUND)) { ipo= seq->ipo; if(make && ipo==0) ipo= seq->ipo= add_ipo("SeqIpo", ID_SEQ); } else return 0; - } + } else if( type==ID_CU) { cu= (Curve *)from; if(cu->id.lib) return 0; diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c index 3f66bd5724d..781ddfe518d 100644 --- a/source/blender/src/editnla.c +++ b/source/blender/src/editnla.c @@ -140,7 +140,7 @@ void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case DKEY: if (G.qual & LR_SHIFTKEY && mval[0]>=NLAWIDTH){ duplicate_nlachannel_keys(); - update_for_newframe(); + update_for_newframe_muted(); } break; case DELKEY: @@ -149,17 +149,17 @@ void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt) delete_nlachannel_keys (); else delete_nlachannels(); - update_for_newframe(); + update_for_newframe_muted(); break; case GKEY: if (mval[0]>=NLAWIDTH) transform_nlachannel_keys ('g'); - update_for_newframe(); + update_for_newframe_muted(); break; case SKEY: if (mval[0]>=NLAWIDTH) transform_nlachannel_keys ('s'); - update_for_newframe(); + update_for_newframe_muted(); break; case BKEY: borderselect_nla(); @@ -1566,7 +1566,7 @@ void clever_numbuts_nla(void){ strip->blendout = (strip->end-strip->start-strip->blendin); - update_for_newframe(); + update_for_newframe_muted(); allqueue (REDRAWNLA, 0); allqueue (REDRAWVIEW3D, 0); } diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index 54e63a1b42d..79db90154c6 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -63,6 +63,7 @@ #include "DNA_sequence_types.h" #include "DNA_view2d_types.h" #include "DNA_userdef_types.h" +#include "DNA_sound_types.h" #include "BKE_utildefines.h" #include "BKE_plugin_types.h" @@ -81,11 +82,13 @@ #include "BIF_writemovie.h" #include "BIF_editview.h" #include "BIF_scrarea.h" +#include "BIF_editsound.h" #include "BSE_edit.h" #include "BSE_sequence.h" #include "BSE_filesel.h" #include "BSE_drawipo.h" +#include "BSE_seqaudio.h" #include "BDR_editobject.h" @@ -95,6 +98,7 @@ Sequence *last_seq=0; char last_imagename[80]= "/"; +char last_sounddir[80]= ""; /* void transform_seq(int mode); already in BIF_editseq.h */ @@ -268,7 +272,7 @@ static void shuffle_seq(Sequence *test) ed= G.scene->ed; if(ed==0) return; - /* als er meerdere select zijn: alleen y shuffelen */ + /* is there more than 1 select: only shuffle y */ a=0; seq= ed->seqbasep->first; while(seq) { @@ -351,7 +355,7 @@ void swap_select_seq(void) END_SEQ WHILE_SEQ(ed->seqbasep) { - /* alles voor zekerheid altijd deselecteren */ + /* always deselect all to be sure */ seq->flag &= SEQ_DESEL; if(sel==0) seq->flag |= SELECT; } @@ -372,8 +376,15 @@ void mouse_select_seq(void) if(seq) { last_seq= seq; - if ELEM(seq->type, SEQ_IMAGE, SEQ_MOVIE) { - if(seq->strip) strcpy(last_imagename, seq->strip->dir); + if ((seq->type == SEQ_IMAGE) || (seq->type == SEQ_MOVIE)) { + if(seq->strip) { + strcpy(last_imagename, seq->strip->dir); + } + } else + if (seq->type == SEQ_SOUND) { + if(seq->strip) { + strcpy(last_sounddir, seq->strip->dir); + } } if(G.qual==0) { @@ -438,7 +449,7 @@ static Sequence *sfile_to_sequence(SpaceFile *sfile, int cfra, int machine, int StripElem *se; int totsel, a; - /* zijn er geselecteerde files? */ + /* are there selected files? */ totsel= 0; for(a=0; a<sfile->totfile; a++) { if(sfile->filelist[a].flags & ACTIVE) { @@ -449,13 +460,13 @@ static Sequence *sfile_to_sequence(SpaceFile *sfile, int cfra, int machine, int } if(last) { - /* of anders een aangegeven file? */ + /* if not, a file handed to us? */ if(totsel==0 && sfile->file[0]) totsel= 1; } if(totsel==0) return 0; - /* seq maken */ + /* make seq */ seq= alloc_sequence(cfra, machine); seq->len= totsel; @@ -466,7 +477,7 @@ static Sequence *sfile_to_sequence(SpaceFile *sfile, int cfra, int machine, int calc_sequence(seq); - /* strip en stripdata */ + /* strip and stripdata */ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); strip->len= totsel; strip->us= 1; @@ -482,13 +493,13 @@ static Sequence *sfile_to_sequence(SpaceFile *sfile, int cfra, int machine, int } } } - /* geen geselecteerde file: */ + /* no selected file: */ if(totsel==1 && se==strip->stripdata) { strcpy(se->name, sfile->file); se->ok= 1; } - /* laatste aktieve naam */ + /* last active name */ strcpy(last_imagename, seq->strip->dir); return seq; @@ -508,7 +519,7 @@ static void sfile_to_mv_sequence(SpaceFile *sfile, int cfra, int machine) strcpy(str, sfile->dir); strcat(str, sfile->file); - /* is er sprake van een movie */ + /* is it a movie? */ anim = openanim(str, IB_rect); if(anim==0) { error("Not a movie"); @@ -517,7 +528,7 @@ static void sfile_to_mv_sequence(SpaceFile *sfile, int cfra, int machine) totframe= IMB_anim_get_duration(anim); - /* seq maken */ + /* make seq */ seq= alloc_sequence(cfra, machine); seq->len= totframe; seq->type= SEQ_MOVIE; @@ -525,14 +536,14 @@ static void sfile_to_mv_sequence(SpaceFile *sfile, int cfra, int machine) calc_sequence(seq); - /* strip en stripdata */ + /* strip and stripdata */ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); strip->len= totframe; strip->us= 1; strcpy(strip->dir, sfile->dir); strip->stripdata= se= MEM_callocN(totframe*sizeof(StripElem), "stripelem"); - /* naam movie in eerste strip */ + /* name movie in first strip */ strcpy(se->name, sfile->file); for(a=1; a<=totframe; a++, se++) { @@ -540,10 +551,70 @@ static void sfile_to_mv_sequence(SpaceFile *sfile, int cfra, int machine) se->nr= a; } - /* laatste aktieve naam */ + /* last active name */ strcpy(last_imagename, seq->strip->dir); } +static Sequence *sfile_to_snd_sequence(SpaceFile *sfile, int cfra, int machine) +{ + Sequence *seq; + bSound *sound; + Strip *strip; + StripElem *se; + double totframe; + int a; + char str[256]; + + totframe= 0.0; + + strcpy(str, sfile->dir); + strcat(str, sfile->file); + + sound= sound_new_sound(str); + if (!sound || sound->sample->type == SAMPLE_INVALID) { + error("Unsupported audio format"); + return 0; + } + if (sound->sample->bits != 16) { + error("Only 16 bit audio supported"); + return 0; + } + sound->id.us=1; + sound->flags |= SOUND_FLAGS_SEQUENCE; + audio_makestream(sound); + + totframe= (int) ( ((float)(sound->streamlen-1)/( (float)G.scene->audio.mixrate*4.0 ))* (float)G.scene->r.frs_sec); + + /* make seq */ + seq= alloc_sequence(cfra, machine); + seq->len= totframe; + seq->type= SEQ_SOUND; + seq->sound = sound; + + calc_sequence(seq); + + /* strip and stripdata */ + seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); + strip->len= totframe; + strip->us= 1; + strcpy(strip->dir, sfile->dir); + strip->stripdata= se= MEM_callocN(totframe*sizeof(StripElem), "stripelem"); + + /* name sound in first strip */ + strcpy(se->name, sfile->file); + + for(a=1; a<=totframe; a++, se++) { + se->ok= 2; /* why? */ + se->ibuf= 0; + se->nr= a; + } + + /* last active name */ + strcpy(last_sounddir, seq->strip->dir); + + return seq; +} + static void add_image_strips(char *name) { SpaceFile *sfile; @@ -639,6 +710,74 @@ static void add_movie_strip(char *name) } +static void add_sound_strip(char *name) +{ + SpaceFile *sfile; + float x, y; + int cfra, machine; + short mval[2]; + + deselect_all_seq(); + + sfile= scrarea_find_space_of_type(curarea, SPACE_FILE); + if (sfile==0) return; + + /* where will it be */ + getmouseco_areawin(mval); + areamouseco_to_ipoco(G.v2d, mval, &x, &y); + cfra= (int)(x+0.5); + machine= (int)(y+0.5); + + waitcursor(1); + + sfile_to_snd_sequence(sfile, cfra, machine); + + waitcursor(0); + + transform_seq('g'); +} + +static void reload_sound_strip(char *name) +{ + Editing *ed; + Sequence *seq, *seqact; + SpaceFile *sfile; + + ed= G.scene->ed; + + if(last_seq==0 || last_seq->type!=SEQ_SOUND) return; + seqact= last_seq; /* last_seq changes in alloc_sequence */ + + /* search sfile */ + sfile= scrarea_find_space_of_type(curarea, SPACE_FILE); + if(sfile==0) return; + + waitcursor(1); + + seq = sfile_to_snd_sequence(sfile, seqact->start, seqact->machine); + printf("seq->type: %i\n", seq->type); + if(seq && seq!=seqact) { + /* i'm not sure about this one, seems to work without it -- sgefant */ + free_strip(seqact->strip); + + seqact->strip= seq->strip; + + seqact->len= seq->len; + calc_sequence(seqact); + + seq->strip= 0; + free_sequence(seq); + BLI_remlink(ed->seqbasep, seq); + + seq= ed->seqbasep->first; + + } + + waitcursor(0); + + allqueue(REDRAWSEQ, 0); +} + static void reload_image_strip(char *name) { Editing *ed; @@ -718,6 +857,7 @@ static int add_seq_effect(int type) seq= ed->seqbasep->first; while(seq) { if(seq->flag & SELECT) { + if (seq->type == SEQ_SOUND) { error("Cannot apply effects to audio sequence"); return 0; } if(seq != seq2) { if(seq1==0) seq1= seq; else if(seq3==0) seq3= seq; @@ -812,7 +952,7 @@ void add_sequence(int type) short nr, event, mval[2]; char *str; - event= pupmenu("Add sequence%t|Images%x1|Movie%x102|Scene%x101|Plugin%x10|Cross%x2|GammaCross%x3|Add%x4|Sub%x5|Mul%x6|AlphaOver%x7|AlphaUnder%x8|AlphaOverDrop%x9"); + event= pupmenu("Add sequence%t|Images%x1|Movie%x102|Audio%x103|Scene%x101|Plugin%x10|Cross%x2|GammaCross%x3|Add%x4|Sub%x5|Mul%x6|AlphaOver%x7|AlphaUnder%x8|AlphaOverDrop%x9"); if(event<1) return; @@ -891,7 +1031,11 @@ void add_sequence(int type) } break; - } + case 103: + if (!last_sounddir[0]) strcpy(last_sounddir, U.sounddir); + activate_fileselect(FILE_SPECIAL, "SELECT WAV", last_sounddir, add_sound_strip); + break; + } } void change_sequence(void) @@ -974,6 +1118,7 @@ static void recurs_del_seq(ListBase *lb) while(seq) { seqn= seq->next; if(seq->flag & SELECT) { + if(seq->type==SEQ_SOUND && seq->sound) seq->sound->id.us--; BLI_remlink(lb, seq); if(seq==last_seq) last_seq= 0; if(seq->type==SEQ_META) recurs_del_seq(&seq->seqbase); @@ -1100,6 +1245,30 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new) seq->flag &= SEQ_DESEL; seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); } + else if(seq->type == SEQ_SOUND) { + seqn= MEM_dupallocN(seq); + seq->newseq= seqn; + BLI_addtail(new, seqn); + + seqn->strip= MEM_dupallocN(seq->strip); + seqn->anim= 0; + seqn->sound->id.us++; + + if(seqn->len>0) { + seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + /* copy first elem */ + *seqn->strip->stripdata= *seq->strip->stripdata; + se= seqn->strip->stripdata; + a= seq->len; + while(a--) { + se->ok= 1; + se++; + } + } + + seq->flag &= SEQ_DESEL; + seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); + } else if(seq->type < SEQ_EFFECT) { seqn= MEM_dupallocN(seq); seq->newseq= seqn; @@ -1274,7 +1443,10 @@ void make_meta(void) tot= 0; seq= ed->seqbasep->first; while(seq) { - if(seq->flag & SELECT) tot++; + if(seq->flag & SELECT) { + tot++; + if (seq->type == SEQ_SOUND) { error("Cannot make Meta from audio"); return; } + } seq= seq->next; } if(tot < 2) return; @@ -1552,7 +1724,7 @@ void transform_seq(int mode) seq->startofs= ix; seq->startstill= 0; } - else { + else if (seq->type != SEQ_SOUND) { seq->startstill= -ix; seq->startofs= 0; } @@ -1575,7 +1747,7 @@ void transform_seq(int mode) seq->endofs= -ix; seq->endstill= 0; } - else { + else if (seq->type != SEQ_SOUND) { seq->endstill= ix; seq->endofs= 0; } @@ -1751,6 +1923,18 @@ void clever_numbuts_seq(void) allqueue(REDRAWSEQ, 0); } } + else if(last_seq->type==SEQ_SOUND) { + + add_numbut(0, TEX, "Name:", 0.0, 21.0, last_seq->name+2, 0); + add_numbut(1, NUM|FLO, "Gain (dB):", -96.0, 6.0, &last_seq->level, 0); + add_numbut(2, NUM|FLO, "Pan:", -1.0, 1.0, &last_seq->pan, 0); + add_numbut(3, TOG|SHO|BIT|5, "Mute", 0.0, 1.0, &last_seq->flag, 0); + + if( do_clever_numbuts("Audio", 4, REDRAW) ) { + se= last_seq->curelem; + allqueue(REDRAWSEQ, 0); + } + } else if(last_seq->type==SEQ_META) { add_numbut(0, TEX, "Name:", 0.0, 21.0, last_seq->name+2, 0); diff --git a/source/blender/src/editsound.c b/source/blender/src/editsound.c index 4099e665d7a..27a68a76153 100644 --- a/source/blender/src/editsound.c +++ b/source/blender/src/editsound.c @@ -175,7 +175,6 @@ void winqreadsoundspace(ScrArea *sa, void *spacedata, BWinEvent *evt) void sound_initialize_sounds(void) { -#if GAMEBLENDER == 1 bSound* sound; /* clear the soundscene */ @@ -189,7 +188,6 @@ void sound_initialize_sounds(void) sound_sample_is_null(sound); sound = (bSound *) sound->id.next; } -#endif } @@ -197,7 +195,6 @@ void sound_initialize_sounds(void) bSound* sound_make_copy(bSound* originalsound) { bSound* sound = NULL; -#if GAMEBLENDER == 1 char name[160]; int len; @@ -240,7 +237,6 @@ bSound* sound_make_copy(bSound* originalsound) sound->flags &= ~SOUND_FLAGS_3D; } -#endif return sound; } @@ -253,7 +249,6 @@ void sound_initialize_sample(bSound* sound) } - void sound_read_wav_data(bSound* sound, PackedFile* pf) { int i, temp; @@ -267,22 +262,22 @@ void sound_read_wav_data(bSound* sound, PackedFile* pf) /* prepare for the worst... */ sound->sample->type = SAMPLE_INVALID; - + rewindPackedFile(pf); - + /* check to see if it is a file in "RIFF WAVE fmt" format */ if (readPackedFile(pf, buffer, 16) != 16) { if (G.f & G_DEBUG) printf("File too short\n"); return; } - + if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8))) { readPackedFile(pf, &i, 4);// start of data if(G.order==B_ENDIAN) SWITCH_INT(i); - + /* read the sampleformat */ readPackedFile(pf, &shortbuf, 2); if(G.order==B_ENDIAN) @@ -294,9 +289,10 @@ void sound_read_wav_data(bSound* sound, PackedFile* pf) p_i[0]= p_i[1]; p_i[1]= s_i; } - + /* read the number of channels */ readPackedFile(pf, &shortbuf, 2); + if(G.order==B_ENDIAN) { /* was SWITCH_SHORT before */ @@ -306,7 +302,7 @@ void sound_read_wav_data(bSound* sound, PackedFile* pf) p_i[0]= p_i[1]; p_i[1]= s_i; } - + /* check the number of channels */ if(shortbuf != 1 && shortbuf != 2) { @@ -317,6 +313,8 @@ void sound_read_wav_data(bSound* sound, PackedFile* pf) /* read the samplerate */ readPackedFile(pf, &longbuf, 4); + + if(G.order==B_ENDIAN) SWITCH_INT(longbuf); rate = longbuf; @@ -324,6 +322,7 @@ void sound_read_wav_data(bSound* sound, PackedFile* pf) /* read the bitrate */ // Ton's way readPackedFile(pf, &temp, 4); + if(G.order==B_ENDIAN) SWITCH_INT(temp); @@ -331,6 +330,7 @@ void sound_read_wav_data(bSound* sound, PackedFile* pf) bits= 8*temp/(rate * channels); // Frank's way + readPackedFile(pf, &shortbuf, 2); readPackedFile(pf, &shortbuf, 2); if(G.order==B_ENDIAN) @@ -346,7 +346,6 @@ void sound_read_wav_data(bSound* sound, PackedFile* pf) seekPackedFile(pf, i-16, SEEK_CUR); readPackedFile(pf, buffer, 4); - /* check if we have a 'data' chunk */ while(memcmp(buffer, "data", 4)!=0) { @@ -357,7 +356,6 @@ void sound_read_wav_data(bSound* sound, PackedFile* pf) SWITCH_INT(i); seekPackedFile(pf, i, SEEK_CUR); - if (readPackedFile(pf, buffer, 4) != 4) break; } @@ -374,17 +372,18 @@ void sound_read_wav_data(bSound* sound, PackedFile* pf) if(G.order==B_ENDIAN) SWITCH_INT(longbuf); /* handle 8 and 16 bit samples differently */ - if (bits == 8) - data = (char *)MEM_mallocN(2 * longbuf, "sample data"); - else if (bits == 16) + /* intrr: removed, longbuf is length in bytes, not samples */ + if (bits == 16) data = (char *)MEM_mallocN(longbuf, "sample data"); + else + data = (char *)MEM_mallocN(longbuf*2, "sample data"); - len = longbuf; + len = longbuf /*/ 4.0*/; /* for some strange reason the sample length is off by a factor of 4... */ + /* intrr's comment: Funny eh, how one 16-bit stereo sample is 4 bytes? :-) */ if(data) { readPackedFile(pf, data, len); - /* data is only used to draw! */ if (bits == 8) { @@ -397,19 +396,9 @@ void sound_read_wav_data(bSound* sound, PackedFile* pf) { if(G.order==B_ENDIAN) { - temps= (short *)data; - for(i=0; i< len / 2; i++, temps++) - { - /* was SWITCH_SHORT before */ - char s_i, *p_i; - p_i= (char *)&(temps); - s_i= p_i[0]; - p_i[0]= p_i[1]; - p_i[1]= s_i; - } + swab(data, data, len); } } - /* fill the sound with the found data */ sample = sound->sample; sample->channels = channels; @@ -434,7 +423,6 @@ void sound_read_wav_data(bSound* sound, PackedFile* pf) int sound_get_filetype_from_header(bSound* sound, PackedFile* pf) { int filetype = SAMPLE_INVALID; -#if GAMEBLENDER == 1 int i; char buffer[25]; short shortbuf; @@ -509,7 +497,6 @@ int sound_get_filetype_from_header(bSound* sound, PackedFile* pf) if (G.f & G_DEBUG) printf("Unsupported sound format: %s\n", sound->name); } -#endif return filetype; } @@ -574,7 +561,6 @@ int check_filetype(bSound* sound, PackedFile* pf) int sound_load_sample(bSound* sound) { int result = FALSE; -#if GAMEBLENDER == 1 PackedFile* pf; int freePF = FALSE; int buffer = -1; @@ -652,8 +638,6 @@ int sound_load_sample(bSound* sound) result = TRUE; } -#endif - return result; } @@ -662,10 +646,10 @@ int sound_load_sample(bSound* sound) bSound* sound_new_sound(char* name) { bSound *sound = NULL; -#if GAMEBLENDER == 1 int len, file; char str[FILE_MAXDIR+FILE_MAXFILE]; - + + if (!G.scene->audio.mixrate) G.scene->audio.mixrate = 44100; /* convert the name to absolute path */ strcpy(str, name); BLI_convertstringcode(str, G.sce, G.scene->r.cfra); @@ -677,6 +661,7 @@ bSound* sound_new_sound(char* name) { close(file); + /* do some name magic */ len = strlen(name); while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\') @@ -707,7 +692,6 @@ bSound* sound_new_sound(char* name) } } -#endif return (sound); } @@ -716,7 +700,6 @@ bSound* sound_new_sound(char* name) int sound_set_sample(bSound *sound, bSample *sample) { int result = TRUE; -#if GAMEBLENDER == 1 /* decrease the usernumber for this sample */ if (sound->sample) sound->sample->id.us--; @@ -753,8 +736,6 @@ int sound_set_sample(bSound *sound, bSample *sample) } } -#endif - return result; } @@ -999,7 +980,6 @@ static void sound_init_listener(void) void sound_init_audio(void) { -#if GAMEBLENDER == 1 int noaudio; SYS_SystemHandle hSystem = NULL; ghAudioDeviceInterface = NULL; @@ -1007,14 +987,13 @@ void sound_init_audio(void) hSystem = SYS_GetSystem(); noaudio = SYS_GetCommandLineInt(hSystem,"noaudio",0); - if (noaudio) + if (1)/*(noaudio) intrr: disable game engine audio (openal) */ SND_SetDeviceType(snd_e_dummydevice); ghAudioDeviceInterface = SND_GetAudioDevice(); ghSoundScene = SND_CreateScene(ghAudioDeviceInterface); sound_init_listener(); -#endif } @@ -1035,9 +1014,7 @@ static void sound_exit_listener(void) void sound_exit_audio(void) { -#if GAMEBLENDER == 1 SND_DeleteScene(ghSoundScene); SND_ReleaseDevice(); sound_exit_listener(); -#endif } diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index 6d9c4904691..9c4d54ba494 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -595,6 +595,9 @@ void test_flags_file(SpaceFile *sfile) || BLI_testextensie(file->relname, ".mv")) { file->flags |= MOVIEFILE; } + else if(BLI_testextensie(file->relname, ".wav")) { + file->flags |= SOUNDFILE; + } } } } @@ -943,6 +946,10 @@ static void printregel(SpaceFile *sfile, struct direntry *files, int x, int y) cpack(0x4477dd); glRects(x-14, y, x-8, y+7); } + else if(files->flags & SOUNDFILE) { + cpack(0xa0a000); + glRects(x-14, y, x-8, y+7); + } else if(files->flags & FTFONTFILE) { cpack(0xff2371); glRects(x-14, y, x-8, y+7); diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c index 74eacc4ad37..8e7f78962ab 100644 --- a/source/blender/src/headerbuttons.c +++ b/source/blender/src/headerbuttons.c @@ -497,7 +497,7 @@ static int std_libbuttons(uiBlock *block, int xco, int pin, short *pinpoin, int return xco; } -void update_for_newframe(void) +void do_update_for_newframe(int mute) { allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWACTION,0); @@ -518,6 +518,18 @@ void update_for_newframe(void) do_all_ikas(); test_all_displists(); + + if ( (CFRA>1) && (!mute) && (G.scene->audio.flag & AUDIO_SCRUB)) audiostream_scrub( CFRA ); +} + +void update_for_newframe(void) +{ + do_update_for_newframe(0); +} + +void update_for_newframe_muted(void) +{ + do_update_for_newframe(1); } static void show_splash(void) @@ -1057,7 +1069,7 @@ void do_global_buttons(unsigned short event) } else if(ipo->blocktype==ID_SEQ) { seq= (Sequence *)from; - if(seq->type & SEQ_EFFECT) { + if((seq->type & SEQ_EFFECT)||(seq->type == SEQ_SOUND)) { id_us_plus(idtest); seq->ipo= ipo; } diff --git a/source/blender/src/renderwin.c b/source/blender/src/renderwin.c index 0a502b835d9..a9b3604a199 100644 --- a/source/blender/src/renderwin.c +++ b/source/blender/src/renderwin.c @@ -801,7 +801,7 @@ static void do_render(View3D *ogl_render_view3d, int anim, int force_dispwin) RE_initrender(ogl_render_view3d); } - if(anim) update_for_newframe(); // only when anim, causes redraw event which frustrates dispview + if(anim) update_for_newframe_muted(); // only when anim, causes redraw event which frustrates dispview R.flag= 0; if (render_win) window_set_cursor(render_win->win, CURSOR_STD); diff --git a/source/blender/src/seqaudio.c b/source/blender/src/seqaudio.c new file mode 100644 index 00000000000..fa43d3a6c39 --- /dev/null +++ b/source/blender/src/seqaudio.c @@ -0,0 +1,392 @@ +/** + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): intrr + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <math.h> +#include <stdlib.h> +#include <string.h> + +#ifndef WIN32 +#include <unistd.h> +#else +#include <io.h> +#include "BLI_winstuff.h" +#endif + +#include <fcntl.h> +#include <stdio.h> + +#include "MEM_guardedalloc.h" + +#include "PIL_time.h" + +#include "BMF_Api.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_editVert.h" + +#include "DNA_screen_types.h" +#include "DNA_sound_types.h" +#include "DNA_userdef_types.h" +#include "DNA_sequence_types.h" +#include "DNA_scene_types.h" +#include "DNA_ipo_types.h" + +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_blender.h" +#include "BKE_main.h" +#include "BKE_ipo.h" + +#include "BIF_gl.h" +#include "BIF_graphics.h" +#include "BIF_keyval.h" +#include "BIF_mainqueue.h" +#include "BIF_resources.h" +#include "BIF_screen.h" +#include "BIF_toolbox.h" +#include "BIF_mywindow.h" +#include "BIF_space.h" +#include "BIF_glutil.h" +#include "BIF_interface.h" + +#include "BSE_view.h" +#include "BSE_seqaudio.h" + +#include "mydevice.h" +#include "interface.h" +#include "blendef.h" + +void audio_fill(void *mixdown, Uint8 *sstream, int len); +/* ************ GLOBALS ************* */ + +int audio_pos; +SDL_AudioSpec wav_spec; +int audio_scrub=0; +int audio_playing=0; +///// +// + + +void makewavstring (char *string) +{ + char txt[64]; + + if (string==0) return; + + strcpy(string, G.scene->r.pic); + BLI_convertstringcode(string, G.sce, G.scene->r.cfra); + + RE_make_existing_file(string); + + if (strcasecmp(string + strlen(string) - 4, ".wav")) { + sprintf(txt, "%04d_%04d.wav", (G.scene->r.sfra) , (G.scene->r.efra) ); + strcat(string, txt); + } +} + +void audio_mixdown() +{ + int file, c, totlen, totframe, i, oldcfra, cfra2; + char *buf; + + buf = MEM_mallocN(65536, "audio_mixdown"); + makewavstring(buf); + + file = open(buf, O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666); + + if(file == -1) + { + error("Cannot open output file!"); + return; + } + + strcpy(buf, "RIFFlengWAVEfmt fmln01ccRATEbsecBP16dataDLEN"); + totframe = (EFRA - SFRA + 1); + totlen = (int) ( ((float)totframe / (float)G.scene->r.frs_sec) * (float)G.scene->audio.mixrate * 4.0); + printf("totlen %x\n", totlen); + memcpy(buf+4, &totlen, 4); + buf[16] = 0x10; buf[17] = buf[18] = buf[19] = 0; buf[20] = 1; buf[21] = 0; + buf[22] = 2; buf[23]= 0; + memcpy(buf+24, &G.scene->audio.mixrate, 4); + i = G.scene->audio.mixrate * 4; + memcpy(buf+28, &i, 4); + buf[32] = 4; buf[33] = 0; buf[34] = 16; buf[35] = 0; + i = totlen; + memcpy(buf+40, &i, 4); + + if (G.order == B_ENDIAN) { + /* swap the four ints to little endian */ + + /* length */ + SWITCH_INT(buf[4]); + + /* audio rate */ + SWITCH_INT(buf[24]); + + /* audio mixrate * 4 */ + SWITCH_INT(buf[28]); + + /* length */ + SWITCH_INT(buf[40]); + } + + c = write(file, buf, 44); + + oldcfra = CFRA; + audiostream_play(SFRA, 0, 1); + for (CFRA = SFRA, i = 0; (CFRA<=EFRA); + CFRA=(int) ( ((float)(audio_pos-64)/( G.scene->audio.mixrate*4 ))*(float)G.scene->r.frs_sec )) { + if (cfra2 != CFRA) { + cfra2 = CFRA; + set_timecursor(CFRA); + } + memset(buf+i, 0, 64); + audio_fill(buf+i, NULL, 64); + if (G.order == B_ENDIAN) { + swab(buf+i, buf+i, 64); + } + if (i == (65536-64)) { + i=0; + write(file, buf, 65536); + } else i+=64; + } + write(file, buf, i); + waitcursor(0); + CFRA = oldcfra; + close(file); + MEM_freeN(buf); + + return; +} + +void audio_levels(Uint8 *buf, int len, float db, float facf, float pan) +{ + int i; + float facl, facr, fac; + signed short *sample; + + 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; + facl /= fac; + facr /= fac; + + for (i=0; i<len; i+=4) { + sample = (signed short*)(buf+i); + sample[1] = (short) ((float)sample[0] * facl); + sample[0] = (short) ((float)sample[1] * facr); +/* if (G.order==B_ENDIAN) { + sample[0] = ((((sample[0]) & 0xff00) >> 8) | ((sample[0]) & 0x00ff) << 8); + sample[1] = ((((sample[1]) & 0xff00) >> 8) | ((sample[1]) & 0x00ff) << 8); + }*/ + } +} + +/* convert mono/stereo and sampling rate, alloc a buffer for + * sound->stream to contain the new sample, and set sound->streamlen + * accordingly. + */ +void audio_makestream(bSound *sound) +{ + signed short *source, *dest; + float ratio; + int i; + + if ( (!sound)||(sound->stream)||(!sound->sample)||(!G.scene) ) { + return; + } + ratio = (float)G.scene->audio.mixrate / (float)sound->sample->rate; + sound->streamlen = (int) ( (float)sound->sample->len * ratio * 2.0/((float)sound->sample->channels) ); + sound->stream = MEM_mallocN((int) ((float)sound->streamlen * 1.05), "stream"); + if (sound->sample->rate == G.scene->audio.mixrate) { + if (sound->sample->channels == 2) { + memcpy(sound->stream, sound->sample->data, sound->streamlen); + return; + } else { + for (source = (signed short*)(sound->sample->data), + dest = (signed short*)(sound->stream), + i=0; + i<sound->streamlen/4; + dest += 2, source++, i++) dest[0] = dest[1] = source[0]; + return; + } + } + if (sound->sample->channels == 1) { + for (dest=(signed short*)(sound->stream), i=0, source=(signed short*)(sound->sample->data); + i<(sound->streamlen/4); dest+=2, i++) + dest[0] = dest[1] = source[(int)((float)i/ratio)]; + } + else if (sound->sample->channels == 2) { + for (dest=(signed short*)(sound->stream), i=0, source=(signed short*)(sound->sample->data); + i<(sound->streamlen/2); dest+=2, i+=2) { + dest[1] = source[(int)((float)i/ratio)]; + dest[0] = source[(int)((float)i/ratio)+1]; + } + } +} + +void audio_fill(void *mixdown, Uint8 *sstream, int len) +{ + static Editing *ed; + static Sequence *seq; + static Uint8* cvtbuf; + static bSound* sound; + static float facf; + + + ed= G.scene->ed; + if((ed) && (!(G.scene->audio.flag & AUDIO_MUTE))) { + seq= ed->seqbasep->first; + while(seq) { + if ( (seq->type == SEQ_SOUND) && + (seq->sound) && + (!(seq->flag & SEQ_MUTE))) + { + sound = seq->sound; + audio_makestream(sound); + if ((seq->curpos<sound->streamlen -len) && (seq->curpos>=0) && + (seq->startdisp <= CFRA) && ((seq->enddisp) > CFRA)) + { + if(seq->ipo && seq->ipo->curve.first) facf = seq->facf0; else facf = 1.0; + cvtbuf = MEM_callocN(len, "cvtbuf"); + memcpy(cvtbuf, ((Uint8*)sound->stream)+(seq->curpos & (~3)), len); + audio_levels(cvtbuf, len, seq->level, facf, seq->pan); + if (!mixdown) { + SDL_MixAudio(sstream, cvtbuf, len, SDL_MIX_MAXVOLUME); + } else { + SDL_MixAudio((Uint8*)mixdown, cvtbuf, len, SDL_MIX_MAXVOLUME); + } + MEM_freeN(cvtbuf); + } + seq->curpos += len; + } + seq= seq->next; + } + } + + + audio_pos += len; + if (audio_scrub) { + audio_scrub--; + if (!audio_scrub) { + audiostream_stop(); + } + } +} + +int audio_init(SDL_AudioSpec *desired) +{ + SDL_AudioSpec *obtained, *hardware_spec; + + SDL_CloseAudio(); + + obtained = (SDL_AudioSpec*)MEM_mallocN(sizeof(SDL_AudioSpec), "SDL_AudioSpec"); + + desired->callback=audio_fill; + + if ( SDL_OpenAudio(desired, obtained) < 0 ){ + fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError()); + return 0; + } + hardware_spec=obtained; + + MEM_freeN(obtained); + + SDL_PauseAudio(1); + return 1; +} + +void audiostream_play(Uint32 startframe, Uint32 duration, int mixdown) +{ + static SDL_AudioSpec desired; + Editing *ed; + Sequence *seq; + bSound *sound; + + ed= G.scene->ed; + if(ed) { + seq= ed->seqbasep->first; + while(seq) { + if ((seq->type == SEQ_SOUND) && (seq->sound)) + { + sound = ((bSound*)seq->sound); + seq->curpos = (int)( (((float)((float)startframe-(float)seq->start)/(float)G.scene->r.frs_sec)*((float)G.scene->audio.mixrate)*4 )); + } + seq= seq->next; + } + } + + if (!(duration + mixdown)) { + desired.freq=G.scene->audio.mixrate; + desired.format=AUDIO_S16SYS; + desired.channels=2; + desired.samples=U.mixbufsize; + desired.userdata=0; + if (audio_init(&desired)==0) { + U.mixbufsize = 0; /* no audio */ + } + } + audio_pos = ( ((int)( (((float)startframe)/(float)G.scene->r.frs_sec)*(G.scene->audio.mixrate)*4 )) & (~3) ); + + audio_scrub = duration; + if (!mixdown) { + SDL_PauseAudio(0); + audio_playing++; + } +} + +void audiostream_start(Uint32 frame) +{ + audiostream_play(frame, 0, 0); +} + +void audiostream_scrub(Uint32 frame) +{ + if (U.mixbufsize) audiostream_play(frame, 4096/U.mixbufsize, 0); +} + +void audiostream_stop(void) +{ + SDL_PauseAudio(1); + audio_playing=0; +} + +int audiostream_pos(void) +{ + int pos; + + pos = (int) ( ((float)(audio_pos-U.mixbufsize)/( G.scene->audio.mixrate*4 ))*(float)G.scene->r.frs_sec ); + if (pos<1) pos=1; + return ( pos ); +} + diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index f30eff81195..76beb874345 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -1234,6 +1234,9 @@ void do_build_seqar_cfra(ListBase *seqbase, Sequence ***seqar, int cfra) /* set at zero because free_imbuf_seq... */ seq->curelem= 0; + + if ((seq->type == SEQ_SOUND) && (seq->ipo) + &&(seq->startdisp<=cfra+2) && (seq->enddisp>cfra)) do_seq_ipo(seq); if(seq->startdisp <=cfra && seq->enddisp > cfra) { @@ -1256,6 +1259,9 @@ void do_build_seqar_cfra(ListBase *seqbase, Sequence ***seqar, int cfra) se->ibuf= se->se1->ibuf; } } + else if(seq->type == SEQ_SOUND) { + se->ok= 2; + } else if(seq->type & SEQ_EFFECT) { /* test if image is too small: reload */ @@ -1371,7 +1377,7 @@ void do_build_seqar_cfra(ListBase *seqbase, Sequence ***seqar, int cfra) RE_initrender(NULL); if (!G.background) { - if(R.r.mode & R_FIELDS) update_for_newframe(); + if(R.r.mode & R_FIELDS) update_for_newframe_muted(); R.flag= 0; free_filesel_spec(G.scene->r.pic); @@ -1476,7 +1482,7 @@ ImBuf *give_ibuf_seq(int cfra) seq= seqar[seqnr]; se= seq->curelem; - if(se) { + if((seq->type != SEQ_SOUND) && (se)) { if(seq->type==SEQ_META) { /* bottom strip! */ @@ -1508,7 +1514,8 @@ ImBuf *give_ibuf_seq(int cfra) MEM_freeN(seqar); - if(seqfirst->curelem==0) return 0; + if(!seqfirst) return 0; + if(!seqfirst->curelem==0) return 0; return seqfirst->curelem->ibuf; } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 9c5f87076e0..6425303a97a 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1780,7 +1780,7 @@ void drawinfospace(ScrArea *sa, void *spacedata) #ifdef _WIN32 uiDefBut(block, LABEL,0,"Win Codecs:", - (xpos+edgespace+(2*midspace)+(2*medprefbut)),y3label,medprefbut,buth, + (xpos+edgespace+(1*midspace)+(1*medprefbut)),y3label,medprefbut,buth, 0, 0, 0, 0, 0, ""); uiDefButS(block, TOG|BIT|8, 0, "Enable all codecs", @@ -1828,6 +1828,14 @@ void drawinfospace(ScrArea *sa, void *spacedata) (xpos+edgespace+(5*medprefbut)+(5*midspace)),y1,medprefbut,buth, &(U.gameflags), 0, 0, 0, 0, "Toggles between vertex arrays on (less reliable) and off (more reliable)"); + uiDefBut(block, LABEL,0,"Audio:", + (xpos+edgespace+(2*midspace)+(2*medprefbut)),y3label,medprefbut,buth, + 0, 0, 0, 0, 0, ""); + + uiDefButI(block, ROW, 0, "Mixing buffer 256", (xpos+edgespace+(2*midspace)+(2*medprefbut)),y2,medprefbut,buth, &U.mixbufsize, 2.0, 256.0, 0, 0, "Set audio buffer size to 256 samples"); + uiDefButI(block, ROW, 0, "512", (xpos+edgespace+(2*midspace)+(2*medprefbut)),y1,61,buth, &U.mixbufsize, 2.0, 512.0, 0, 0, "Set audio buffer size to 512 samples"); + uiDefButI(block, ROW, 0, "1024", (xpos+edgespace+(2*midspace)+(2*medprefbut))+61+midspace,y1,61,buth, &U.mixbufsize, 2.0, 1024.0, 0, 0, "Set audio buffer size to 1024 samples"); + uiDefButI(block, ROW, 0, "2048", (xpos+edgespace+(2*midspace)+(2*medprefbut))+2*(61+midspace),y1,61,buth, &U.mixbufsize, 2.0, 2048.0, 0, 0, "Set audio buffer size to 2048 samples"); } else if(U.userpref == 5) { /* file paths */ @@ -2132,6 +2140,7 @@ void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt) CFRA= cfra; force_draw(); + update_for_newframe(); /* for audio scrubbing */ } } while(get_mbut()&L_MOUSE); diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 3bffcffb471..29f2b3d6a28 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -230,7 +230,9 @@ int BIF_read_homefile(void) U.transopts |= TR_ALL; } #endif - + if (G.main->versionfile <= 227) { + U.mixbufsize= 2048; + } space_set_commmandline_options(); reset_autosave(); diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index f0c33cb80e6..ecd1623576c 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -79,6 +79,8 @@ all debug:: else export NAN_FTGL ?= $(LCGDIR)/ftgl endif + export NAN_SDLLIBS ?= $(shell sdl-config --libs) + export NAN_SDLCFLAGS ?= $(shell sdl-config --cflags) # Platform Dependent settings go below: diff --git a/source/nan_link.mk b/source/nan_link.mk index 67c4edf8f60..7db3eebf8a9 100644 --- a/source/nan_link.mk +++ b/source/nan_link.mk @@ -150,3 +150,4 @@ ifeq ($(OS),windows) endif endif +LLIBS += $(NAN_SDLLIBS) |