Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWouter van Heyst <larstiq-bforge@larstiq.dyndns.org>2003-07-14 00:16:56 +0400
committerWouter van Heyst <larstiq-bforge@larstiq.dyndns.org>2003-07-14 00:16:56 +0400
commit4f273867403672b3970ff8879afe8459827f172a (patch)
tree75476eed3e2e70481dcc38a2f10c51805b8ab305 /source/blender/src/seqaudio.c
parent9cb79c6534ae4a1c51571d59fe93d41706cd2dc3 (diff)
Commit message and the brunt of the code courtesy of intrr, apologies for the
size of this; Finally, the Sequencer audio support and global audio/animation sync stuff! (See http://intrr.org/blender/audiosequencer.html) Stuff that has been done: ./source/blender/blenloader/intern/writefile.c ./source/blender/blenloader/intern/readfile.c Added code to make it handle sounds used by audio strips, and to convert Scene data from older (<2.28) versions to init Scene global audio settings (Scene->audio) to defaults. ./source/blender/include/BSE_seqaudio.h ./source/blender/src/seqaudio.c The main audio routines that start/stop/scrub the audio stream at a certain frame position, provide the frame reference for the current stream position, mix the audio, convert the audio, mixdown the audio into a file. ./source/blender/makesdna/DNA_sound_types.h Introduced new variables in the bSound struct to accomodate the sample data after converted to the scene's global mixing format (stream, streamlen). Also added a new flag SOUND_FLAGS_SEQUENCE that gets set if the Sound belongs to a sequence strip. ./source/blender/makesdna/DNA_scene_types.h Added AudioData struct, which holds scene-global audio settings. ./source/blender/makesdna/DNA_sequence_types.h Added support for audio strips. Some variables to hold Panning/Attenuation information, position information, reference to the sample, and some flags. ./source/blender/makesdna/DNA_userdef_types.h ./source/blender/src/usiblender.c Added a "Mixing buffer size" userpref. Made the versions stuff initialize it to a default for versions <2.28. ./source/blender/makesdna/DNA_space_types.h ./source/blender/src/filesel.c Added a Cyan dot to .WAV files. Any other suggestions on a better color? :) ./source/blender/src/editsound.c Changes (fixes) to the WAV file loader, re-enabled some gameengine code that is needed for dealing with bSounds and bSamples. ./source/blender/src/editipo.c ./source/blender/src/drawseq.c ./source/blender/src/editnla.c ./source/blender/src/space.c ./source/blender/src/drawview.c ./source/blender/src/renderwin.c ./source/blender/src/headerbuttons.c - Created two different wrappers for update_for_newframe(), one which scrubs the audio, one which doesn't. - Replaced some of the occurences of update_for_newframe() with update_for_newframe_muted(), which doesn't scrub the audio. - In drawview.c: Changed the synchronization scheme to get the current audio position from the audio engine, and use that as a reference for setting CFRA. Implements a/v sync and framedrop. - In editipo.c: Changed handling of Fac IPOs to be usable for audio strips as volume envelopes. - In space.c: Added the mixing buffer size Userpref, enabled audio scrubbing (update_for_newframe()) for moving the sequence editor framebar. ./source/blender/src/editseq.c Added support for audio strips and a default directory for WAV files which gets saved from the last Shift-A operation. ./source/blender/src/buttons.c Added Scene-global audio sequencer settings in Sound buttons. ./source/blender/src/sequence.c Various stuff that deals with handling audio strips differently than usual strips.
Diffstat (limited to 'source/blender/src/seqaudio.c')
-rw-r--r--source/blender/src/seqaudio.c392
1 files changed, 392 insertions, 0 deletions
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 );
+}
+