2.5 Audio:
authorJoerg Mueller <nexyon@gmail.com>
Sun, 7 Feb 2010 23:41:17 +0000 (23:41 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Sun, 7 Feb 2010 23:41:17 +0000 (23:41 +0000)
- recode of the whole sequencer audio handling
- encode audio flag removed, instead you choose None as audio codec, added None for video codec too
- ffmpeg formats/codecs: enabled: theora, ogg, vorbis; added: matroska, flac (not working, who can fix?), mp3, wav
- sequencer wave drawing
- volume animation (now also working when mixing down to a file!)
- made sequencer strip position and length values unanimatable

37 files changed:
intern/audaspace/FX/AUD_LoopReader.cpp
intern/audaspace/FX/AUD_LoopReader.h
intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
intern/audaspace/intern/AUD_C-API.cpp
intern/audaspace/intern/AUD_C-API.h
intern/audaspace/intern/AUD_Mixer.cpp
intern/audaspace/intern/AUD_Mixer.h
intern/audaspace/intern/AUD_SequencerFactory.cpp [new file with mode: 0644]
intern/audaspace/intern/AUD_SequencerFactory.h [new file with mode: 0644]
intern/audaspace/intern/AUD_SequencerReader.cpp [new file with mode: 0644]
intern/audaspace/intern/AUD_SequencerReader.h [new file with mode: 0644]
intern/audaspace/intern/AUD_SoftwareDevice.cpp
intern/audaspace/intern/AUD_Space.h
release/scripts/ui/properties_render.py
source/blender/blenkernel/BKE_sequencer.h
source/blender/blenkernel/BKE_sound.h
source/blender/blenkernel/BKE_writeffmpeg.h
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/sound.c
source/blender/blenkernel/intern/writeffmpeg.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/animation/anim_ops.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/sound/sound_ops.c
source/blender/editors/space_graph/graph_ops.c
source/blender/editors/space_sequencer/sequencer_add.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/transform/transform_conversions.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesdna/DNA_sound_types.h
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_sequencer.c
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Ketsji/KX_SoundActuator.cpp

index 7d70fc2022170d1590678c4a706e1d6f5bec72a0..3bcd8c2f9d32e4484bc117b1569dd315dbeb0848 100644 (file)
@@ -31,6 +31,7 @@
 AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) :
                AUD_EffectReader(reader), m_loop(loop)
 {
+       m_samples = -1;
        m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
 }
 
@@ -51,6 +52,7 @@ bool AUD_LoopReader::notify(AUD_Message &message)
        if(message.type == AUD_MSG_LOOP)
        {
                m_loop = message.loopcount;
+               m_samples = message.time * m_reader->getSpecs().rate;
 
                m_reader->notify(message);
 
@@ -64,6 +66,13 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer)
        AUD_Specs specs = m_reader->getSpecs();
        int samplesize = AUD_SAMPLE_SIZE(specs);
 
+       if(m_samples >= 0)
+       {
+               if(length > m_samples)
+                       length = m_samples;
+               m_samples -= length;
+       }
+
        int len = length;
 
        m_reader->read(len, buffer);
index 621ee3493abe6fbf467975dd21072d85e7b59725..e61a49cb0db39c4c13c1a7c4c7dc259f9ae4e6b0 100644 (file)
@@ -46,6 +46,11 @@ private:
         */
        int m_loop;
 
+       /**
+        * The left samples.
+        */
+       int m_samples;
+
 public:
        /**
         * Creates a new loop reader.
index 0b3e86eda56fb7c4ad91bd0b9eec383626cd3b3c..9e153b9b34f124dc0ccc10443f797f5db7258fa5 100644 (file)
@@ -180,7 +180,7 @@ void AUD_OpenALDevice::updateStreams()
                                                                                         AUD_DEVICE_SAMPLE_SIZE(specs),
                                                                                         specs.rate);
 
-                                                               if(alGetError() != AL_NO_ERROR)
+                                                               if((err = alGetError()) != AL_NO_ERROR)
                                                                {
                                                                        sound->data_end = true;
                                                                        break;
@@ -839,13 +839,14 @@ bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position)
 
                        if(info != AL_PLAYING)
                        {
-                               if(info != AL_STOPPED)
+                               if(info == AL_PAUSED)
                                        alSourceStop(alhandle->source);
 
-                               alSourceUnqueueBuffers(alhandle->source,
-                                                                          AUD_OPENAL_CYCLE_BUFFERS,
-                                                                          alhandle->buffers);
-                               if(alGetError() == AL_NO_ERROR)
+                               alSourcei(alhandle->source, AL_BUFFER, 0);
+                               alhandle->current = 0;
+
+                               ALenum err;
+                               if((err = alGetError()) == AL_NO_ERROR)
                                {
                                        sample_t* buf;
                                        int length;
index b7d0183cb5e4a1e384d78064fcb5375fe4d313f1..b363c4576b38efb67aff69542c43e31fa1cbe4a9 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <cstdlib>
 #include <cstring>
+#include <cmath>
 
 #include "AUD_NULLDevice.h"
 #include "AUD_I3DDevice.h"
@@ -47,6 +48,7 @@
 #include "AUD_ReadDevice.h"
 #include "AUD_SourceCaps.h"
 #include "AUD_IReader.h"
+#include "AUD_SequencerFactory.h"
 
 #ifdef WITH_SDL
 #include "AUD_SDLDevice.h"
@@ -231,7 +233,7 @@ AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay)
        }
 }
 
-extern AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end)
+AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end)
 {
        assert(sound);
 
@@ -273,13 +275,14 @@ AUD_Sound* AUD_loopSound(AUD_Sound* sound)
        }
 }
 
-int AUD_stopLoop(AUD_Handle* handle)
+int AUD_setLoop(AUD_Handle* handle, int loops, float time)
 {
        if(handle)
        {
                AUD_Message message;
                message.type = AUD_MSG_LOOP;
-               message.loopcount = 0;
+               message.loopcount = loops;
+               message.time = time;
 
                try
                {
@@ -537,14 +540,16 @@ AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs)
        }
 }
 
-AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound)
+AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
 {
        assert(device);
        assert(sound);
 
        try
        {
-               return device->play(sound);
+               AUD_Handle* handle = device->play(sound);
+               device->seek(handle, seek);
+               return handle;
        }
        catch(AUD_Exception)
        {
@@ -663,3 +668,97 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high,
        *length = position;
        return result;
 }
+
+AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume)
+{
+       if(AUD_device)
+       {
+               return new AUD_SequencerFactory(AUD_device->getSpecs().specs, data, volume);
+       }
+       else
+       {
+               AUD_Specs specs;
+               specs.channels = AUD_CHANNELS_STEREO;
+               specs.rate = AUD_RATE_44100;
+               return new AUD_SequencerFactory(specs, data, volume);
+       }
+}
+
+void AUD_destroySequencer(AUD_Sound* sequencer)
+{
+       delete ((AUD_SequencerFactory*)sequencer);
+}
+
+AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound,
+                                                                float begin, float end, float skip, void* data)
+{
+       return ((AUD_SequencerFactory*)sequencer)->add((AUD_IFactory**) sound, begin, end, skip, data);
+}
+
+void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry)
+{
+       ((AUD_SequencerFactory*)sequencer)->remove(entry);
+}
+
+void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
+                                  float begin, float end, float skip)
+{
+       ((AUD_SequencerFactory*)sequencer)->move(entry, begin, end, skip);
+}
+
+void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, char mute)
+{
+       ((AUD_SequencerFactory*)sequencer)->mute(entry, mute);
+}
+
+int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
+{
+       AUD_IReader* reader = sound->createReader();
+       AUD_DeviceSpecs specs;
+       sample_t* buf;
+
+       specs.specs = reader->getSpecs();
+       specs.channels = AUD_CHANNELS_MONO;
+       specs.format = AUD_FORMAT_FLOAT32;
+
+       AUD_ChannelMapperFactory mapper(reader, specs);
+
+       if(!reader || reader->getType() != AUD_TYPE_BUFFER)
+               return -1;
+
+       reader = mapper.createReader();
+
+       if(!reader)
+               return -1;
+
+       int len = reader->getLength();
+       float samplejump = (float)len / (float)length;
+       float min, max;
+
+       for(int i = 0; i < length; i++)
+       {
+               len = floor(samplejump * (i+1)) - floor(samplejump * i);
+               reader->read(len, buf);
+
+               if(len < 1)
+               {
+                       length = i;
+                       break;
+               }
+
+               max = min = *buf;
+               for(int j = 1; j < len; j++)
+               {
+                       if(buf[j] < min)
+                               min = buf[j];
+                       if(buf[j] > max)
+                               max = buf[j];
+                       buffer[i * 2] = min;
+                       buffer[i * 2 + 1] = max;
+               }
+       }
+
+       delete reader; AUD_DELETE("reader")
+
+       return length;
+}
index c3439f89ade990a0b0eab5b6e7a7151be10e9828..ce1791886de5be548343d41aef55c3dd3c5cf90e 100644 (file)
@@ -50,6 +50,8 @@ typedef struct
        typedef void AUD_Sound;
        typedef void AUD_Handle;
        typedef void AUD_Device;
+       typedef void AUD_SequencerEntry;
+       typedef float (*AUD_volumeFunction)(void*, void*, float);
 #endif
 
 /**
@@ -143,11 +145,13 @@ extern AUD_Sound* AUD_pingpongSound(AUD_Sound* sound);
 extern AUD_Sound* AUD_loopSound(AUD_Sound* sound);
 
 /**
- * Stops a looping sound when the current playback finishes.
+ * Sets a remaining loop count of a looping sound that currently plays.
  * \param handle The playback handle.
+ * \param loops The count of remaining loops, -1 for infinity.
+ * \param time The time after which playback should stop, -1 for infinity.
  * \return Whether the handle is valid.
  */
-extern int AUD_stopLoop(AUD_Handle* handle);
+extern int AUD_setLoop(AUD_Handle* handle, int loops, float time);
 
 /**
  * Rectifies a sound.
@@ -211,6 +215,7 @@ extern int AUD_seek(AUD_Handle* handle, float seekTo);
 
 /**
  * Retrieves the playback position of a handle.
+ * \param handle The handle to the sound.
  * \return The current playback position in seconds or 0.0 if the handle is
  *         invalid.
  */
@@ -318,9 +323,10 @@ extern int AUD_setDeviceVolume(AUD_Device* device, float volume);
  * Plays back a sound file through a read device.
  * \param device The read device.
  * \param sound The handle of the sound file.
+ * \param seek The position where the sound should be seeked to.
  * \return A handle to the played back sound.
  */
-extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound);
+extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek);
 
 /**
  * Sets the volume of a played back sound of a read device.
@@ -360,6 +366,23 @@ extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
                                                                  float sthreshold, int samplerate,
                                                                  int* length);
 
+extern AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume);
+
+extern void AUD_destroySequencer(AUD_Sound* sequencer);
+
+extern AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound,
+                                                                               float begin, float end, float skip, void* data);
+
+extern void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry);
+
+extern void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
+                                                 float begin, float end, float skip);
+
+extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
+                                                 char mute);
+
+extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length);
+
 #ifdef __cplusplus
 }
 #endif
index bddc719b17959ada7452b32f5af246546e50ded9..299388b558bf6c1e377961358319271788848480 100644 (file)
@@ -68,6 +68,11 @@ AUD_IReader* AUD_Mixer::prepare(AUD_IReader* reader)
        return reader;
 }
 
+AUD_DeviceSpecs AUD_Mixer::getSpecs()
+{
+       return m_specs;
+}
+
 void AUD_Mixer::setSpecs(AUD_DeviceSpecs specs)
 {
        m_specs = specs;
@@ -115,10 +120,11 @@ void AUD_Mixer::setSpecs(AUD_DeviceSpecs specs)
        }
 }
 
-void AUD_Mixer::add(sample_t* buffer, int length, float volume)
+void AUD_Mixer::add(sample_t* buffer, int start, int length, float volume)
 {
        AUD_MixerBuffer buf;
        buf.buffer = buffer;
+       buf.start = start;
        buf.length = length;
        buf.volume = volume;
        m_buffers.push_back(buf);
@@ -145,11 +151,11 @@ void AUD_Mixer::superpose(data_t* buffer, int length, float volume)
                buf = m_buffers.front();
                m_buffers.pop_front();
 
-               end = buf.length*channels;
+               end = buf.length * channels;
                in = buf.buffer;
 
                for(int i = 0; i < end; i++)
-                       out[i] += in[i]*buf.volume * volume;
+                       out[i + buf.start * channels] += in[i] * buf.volume * volume;
        }
 
        m_convert(buffer, (data_t*) out, length * channels);
index 5097b9ec2a6e3a7b57a97627339d2b9fbb66d219..5dcdef45eba17cc6315a99fe1bee151e25f79fbc 100644 (file)
@@ -37,6 +37,7 @@ class AUD_IReader;
 struct AUD_MixerBuffer
 {
        sample_t* buffer;
+       int start;
        int length;
        float volume;
 };
@@ -98,6 +99,12 @@ public:
         */
        AUD_IReader* prepare(AUD_IReader* reader);
 
+       /**
+        * Returns the target specification for superposing.
+        * \return The target specification.
+        */
+       AUD_DeviceSpecs getSpecs();
+
        /**
         * Sets the target specification for superposing.
         * \param specs The target specification.
@@ -111,7 +118,7 @@ public:
         * \param length The length of the buffer in samples.
         * \param volume The mixing volume. Must be a value between 0.0 and 1.0.
         */
-       void add(sample_t* buffer, int length, float volume);
+       void add(sample_t* buffer, int start, int length, float volume);
 
        /**
         * Superposes all added buffers into an output buffer.
diff --git a/intern/audaspace/intern/AUD_SequencerFactory.cpp b/intern/audaspace/intern/AUD_SequencerFactory.cpp
new file mode 100644 (file)
index 0000000..bb5cf27
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_SequencerFactory.h"
+#include "AUD_SequencerReader.h"
+
+typedef std::list<AUD_SequencerReader*>::iterator AUD_ReaderIterator;
+
+AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, void* data, AUD_volumeFunction volume)
+{
+       m_specs = specs;
+       m_data = data;
+       m_volume = volume;
+}
+
+AUD_SequencerFactory::~AUD_SequencerFactory()
+{
+       AUD_SequencerReader* reader;
+       AUD_SequencerEntry* entry;
+
+       while(!m_readers.empty())
+       {
+               reader = m_readers.front();
+               m_readers.pop_front();
+               reader->destroy();
+       }
+
+       while(!m_entries.empty())
+       {
+               entry = m_entries.front();
+               m_entries.pop_front();
+               delete entry; AUD_DELETE("seqentry")
+       }
+}
+
+AUD_SequencerEntry* AUD_SequencerFactory::add(AUD_IFactory** sound, float begin, float end, float skip, void* data)
+{
+       AUD_SequencerEntry* entry = new AUD_SequencerEntry; AUD_NEW("seqentry")
+       entry->sound = sound;
+       entry->begin = begin;
+       entry->skip = skip;
+       entry->end = end;
+       entry->muted = false;
+       entry->data = data;
+
+       m_entries.push_front(entry);
+
+       for(AUD_ReaderIterator i = m_readers.begin(); i != m_readers.end(); i++)
+               (*i)->add(entry);
+
+       return entry;
+}
+
+void AUD_SequencerFactory::remove(AUD_SequencerEntry* entry)
+{
+       for(AUD_ReaderIterator i = m_readers.begin(); i != m_readers.end(); i++)
+               (*i)->remove(entry);
+
+       m_entries.remove(entry);
+
+       delete entry; AUD_DELETE("seqentry")
+}
+
+void AUD_SequencerFactory::move(AUD_SequencerEntry* entry, float begin, float end, float skip)
+{
+       entry->begin = begin;
+       entry->skip = skip;
+       entry->end = end;
+}
+
+void AUD_SequencerFactory::mute(AUD_SequencerEntry* entry, bool mute)
+{
+       entry->muted = mute;
+}
+
+AUD_IReader* AUD_SequencerFactory::createReader()
+{
+       AUD_SequencerReader* reader = new AUD_SequencerReader(this, m_entries, m_specs, m_data, m_volume); AUD_NEW("reader")
+       m_readers.push_front(reader);
+
+       return reader;
+}
+
+void AUD_SequencerFactory::removeReader(AUD_SequencerReader* reader)
+{
+       m_readers.remove(reader);
+}
diff --git a/intern/audaspace/intern/AUD_SequencerFactory.h b/intern/audaspace/intern/AUD_SequencerFactory.h
new file mode 100644 (file)
index 0000000..b564c88
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_SEQUENCERFACTORY
+#define AUD_SEQUENCERFACTORY
+
+#include "AUD_IFactory.h"
+
+#include <list>
+
+typedef float (*AUD_volumeFunction)(void*, void*, float);
+
+struct AUD_SequencerEntry
+{
+       AUD_IFactory** sound;
+       float begin;
+       float end;
+       float skip;
+       bool muted;
+       void* data;
+};
+
+class AUD_SequencerReader;
+
+/**
+ * This factory creates a resampling reader that does simple linear resampling.
+ */
+class AUD_SequencerFactory : public AUD_IFactory
+{
+private:
+       /**
+        * The target specification.
+        */
+       AUD_Specs m_specs;
+
+       std::list<AUD_SequencerEntry*> m_entries;
+       std::list<AUD_SequencerReader*> m_readers;
+       void* m_data;
+       AUD_volumeFunction m_volume;
+
+public:
+       AUD_SequencerFactory(AUD_Specs specs, void* data, AUD_volumeFunction volume);
+       ~AUD_SequencerFactory();
+
+       AUD_SequencerEntry* add(AUD_IFactory** sound, float begin, float end, float skip, void* data);
+       void remove(AUD_SequencerEntry* entry);
+       void move(AUD_SequencerEntry* entry, float begin, float end, float skip);
+       void mute(AUD_SequencerEntry* entry, bool mute);
+
+       virtual AUD_IReader* createReader();
+
+       void removeReader(AUD_SequencerReader* reader);
+};
+
+#endif //AUD_SEQUENCERFACTORY
diff --git a/intern/audaspace/intern/AUD_SequencerReader.cpp b/intern/audaspace/intern/AUD_SequencerReader.cpp
new file mode 100644 (file)
index 0000000..84c1476
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_SequencerReader.h"
+#include "AUD_Buffer.h"
+
+#include <math.h>
+
+typedef std::list<AUD_SequencerStrip*>::iterator AUD_StripIterator;
+typedef std::list<AUD_SequencerEntry*>::iterator AUD_EntryIterator;
+
+AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs, void* data, AUD_volumeFunction volume)
+{
+       AUD_DeviceSpecs dspecs;
+       dspecs.specs = specs;
+       dspecs.format = AUD_FORMAT_FLOAT32;
+
+       m_mixer.setSpecs(dspecs);
+       m_factory = factory;
+       m_data = data;
+       m_volume = volume;
+
+       AUD_SequencerStrip* strip;
+
+       for(AUD_EntryIterator i = entries.begin(); i != entries.end(); i++)
+       {
+               strip = new AUD_SequencerStrip;  AUD_NEW("seqstrip")
+               strip->entry = *i;
+               strip->old_sound = NULL;
+
+               if(strip->old_sound)
+                       strip->reader = m_mixer.prepare(strip->old_sound->createReader());
+               else
+                       strip->reader = NULL;
+
+               m_strips.push_front(strip);
+       }
+
+       m_position = 0;
+       m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+}
+
+AUD_SequencerReader::~AUD_SequencerReader()
+{
+       if(m_factory != NULL)
+               m_factory->removeReader(this);
+
+       AUD_SequencerStrip* strip;
+
+       while(!m_strips.empty())
+       {
+               strip = m_strips.front();
+               m_strips.pop_front();
+               if(strip->reader)
+               {
+                       delete strip->reader; AUD_DELETE("reader")
+               }
+               delete strip; AUD_DELETE("seqstrip")
+       }
+
+       delete m_buffer; AUD_DELETE("buffer")
+}
+
+void AUD_SequencerReader::destroy()
+{
+       m_factory = NULL;
+       AUD_SequencerStrip* strip;
+
+       while(!m_strips.empty())
+       {
+               strip = m_strips.front();
+               m_strips.pop_front();
+               delete strip; AUD_DELETE("seqstrip")
+       }
+}
+
+void AUD_SequencerReader::add(AUD_SequencerEntry* entry)
+{
+       AUD_SequencerStrip* strip = new AUD_SequencerStrip; AUD_NEW("seqstrip")
+       strip->entry = entry;
+       strip->old_sound = NULL;
+
+       if(strip->old_sound)
+               strip->reader = m_mixer.prepare(strip->old_sound->createReader());
+       else
+               strip->reader = NULL;
+
+       m_strips.push_front(strip);
+}
+
+void AUD_SequencerReader::remove(AUD_SequencerEntry* entry)
+{
+       AUD_SequencerStrip* strip;
+       for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
+       {
+               strip = *i;
+               if(strip->entry == entry)
+               {
+                       i++;
+                       if(strip->reader)
+                       {
+                               delete strip->reader; AUD_DELETE("reader")
+                       }
+                       m_strips.remove(strip);
+                       delete strip;
+                       return;
+               }
+       }
+}
+
+bool AUD_SequencerReader::isSeekable()
+{
+       return true;
+}
+
+void AUD_SequencerReader::seek(int position)
+{
+       m_position = position;
+}
+
+int AUD_SequencerReader::getLength()
+{
+       return -1;
+}
+
+int AUD_SequencerReader::getPosition()
+{
+       return m_position;
+}
+
+AUD_Specs AUD_SequencerReader::getSpecs()
+{
+       return m_mixer.getSpecs().specs;
+}
+
+AUD_ReaderType AUD_SequencerReader::getType()
+{
+       return AUD_TYPE_STREAM;
+}
+
+bool AUD_SequencerReader::notify(AUD_Message &message)
+{
+       bool result = false;
+       AUD_SequencerStrip* strip;
+
+       for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
+       {
+               strip = *i;
+               if(strip->reader)
+                       result |= (*i)->reader->notify(message);
+       }
+
+       return result;
+}
+
+void AUD_SequencerReader::read(int & length, sample_t* & buffer)
+{
+       AUD_DeviceSpecs specs = m_mixer.getSpecs();
+       int samplesize = AUD_SAMPLE_SIZE(specs);
+       int rate = specs.rate;
+
+       int size = length * samplesize;
+
+       int start, end, current, skip, len;
+       AUD_SequencerStrip* strip;
+       sample_t* buf;
+
+       if(m_buffer->getSize() < size)
+               m_buffer->resize(size);
+       buffer = m_buffer->getBuffer();
+
+       for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
+       {
+               strip = *i;
+               if(!strip->entry->muted)
+               {
+                       if(strip->old_sound != *strip->entry->sound)
+                       {
+                               strip->old_sound = *strip->entry->sound;
+                               if(strip->reader)
+                               {
+                                       delete strip->reader; AUD_DELETE("reader")
+                               }
+
+                               if(strip->old_sound)
+                                       strip->reader = m_mixer.prepare(strip->old_sound->createReader());
+                               else
+                                       strip->reader = NULL;
+                       }
+
+                       if(strip->reader)
+                       {
+                               end = floor(strip->entry->end * rate);
+                               if(m_position < end)
+                               {
+                                       start = floor(strip->entry->begin * rate);
+                                       if(m_position + length > start)
+                                       {
+                                               current = m_position - start;
+                                               if(current < 0)
+                                               {
+                                                       skip = -current;
+                                                       current = 0;
+                                               }
+                                               else
+                                                       skip = 0;
+                                               current += strip->entry->skip * rate;
+                                               len = length > end - m_position ? end - m_position : length;
+                                               len -= skip;
+                                               if(strip->reader->getPosition() != current)
+                                                       strip->reader->seek(current);
+                                               strip->reader->read(len, buf);
+                                               m_mixer.add(buf, skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate));
+                                       }
+                               }
+                       }
+               }
+       }
+
+       m_mixer.superpose((data_t*)buffer, length, 1.0f);
+
+       m_position += length;
+}
diff --git a/intern/audaspace/intern/AUD_SequencerReader.h b/intern/audaspace/intern/AUD_SequencerReader.h
new file mode 100644 (file)
index 0000000..a50e164
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_SEQUENCERREADER
+#define AUD_SEQUENCERREADER
+
+#include "AUD_IReader.h"
+#include "AUD_SequencerFactory.h"
+#include "AUD_Mixer.h"
+
+class AUD_Buffer;
+
+struct AUD_SequencerStrip
+{
+       AUD_IFactory* old_sound;
+       AUD_IReader* reader;
+       AUD_SequencerEntry* entry;
+};
+
+/**
+ * This resampling reader uses libsamplerate for resampling.
+ */
+class AUD_SequencerReader : public AUD_IReader
+{
+private:
+       /**
+        * The current position.
+        */
+       int m_position;
+
+       /**
+        * The sound output buffer.
+        */
+       AUD_Buffer *m_buffer;
+
+       /**
+        * The target specification.
+        */
+       AUD_Mixer m_mixer;
+
+       /**
+        * Saves the SequencerFactory the reader belongs to.
+        */
+       AUD_SequencerFactory* m_factory;
+
+       std::list<AUD_SequencerStrip*> m_strips;
+
+       void* m_data;
+       AUD_volumeFunction m_volume;
+
+public:
+       /**
+        * Creates a resampling reader.
+        * \param reader The reader to mix.
+        * \param specs The target specification.
+        * \exception AUD_Exception Thrown if the reader is NULL.
+        */
+       AUD_SequencerReader(AUD_SequencerFactory* factory, std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs, void* data, AUD_volumeFunction volume);
+
+       /**
+        * Destroys the reader.
+        */
+       ~AUD_SequencerReader();
+
+       void destroy();
+
+       void add(AUD_SequencerEntry* entry);
+       void remove(AUD_SequencerEntry* entry);
+
+       virtual bool isSeekable();
+       virtual void seek(int position);
+       virtual int getLength();
+       virtual int getPosition();
+       virtual AUD_Specs getSpecs();
+       virtual AUD_ReaderType getType();
+       virtual bool notify(AUD_Message &message);
+       virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_SEQUENCERREADER
index a615bcd0245d5deceb5ff62ecc1add8167565e5e..5a3f25fba077382a7841ffc57eddabf2f8c90984 100644 (file)
@@ -100,7 +100,6 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
                AUD_SoftwareHandle* sound;
                int len;
                sample_t* buf;
-               int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs);
                std::list<AUD_SoftwareHandle*> stopSounds;
 
                // for all sounds
@@ -116,7 +115,7 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
                        len = length;
                        sound->reader->read(len, buf);
 
-                       m_mixer->add(buf, len, sound->volume);
+                       m_mixer->add(buf, 0, len, sound->volume);
 
                        // in case the end of the sound is reached
                        if(len < length)
@@ -128,12 +127,6 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
                        }
                }
 
-               // fill with silence
-               if(m_specs.format == AUD_FORMAT_U8)
-                       memset(buffer, 0x80, length * sample_size);
-               else
-                       memset(buffer, 0, length * sample_size);
-
                // superpose
                m_mixer->superpose(buffer, length, m_volume);
 
index 1d60be3979b0043012dc315a3fbab54d39e77401..9e192ac2cac57092d741d2dfe9f3c6da25b98ae9 100644 (file)
@@ -294,7 +294,11 @@ typedef struct
        union
        {
                // loop reader
-               int loopcount;
+               struct
+               {
+                       int loopcount;
+                       float time;
+               };
 
                // volume reader
                float volume;
index c7f8ddd052cfe7440f6e0ef82e1c62624d30fb55..0eb46955a0c0bc58b8b67edcae2e2091dd88c0df 100644 (file)
@@ -416,11 +416,11 @@ class RENDER_PT_encoding(RenderButtonsPanel):
         col.prop(rd, "ffmpeg_packetsize", text="Packet Size")
 
         # Audio:
-        layout.prop(rd, "ffmpeg_multiplex_audio", text="Audio")
-
         sub = layout.column()
-        sub.active = rd.ffmpeg_multiplex_audio
-        sub.prop(rd, "ffmpeg_audio_codec", text="Codec")
+
+        if rd.ffmpeg_format not in ('MP3'):
+          sub.prop(rd, "ffmpeg_audio_codec", text="Audio Codec")
+
         sub.separator()
 
         split = sub.split()
index 0c84d729d474879cd8054791cb40d73410c96b0d..49afe201c92c4f118b23f2206fb59ebc4bdaba22 100644 (file)
@@ -150,8 +150,8 @@ struct ImBuf *give_ibuf_seq(struct Scene *scene, int rectx, int recty, int cfra,
 struct ImBuf *give_ibuf_seq_threaded(struct Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size);
 struct ImBuf *give_ibuf_seq_direct(struct Scene *scene, int rectx, int recty, int cfra, int render_size, struct Sequence *seq);
 void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, int render_size);
-void calc_sequence(struct Sequence *seq);
-void calc_sequence_disp(struct Sequence *seq);
+void calc_sequence(struct Scene *scene, struct Sequence *seq);
+void calc_sequence_disp(struct Scene *scene, struct Sequence *seq);
 void new_tstripdata(struct Sequence *seq);
 void reload_sequence_new_file(struct Scene *scene, struct Sequence * seq);
 void sort_seq(struct Scene *scene);
@@ -191,8 +191,8 @@ int shuffle_seq_time(ListBase * seqbasep, struct Scene *evil_scene);
 int seqbase_isolated_sel_check(struct ListBase *seqbase);
 void free_imbuf_seq(struct Scene *scene, struct ListBase * seqbasep, int check_mem_usage);
 
-void seq_update_sound(struct Sequence *seq);
-void seq_update_muting(struct Editing *ed);
+void seq_update_sound(struct Scene* scene, struct Sequence *seq);
+void seq_update_muting(struct Scene* scene, struct Editing *ed);
 void seqbase_sound_reload(Scene *scene, ListBase *seqbase);
 void clear_scene_in_allseqs(struct Scene *sce);
 
index 82ef525ba918077dc696e2de4d597fc855ef6b90..1c9a7db03c3c322580ea75667497f7762c2edfee 100644 (file)
@@ -36,6 +36,7 @@ struct bSound;
 struct bContext;
 struct ListBase;
 struct Main;
+struct Sequence;
 
 void sound_init();
 
@@ -63,20 +64,28 @@ void sound_load(struct Main *main, struct bSound* sound);
 
 void sound_free(struct bSound* sound);
 
-void sound_unlink(struct bContext *C, struct bSound* sound);
+#ifdef AUD_CAPI
+AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume);
+#endif
 
-struct SoundHandle* sound_new_handle(struct Scene *scene, struct bSound* sound, int startframe, int endframe, int frameskip);
+void sound_create_scene(struct Scene *scene);
 
-void sound_delete_handle(struct Scene *scene, struct SoundHandle *handle);
+void sound_destroy_scene(struct Scene *scene);
 
-void sound_update_playing(struct bContext *C);
+void* sound_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip);
 
-void sound_scrub(struct bContext *C);
+void sound_remove_scene_sound(struct Scene *scene, void* handle);
 
-#ifdef AUD_CAPI
-AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, int end, float volume);
-#endif
+void sound_mute_scene_sound(struct Scene *scene, void* handle, char mute);
+
+void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, int endframe, int frameskip);
+
+void sound_play_scene(struct Scene *scene);
+
+void sound_stop_scene(struct Scene *scene);
+
+void sound_seek_scene(struct bContext *C);
 
-void sound_stop_all(struct bContext *C);
+int sound_read_sound_buffer(struct bSound* sound, float* buffer, int length);
 
 #endif
index 98c385ea2e1678364c688dbd8ac7eb3b165adfda..20c5b2fd46fc3f50bd75b17a801b0be5e4fb3600 100644 (file)
@@ -45,6 +45,8 @@ extern "C" {
 #define FFMPEG_FLV      8
 #define FFMPEG_MKV      9
 #define FFMPEG_OGG      10
+#define FFMPEG_WAV      11
+#define FFMPEG_MP3      12
 
 #define FFMPEG_PRESET_NONE             0
 #define FFMPEG_PRESET_DVD              1
index b80f22a05c27e764dc4403c59e3eaf4f836933ec..780ded2a94182fb8c01ffd64898407cc6d52b288 100644 (file)
@@ -83,6 +83,7 @@
 #include "BKE_sequencer.h"
 #include "BKE_world.h"
 #include "BKE_utildefines.h"
+#include "BKE_sound.h"
 
 //XXX #include "BIF_previewrender.h"
 //XXX #include "BIF_editseq.h"
@@ -233,6 +234,8 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type)
         }
        }
 
+       sound_create_scene(scen);
+
        return scen;
 }
 
@@ -315,6 +318,8 @@ void free_scene(Scene *sce)
 
        if(sce->stats)
                MEM_freeN(sce->stats);
+
+       sound_destroy_scene(sce);
 }
 
 Scene *add_scene(char *name)
@@ -480,6 +485,8 @@ Scene *add_scene(char *name)
        sce->gm.flag = GAME_DISPLAY_LISTS;
        sce->gm.matmode = GAME_MAT_MULTITEX;
 
+       sound_create_scene(sce);
+
        return sce;
 }
 
index 9fde073001111b59ce1a849cf7a2b097da1ac080..8c119eb753ba7eaaa37bf5fff42400c158edf562 100644 (file)
@@ -233,8 +233,8 @@ void seq_free_sequence(Scene *scene, Sequence *seq)
                if (ed->act_seq==seq)
                        ed->act_seq= NULL;
 
-               if(seq->sound_handle)
-                       sound_delete_handle(scene, seq->sound_handle);
+               if(seq->scene_sound)
+                       sound_remove_scene_sound(scene, seq->scene_sound);
        }
 
        MEM_freeN(seq);
@@ -484,7 +484,7 @@ void build_seqar_cb(ListBase *seqbase, Sequence  ***seqar, int *totseq,
 }
 
 
-void calc_sequence_disp(Sequence *seq)
+void calc_sequence_disp(Scene *scene, Sequence *seq)
 {
        if(seq->startofs && seq->startstill) seq->startstill= 0;
        if(seq->endofs && seq->endstill) seq->endstill= 0;
@@ -500,10 +500,10 @@ void calc_sequence_disp(Sequence *seq)
                seq->handsize= (float)((seq->enddisp-seq->startdisp)/25);
        }
 
-       seq_update_sound(seq);
+       seq_update_sound(scene, seq);
 }
 
-void calc_sequence(Sequence *seq)
+void calc_sequence(Scene *scene, Sequence *seq)
 {
        Sequence *seqm;
        int min, max;
@@ -511,7 +511,7 @@ void calc_sequence(Sequence *seq)
        /* check all metas recursively */
        seqm= seq->seqbase.first;
        while(seqm) {
-               if(seqm->seqbase.first) calc_sequence(seqm);
+               if(seqm->seqbase.first) calc_sequence(scene, seqm);
                seqm= seqm->next;
        }
 
@@ -534,7 +534,7 @@ void calc_sequence(Sequence *seq)
                        seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp);
                        seq->len= seq->enddisp - seq->startdisp;
                } else {
-                       calc_sequence_disp(seq);
+                       calc_sequence_disp(scene, seq);
                }
 
                if(seq->strip && seq->len!=seq->strip->len) {
@@ -563,7 +563,7 @@ void calc_sequence(Sequence *seq)
                                }
                        }
                }
-               calc_sequence_disp(seq);
+               calc_sequence_disp(scene, seq);
        }
 }
 
@@ -614,7 +614,7 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq)
                }
                seq->strip->len = seq->len;
        } else if (seq->type == SEQ_SOUND) {
-               seq->len = AUD_getInfo(seq->sound->handle).length * FPS;
+               seq->len = AUD_getInfo(seq->sound->playback_handle).length * FPS;
                seq->len -= seq->anim_startofs;
                seq->len -= seq->anim_endofs;
                if (seq->len < 0) {
@@ -653,7 +653,7 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq)
 
        free_proxy_seq(seq);
 
-       calc_sequence(seq);
+       calc_sequence(scene, seq);
 }
 
 void sort_seq(Scene *scene)
@@ -3189,7 +3189,7 @@ static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *chan
                }
                
                if(len_change)
-                       calc_sequence(seq);
+                       calc_sequence(scene, seq);
        }
        
        return free_imbuf;
@@ -3239,23 +3239,6 @@ static void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo)
 }
 #endif
 
-static int seq_sound_reload_cb(Sequence *seq, void *arg_pt)
-{
-       if (seq->type==SEQ_SOUND && seq->sound) {
-               Scene *scene= (Scene *)arg_pt;
-               if(seq->sound_handle)
-                       sound_delete_handle(scene, seq->sound_handle);
-
-               seq->sound_handle = sound_new_handle(scene, seq->sound, seq->start, seq->start + seq->strip->len, 0);
-               return 0;
-       }
-       return 1; /* recurse meta's */
-}
-void seqbase_sound_reload(Scene *scene, ListBase *seqbase)
-{
-       seqbase_recursive_apply(seqbase, seq_sound_reload_cb, (void *)scene);
-}
-
 /* seq funcs's for transforming internally
  notice the difference between start/end and left/right.
 
@@ -3463,7 +3446,7 @@ static void seq_translate(Scene *evil_scene, Sequence *seq, int delta)
                }
        }
 
-       calc_sequence_disp(seq);
+       calc_sequence_disp(evil_scene, seq);
 }
 
 /* return 0 if there werent enough space */
@@ -3471,13 +3454,13 @@ int shuffle_seq(ListBase * seqbasep, Sequence *test, Scene *evil_scene)
 {
        int orig_machine= test->machine;
        test->machine++;
-       calc_sequence(test);
+       calc_sequence(evil_scene, test);
        while( seq_test_overlap(seqbasep, test) ) {
                if(test->machine >= MAXSEQ) {
                        break;
                }
                test->machine++;
-               calc_sequence(test); // XXX - I dont think this is needed since were only moving vertically, Campbell.
+               calc_sequence(evil_scene, test); // XXX - I dont think this is needed since were only moving vertically, Campbell.
        }
 
        
@@ -3497,7 +3480,7 @@ int shuffle_seq(ListBase * seqbasep, Sequence *test, Scene *evil_scene)
                new_frame = new_frame + (test->start-test->startdisp); /* adjust by the startdisp */
                seq_translate(evil_scene, test, new_frame - test->start);
 
-               calc_sequence(test);
+               calc_sequence(evil_scene, test);
                return 0;
        } else {
                return 1;
@@ -3526,7 +3509,7 @@ static int shuffle_seq_time_offset_test(ListBase * seqbasep, char dir)
        return offset;
 }
 
-static int shuffle_seq_time_offset(ListBase * seqbasep, char dir)
+static int shuffle_seq_time_offset(Scene* scene, ListBase * seqbasep, char dir)
 {
        int ofs= 0;
        int tot_ofs= 0;
@@ -3545,7 +3528,7 @@ static int shuffle_seq_time_offset(ListBase * seqbasep, char dir)
 
        for(seq= seqbasep->first; seq; seq= seq->next) {
                if(seq->tmp)
-                       calc_sequence_disp(seq); /* corrects dummy startdisp/enddisp values */
+                       calc_sequence_disp(scene, seq); /* corrects dummy startdisp/enddisp values */
        }
 
        return tot_ofs;
@@ -3557,8 +3540,8 @@ int shuffle_seq_time(ListBase * seqbasep, Scene *evil_scene)
 
        Sequence *seq;
 
-       int offset_l = shuffle_seq_time_offset(seqbasep, 'L');
-       int offset_r = shuffle_seq_time_offset(seqbasep, 'R');
+       int offset_l = shuffle_seq_time_offset(evil_scene, seqbasep, 'L');
+       int offset_r = shuffle_seq_time_offset(evil_scene, seqbasep, 'R');
        int offset = (-offset_l < offset_r) ?  offset_l:offset_r;
 
        if(offset) {
@@ -3573,19 +3556,16 @@ int shuffle_seq_time(ListBase * seqbasep, Scene *evil_scene)
        return offset? 0:1;
 }
 
-void seq_update_sound(Sequence *seq)
+void seq_update_sound(Scene* scene, Sequence *seq)
 {
-       if(seq->type == SEQ_SOUND && seq->sound_handle)
+       if(seq->scene_sound)
        {
-               seq->sound_handle->startframe = seq->startdisp;
-               seq->sound_handle->endframe = seq->enddisp;
-               seq->sound_handle->frameskip = seq->startofs + seq->anim_startofs;
-               seq->sound_handle->changed = -1;
+               sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
                /* mute is set in seq_update_muting_recursive */
        }
 }
 
-static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, int mute)
+static void seq_update_muting_recursive(Scene *scene, ListBase *seqbasep, Sequence *metaseq, int mute)
 {
        Sequence *seq;
        int seqmute;
@@ -3601,27 +3581,26 @@ static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, i
                        if(seq == metaseq)
                                seqmute= 0;
 
-                       seq_update_muting_recursive(&seq->seqbase, metaseq, seqmute);
+                       seq_update_muting_recursive(scene, &seq->seqbase, metaseq, seqmute);
                }
                else if(seq->type == SEQ_SOUND) {
-                       if(seq->sound_handle && seqmute != seq->sound_handle->mute) {
-                               seq->sound_handle->mute = seqmute;
-                               seq->sound_handle->changed = -1;
+                       if(seq->scene_sound) {
+                               sound_mute_scene_sound(scene, seq->scene_sound, seqmute);
                        }
                }
        }
 }
 
-void seq_update_muting(Editing *ed)
+void seq_update_muting(Scene *scene, Editing *ed)
 {
        if(ed) {
                /* mute all sounds up to current metastack list */
                MetaStack *ms= ed->metastack.last;
 
                if(ms)
-                       seq_update_muting_recursive(&ed->seqbase, ms->parseq, 1);
+                       seq_update_muting_recursive(scene, &ed->seqbase, ms->parseq, 1);
                else
-                       seq_update_muting_recursive(&ed->seqbase, NULL, 0);
+                       seq_update_muting_recursive(scene, &ed->seqbase, NULL, 0);
        }
 }
 
@@ -3744,6 +3723,7 @@ Sequence *alloc_sequence(ListBase *lb, int cfra, int machine)
        seq->machine= machine;
        seq->mul= 1.0;
        seq->blend_opacity = 100.0;
+       seq->volume = 1.0f;
 
        return seq;
 }
@@ -3793,13 +3773,13 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 
        sound = sound_new_file(CTX_data_main(C), seq_load->path);
 
-       if (sound==NULL || sound->handle == NULL) {
+       if (sound==NULL || sound->playback_handle == NULL) {
                //if(op)
                //      BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
                return NULL;
        }
 
-       info = AUD_getInfo(sound->handle);
+       info = AUD_getInfo(sound->playback_handle);
 
        if (info.specs.channels == AUD_CHANNELS_INVALID) {
                sound_delete(C, sound);
@@ -3824,9 +3804,9 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 
        BLI_split_dirfile_basic(seq_load->path, strip->dir, se->name);
 
-       seq->sound_handle = sound_new_handle(scene, sound, seq_load->start_frame, seq_load->start_frame + strip->len, 0);
+       seq->scene_sound = sound_add_scene_sound(scene, seq, seq_load->start_frame, seq_load->start_frame + strip->len, 0);
 
-       calc_sequence_disp(seq);
+       calc_sequence_disp(scene, seq);
 
        /* last active name */
        strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR-1);
@@ -3868,7 +3848,7 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 
        BLI_split_dirfile_basic(seq_load->path, strip->dir, se->name);
 
-       calc_sequence_disp(seq);
+       calc_sequence_disp(scene, seq);
 
 
        if(seq_load->flag & SEQ_LOAD_MOVIE_SOUND) {
index 1be59529cc792b3baec90f6eb7cee522c471f0de..7b451bd5a98d6a79058cc838fbedeea8898e1b4d 100644 (file)
@@ -12,6 +12,7 @@
 #include "BLI_blenlib.h"
 
 #include "DNA_scene_types.h"
+#include "DNA_sequence_types.h"
 #include "DNA_sound_types.h"
 #include "DNA_packedFile_types.h"
 #include "DNA_screen_types.h"
@@ -26,6 +27,9 @@
 #include "BKE_context.h"
 #include "BKE_library.h"
 #include "BKE_packedFile.h"
+#include "BKE_fcurve.h"
+
+#include "RNA_access.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -107,7 +111,7 @@ struct bSound* sound_new_file(struct Main *main, char* filename)
 
        sound_load(main, sound);
 
-       if(!sound->handle)
+       if(!sound->playback_handle)
        {
                free_libblock(&main->sound, sound);
                sound = NULL;
@@ -133,7 +137,7 @@ struct bSound* sound_new_buffer(struct bContext *C, struct bSound *source)
 
        sound_load(CTX_data_main(C), sound);
 
-       if(!sound->handle)
+       if(!sound->playback_handle)
        {
                free_libblock(&CTX_data_main(C)->sound, sound);
                sound = NULL;
@@ -159,7 +163,7 @@ struct bSound* sound_new_limiter(struct bContext *C, struct bSound *source, floa
 
        sound_load(CTX_data_main(C), sound);
 
-       if(!sound->handle)
+       if(!sound->playback_handle)
        {
                free_libblock(&CTX_data_main(C)->sound, sound);
                sound = NULL;
@@ -175,8 +179,6 @@ void sound_delete(struct bContext *C, struct bSound* sound)
        {
                sound_free(sound);
 
-               sound_unlink(C, sound);
-
                free_libblock(&CTX_data_main(C)->sound, sound);
        }
 }
@@ -187,7 +189,7 @@ void sound_cache(struct bSound* sound, int ignore)
                AUD_unload(sound->cache);
 
        sound->cache = AUD_bufferSound(sound->handle);
-       sound->changed++;
+       sound->playback_handle = sound->cache;
 }
 
 void sound_delete_cache(struct bSound* sound)
@@ -196,6 +198,7 @@ void sound_delete_cache(struct bSound* sound)
        {
                AUD_unload(sound->cache);
                sound->cache = NULL;
+               sound->playback_handle = sound->handle;
        }
 }
 
@@ -207,6 +210,7 @@ void sound_load(struct Main *main, struct bSound* sound)
                {
                        AUD_unload(sound->handle);
                        sound->handle = NULL;
+                       sound->playback_handle = NULL;
                }
 
 // XXX unused currently
@@ -253,7 +257,10 @@ void sound_load(struct Main *main, struct bSound* sound)
                        break;
                }
 #endif
-               sound->changed++;
+               if(sound->cache)
+                       sound->playback_handle = sound->cache;
+               else
+                       sound->playback_handle = sound->handle;
        }
 }
 
@@ -269,243 +276,115 @@ void sound_free(struct bSound* sound)
        {
                AUD_unload(sound->handle);
                sound->handle = NULL;
+               sound->playback_handle = NULL;
        }
 }
 
-void sound_unlink(struct bContext *C, struct bSound* sound)
+static float sound_get_volume(Scene* scene, Sequence* sequence, float time)
 {
-       Scene *scene;
-       SoundHandle *handle;
-
-// XXX unused currently
-#if 0
-       bSound *snd;
-       for(snd = CTX_data_main(C)->sound.first; snd; snd = snd->id.next)
-       {
-               if(snd->child_sound == sound)
-               {
-                       snd->child_sound = NULL;
-                       if(snd->handle)
-                       {
-                               AUD_unload(sound->handle);
-                               snd->handle = NULL;
-                       }
-
-                       sound_unlink(C, snd);
-               }
-       }
-#endif
-
-       for(scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next)
-       {
-               for(handle = scene->sound_handles.first; handle; handle = handle->next)
-               {
-                       if(handle->source == sound)
-                       {
-                               handle->source = NULL;
-                               if(handle->handle)
-                                       AUD_stop(handle->handle);
-                       }
-               }
-       }
+       struct FCurve* fcu = id_data_find_fcurve(scene, sequence, &RNA_Sequence, "volume", 0);
+       if(fcu)
+               return evaluate_fcurve(fcu, time * FPS);
+       else
+               return sequence->volume;
 }
 
-struct SoundHandle* sound_new_handle(struct Scene *scene, struct bSound* sound, int startframe, int endframe, int frameskip)
+AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume)
 {
-       ListBase* handles = &scene->sound_handles;
+       AUD_Device* mixdown = AUD_openReadDevice(specs);
+
+       AUD_setDeviceVolume(mixdown, volume);
 
-       SoundHandle* handle = MEM_callocN(sizeof(SoundHandle), "sound_handle");
-       handle->source = sound;
-       handle->startframe = startframe;
-       handle->endframe = endframe;
-       handle->frameskip = frameskip;
-       handle->state = AUD_STATUS_INVALID;
-       handle->volume = 1.0f;
+       AUD_playDevice(mixdown, scene->sound_scene, start / FPS);
 
-       BLI_addtail(handles, handle);
+       return mixdown;
+}
 
-       return handle;
+void sound_create_scene(struct Scene *scene)
+{
+       scene->sound_scene = AUD_createSequencer(scene, (AUD_volumeFunction)&sound_get_volume);
 }
 
-void sound_delete_handle(struct Scene *scene, struct SoundHandle *handle)
+void sound_destroy_scene(struct Scene *scene)
 {
-       if(handle == NULL)
-               return;
+       if(scene->sound_scene_handle)
+               AUD_stop(scene->sound_scene_handle);
+       if(scene->sound_scene)
+               AUD_destroySequencer(scene->sound_scene);
+}
 
-       if(handle->handle)
-               AUD_stop(handle->handle);
+void* sound_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip)
+{
+       return AUD_addSequencer(scene->sound_scene, &(sequence->sound->playback_handle), startframe / FPS, endframe / FPS, frameskip / FPS, sequence);
+}
 
-       BLI_freelinkN(&scene->sound_handles, handle);
+void sound_remove_scene_sound(struct Scene *scene, void* handle)
+{
+       AUD_removeSequencer(scene->sound_scene, handle);
 }
 
-void sound_stop_all(struct bContext *C)
+void sound_mute_scene_sound(struct Scene *scene, void* handle, char mute)
 {
-       SoundHandle *handle;
+       AUD_muteSequencer(scene->sound_scene, handle, mute);
+}
 
-       for(handle = CTX_data_scene(C)->sound_handles.first; handle; handle = handle->next)
-       {
-               if(handle->state == AUD_STATUS_PLAYING)
-               {
-                       AUD_pause(handle->handle);
-                       handle->state = AUD_STATUS_PAUSED;
-               }
-       }
+void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, int endframe, int frameskip)
+{
+       AUD_moveSequencer(scene->sound_scene, handle, startframe / FPS, endframe / FPS, frameskip / FPS);
 }
 
-void sound_update_playing(struct bContext *C)
+void sound_start_play_scene(struct Scene *scene)
 {
-       SoundHandle *handle;
-       Scene* scene = CTX_data_scene(C);
-       int cfra = CFRA;
-       float fps = FPS;
-       int action;
+       AUD_Sound* sound;
+       sound = AUD_loopSound(scene->sound_scene);
+       scene->sound_scene_handle = AUD_play(sound, 1);
+       AUD_unload(sound);
+}
 
+void sound_play_scene(struct Scene *scene)
+{
        AUD_lock();
 
-       for(handle = scene->sound_handles.first; handle; handle = handle->next)
-       {
-               if(cfra < handle->startframe || cfra >= handle->endframe || handle->mute || (scene->audio.flag & AUDIO_MUTE))
-               {
-                       if(handle->state == AUD_STATUS_PLAYING)
-                       {
-                               AUD_pause(handle->handle);
-                               handle->state = AUD_STATUS_PAUSED;
-                       }
-               }
-               else
-               {
-                       action = 0;
-
-                       if(handle->changed != handle->source->changed)
-                       {
-                               handle->changed = handle->source->changed;
-                               action = 3;
-                               if(handle->state != AUD_STATUS_INVALID)
-                               {
-                                       AUD_stop(handle->handle);
-                                       handle->state = AUD_STATUS_INVALID;
-                               }
-                       }
-                       else
-                       {
-                               if(handle->state != AUD_STATUS_PLAYING)
-                                       action = 3;
-                               else
-                               {
-                                       handle->state = AUD_getStatus(handle->handle);
-                                       if(handle->state != AUD_STATUS_PLAYING)
-                                               action = 3;
-                                       else
-                                       {
-                                               float diff = AUD_getPosition(handle->handle) * fps - cfra + handle->startframe;
-                                               if(diff < 0.0)
-                                                       diff = -diff;
-                                               if(diff > FPS/2.0)
-                                               {
-                                                       action = 2;
-                                               }
-                                       }
-                               }
-                       }
-
-                       AUD_setSoundVolume(handle->handle, handle->volume);
-                       
-                       if(action & 1)
-                       {
-                               if(handle->state == AUD_STATUS_INVALID)
-                               {
-                                       if(handle->source && handle->source->handle)
-                                       {
-                                               AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->handle, handle->frameskip / fps, (handle->frameskip + handle->endframe - handle->startframe)/fps);
-                                               handle->handle = AUD_play(limiter, 1);
-                                               AUD_unload(limiter);
-                                               if(handle->handle)
-                                                       handle->state = AUD_STATUS_PLAYING;
-                                               if(cfra == handle->startframe)
-                                                       action &= ~2;
-                                       }
-                               }
-                               else
-                                       if(AUD_resume(handle->handle))
-                                               handle->state = AUD_STATUS_PLAYING;
-                                       else
-                                               handle->state = AUD_STATUS_INVALID;
-                       }
-
-                       if(action & 2)
-                               AUD_seek(handle->handle, (cfra - handle->startframe) / fps);
-               }
-       }
+       if(!scene->sound_scene_handle || AUD_getStatus(scene->sound_scene_handle) == AUD_STATUS_INVALID)
+               sound_start_play_scene(scene);
+
+       AUD_seek(scene->sound_scene_handle, CFRA / FPS);
+       AUD_setLoop(scene->sound_scene_handle, -1, -1);
+       AUD_resume(scene->sound_scene_handle);
 
        AUD_unlock();
 }
 
-void sound_scrub(struct bContext *C)
+void sound_stop_scene(struct Scene *scene)
 {
-       SoundHandle *handle;
-       Scene* scene = CTX_data_scene(C);
-       int cfra = CFRA;
-       float fps = FPS;
-
-       if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer)
-       {
-               AUD_lock();
-
-               for(handle = scene->sound_handles.first; handle; handle = handle->next)
-               {
-                       if(cfra >= handle->startframe && cfra < handle->endframe && !handle->mute)
-                       {
-                               if(handle->source && handle->source->handle)
-                               {
-                                       int frameskip = handle->frameskip + cfra - handle->startframe;
-                                       AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->handle, frameskip / fps, (frameskip + 1)/fps);
-                                       AUD_play(limiter, 0);
-                                       AUD_unload(limiter);
-                               }
-                       }
-               }
-
-               AUD_unlock();
-       }
+       AUD_pause(scene->sound_scene_handle);
 }
 
-AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, int end, float volume)
+void sound_seek_scene(struct bContext *C)
 {
-       AUD_Device* mixdown = AUD_openReadDevice(specs);
-       SoundHandle *handle;
-       float fps = FPS;
-       AUD_Sound *limiter, *delayer;
-       int frameskip, s, e;
+       struct Scene *scene = CTX_data_scene(C);
 
-       end++;
+       AUD_lock();
 
-       AUD_setDeviceVolume(mixdown, volume);
+       if(!scene->sound_scene_handle || AUD_getStatus(scene->sound_scene_handle) == AUD_STATUS_INVALID)
+       {
+               sound_start_play_scene(scene);
+               AUD_pause(scene->sound_scene_handle);
+       }
 
-       for(handle = scene->sound_handles.first; handle; handle = handle->next)
+       if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer)
        {
-               if(start < handle->endframe && end > handle->startframe && !handle->mute && handle->source && handle->source->handle)
-               {
-                       frameskip = handle->frameskip;
-                       s = handle->startframe - start;
-                       e = handle->frameskip + AUD_MIN(handle->endframe, end) - handle->startframe;
-
-                       if(s < 0)
-                       {
-                               frameskip -= s;
-                               s = 0;
-                       }
-                       
-                       AUD_setSoundVolume(handle->handle, handle->volume);
-                       
-                       limiter = AUD_limitSound(handle->source->handle, frameskip / fps, e / fps);
-                       delayer = AUD_delaySound(limiter, s / fps);
-
-                       AUD_playDevice(mixdown, delayer);
-
-                       AUD_unload(delayer);
-                       AUD_unload(limiter);
-               }
+               AUD_setLoop(scene->sound_scene_handle, -1, 1 / FPS);
+               AUD_seek(scene->sound_scene_handle, CFRA / FPS);
+               AUD_resume(scene->sound_scene_handle);
        }
+       else
+               AUD_seek(scene->sound_scene_handle, CFRA / FPS);
 
-       return mixdown;
+       AUD_unlock();
+}
+
+int sound_read_sound_buffer(bSound* sound, float* buffer, int length)
+{
+       AUD_readSound(sound->cache, buffer, length);
 }
index 9c38f84aa2670ec200e6467e407d788b2fe68b43..3aca9ffb4e70937297d39d02439e72b9a15c7650 100644 (file)
@@ -15,7 +15,6 @@
  *
  */
 
-
 #ifdef WITH_FFMPEG
 #include <string.h>
 #include <stdio.h>
@@ -78,11 +77,10 @@ extern void do_init_ffmpeg();
 
 static int ffmpeg_type = 0;
 static int ffmpeg_codec = CODEC_ID_MPEG4;
-static int ffmpeg_audio_codec = CODEC_ID_MP2;
+static int ffmpeg_audio_codec = CODEC_ID_NONE;
 static int ffmpeg_video_bitrate = 1150;
 static int ffmpeg_audio_bitrate = 128;
 static int ffmpeg_gop_size = 12;
-static int ffmpeg_multiplex_audio = 1;
 static int ffmpeg_autosplit = 0;
 static int ffmpeg_autosplit_count = 0;
 
@@ -99,6 +97,7 @@ static uint8_t* audio_input_buffer = 0;
 static int audio_input_frame_size = 0;
 static uint8_t* audio_output_buffer = 0;
 static int audio_outbuf_size = 0;
+static double audio_time = 0.0f;
 
 static AUD_Device* audio_mixdown_device = 0;
 
@@ -130,30 +129,43 @@ static int write_audio_frame(void)
 {
        AVCodecContext* c = NULL;
        AVPacket pkt;
+       AVStream* str = audio_stream;
 
        c = get_codec_from_stream(audio_stream);
 
-       if(audio_mixdown_device)
-               AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_frame_size);
-
        av_init_packet(&pkt);
+       pkt.size = 0;
+
+       AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_frame_size);
+       audio_time += (double) audio_input_frame_size / (double) c->sample_rate;
 
        pkt.size = avcodec_encode_audio(c, audio_output_buffer,
-                                       audio_outbuf_size, 
+                                       audio_outbuf_size,
                                        (short*) audio_input_buffer);
+
+       if(pkt.size <= 0)
+       {
+               // XXX error("Error writing audio packet");
+               return -1;
+       }
+
        pkt.data = audio_output_buffer;
+
+       if(c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE)
+       {
 #ifdef FFMPEG_CODEC_TIME_BASE
-       pkt.pts = av_rescale_q(c->coded_frame->pts, 
-                              c->time_base, audio_stream->time_base);
+               pkt.pts = av_rescale_q(c->coded_frame->pts,
+                                          c->time_base, audio_stream->time_base);
 #else
-       pkt.pts = c->coded_frame->pts;
+               pkt.pts = c->coded_frame->pts;
 #endif
-       fprintf(stderr, "Audio Frame PTS: %d\n", (int)pkt.pts);
+               fprintf(stderr, "Audio Frame PTS: %d\n", (int)pkt.pts);
+       }
 
        pkt.stream_index = audio_stream->index;
        pkt.flags |= PKT_FLAG_KEY;
        if (av_interleaved_write_frame(outfile, &pkt) != 0) {
-               //XXX error("Error writing audio packet");
+               // XXX error("Error writing audio packet");
                return -1;
        }
        return 0;
@@ -233,6 +245,14 @@ static const char** get_file_extensions(int format)
                static const char * rv[] = { ".ogg", ".ogv", NULL };
                return rv;
        }
+       case FFMPEG_MP3: {
+               static const char * rv[] = { ".mp3", NULL };
+               return rv;
+       }
+       case FFMPEG_WAV: {
+               static const char * rv[] = { ".wav", NULL };
+               return rv;
+       }
        default:
                return NULL;
        }
@@ -563,6 +583,7 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
 
        c->sample_rate = rd->ffcodecdata.audio_mixrate;
        c->bit_rate = ffmpeg_audio_bitrate*1000;
+       c->sample_fmt = SAMPLE_FMT_S16;
        c->channels = 2;
        codec = avcodec_find_encoder(c->codec_id);
        if (!codec) {
@@ -577,40 +598,22 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
                return NULL;
        }
 
-       /* FIXME: Should be user configurable */
-       if (ffmpeg_type == FFMPEG_DV) {
-               /* this is a hack around the poor ffmpeg dv multiplexer. */
-               /* only fixes PAL for now 
-                  (NTSC is a lot more complicated here...)! */
-               audio_outbuf_size = 7680;
-       } else {
-               audio_outbuf_size = 10000;
-       }
+       audio_outbuf_size = FF_MIN_BUFFER_SIZE;
+
        audio_output_buffer = (uint8_t*)MEM_mallocN(
                audio_outbuf_size, "FFMPEG audio encoder input buffer");
 
-       /* ugly hack for PCM codecs */
-
-       if (c->frame_size <= 1) {
-               audio_input_frame_size = audio_outbuf_size / c->channels;
-               switch(c->codec_id) {
-               case CODEC_ID_PCM_S16LE:
-               case CODEC_ID_PCM_S16BE:
-               case CODEC_ID_PCM_U16LE:
-               case CODEC_ID_PCM_U16BE:
-                       audio_input_frame_size >>= 1;
-                       break;
-               default:
-                       break;
-               }
-       } else {
+       if((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
+               audio_input_frame_size = audio_outbuf_size * 8 / c->bits_per_coded_sample / c->channels;
+       else
                audio_input_frame_size = c->frame_size;
-       }
 
        audio_input_buffer = (uint8_t*)MEM_mallocN(
-               audio_input_frame_size * sizeof(short) * c->channels, 
+               audio_input_frame_size * c->channels * sizeof(int16_t),
                "FFMPEG audio encoder output buffer");
 
+       audio_time = 0.0f;
+
        return st;
 }
 /* essential functions -- start, append, end */
@@ -629,8 +632,6 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
        ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
        ffmpeg_gop_size = rd->ffcodecdata.gop_size;
-       ffmpeg_multiplex_audio = rd->ffcodecdata.flags
-               & FFMPEG_MULTIPLEX_AUDIO;
        ffmpeg_autosplit = rd->ffcodecdata.flags
                & FFMPEG_AUTOSPLIT_OUTPUT;
        
@@ -641,12 +642,11 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        fprintf(stderr, "Starting output to %s(ffmpeg)...\n"
                "  Using type=%d, codec=%d, audio_codec=%d,\n"
                "  video_bitrate=%d, audio_bitrate=%d,\n"
-               "  gop_size=%d, multiplex=%d, autosplit=%d\n"
+               "  gop_size=%d, autosplit=%d\n"
                "  render width=%d, render height=%d\n", 
                name, ffmpeg_type, ffmpeg_codec, ffmpeg_audio_codec,
                ffmpeg_video_bitrate, ffmpeg_audio_bitrate,
-               ffmpeg_gop_size, ffmpeg_multiplex_audio,
-               ffmpeg_autosplit, rectx, recty);
+               ffmpeg_gop_size, ffmpeg_autosplit, rectx, recty);
        
        exts = get_file_extensions(ffmpeg_type);
        if (!exts) {
@@ -667,7 +667,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        
        of->oformat = fmt;
        of->packet_size= rd->ffcodecdata.mux_packet_size;
-       if (ffmpeg_multiplex_audio) {
+       if (ffmpeg_audio_codec != CODEC_ID_NONE) {
                of->mux_rate = rd->ffcodecdata.mux_rate;
        } else {
                of->mux_rate = 0;
@@ -676,6 +676,8 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        of->preload = (int)(0.5*AV_TIME_BASE);
        of->max_delay = (int)(0.7*AV_TIME_BASE);
 
+       fmt->audio_codec = ffmpeg_audio_codec;
+
        snprintf(of->filename, sizeof(of->filename), "%s", name);
        /* set the codec to the user's selection */
        switch(ffmpeg_type) {
@@ -703,6 +705,11 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        case FFMPEG_FLV:
                fmt->video_codec = CODEC_ID_FLV1;
                break;
+       case FFMPEG_MP3:
+               fmt->audio_codec = CODEC_ID_MP3;
+       case FFMPEG_WAV:
+               fmt->video_codec = CODEC_ID_NONE;
+               break;
        case FFMPEG_MPEG4:
        default:
                fmt->video_codec = CODEC_ID_MPEG4;
@@ -723,30 +730,29 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
                }
        }
        
-       fmt->audio_codec = ffmpeg_audio_codec;
-
        if (ffmpeg_type == FFMPEG_DV) {
                fmt->audio_codec = CODEC_ID_PCM_S16LE;
-               if (ffmpeg_multiplex_audio && rd->ffcodecdata.audio_mixrate != 48000) {
+               if (ffmpeg_audio_codec != CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000) {
                        BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!");
                        return 0;
                }
        }
        
-       video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty);
-       printf("alloc video stream %p\n", video_stream);
-       if (!video_stream) {
-               BKE_report(reports, RPT_ERROR, "Error initializing video stream.");
-               return 0;
+       if (fmt->video_codec != CODEC_ID_NONE) {
+               video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty);
+               printf("alloc video stream %p\n", video_stream);
+               if (!video_stream) {
+                       BKE_report(reports, RPT_ERROR, "Error initializing video stream.");
+                       return 0;
+               }
        }
-       
-       if (ffmpeg_multiplex_audio) {
+
+       if (ffmpeg_audio_codec != CODEC_ID_NONE) {
                audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of);
                if (!audio_stream) {
                        BKE_report(reports, RPT_ERROR, "Error initializing audio stream.");
                        return 0;
                }
-               //XXX audiostream_play(SFRA, 0, 1);
        }
        if (av_set_parameters(of, NULL) < 0) {
                BKE_report(reports, RPT_ERROR, "Error setting output parameters.");
@@ -818,14 +824,14 @@ int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, Repo
 
        success = start_ffmpeg_impl(rd, rectx, recty, reports);
 
-       if(ffmpeg_multiplex_audio && audio_stream)
+       if(audio_stream)
        {
                AVCodecContext* c = get_codec_from_stream(audio_stream);
                AUD_DeviceSpecs specs;
                specs.channels = c->channels;
                specs.format = AUD_FORMAT_S16;
                specs.rate = rd->ffcodecdata.audio_mixrate;
-               audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->efra, rd->ffcodecdata.audio_volume);
+               audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume);
        }
 
        return success;
@@ -833,21 +839,13 @@ int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, Repo
 
 void end_ffmpeg(void);
 
-static void write_audio_frames()
+static void write_audio_frames(double to_pts)
 {
        int finished = 0;
 
-       while (ffmpeg_multiplex_audio && !finished) {
-               double a_pts = ((double)audio_stream->pts.val 
-                               * audio_stream->time_base.num 
-                               / audio_stream->time_base.den);
-               double v_pts = ((double)video_stream->pts.val 
-                               * video_stream->time_base.num 
-                               / video_stream->time_base.den);
-               
-               if (a_pts < v_pts) {
-                       write_audio_frame();
-               } else {
+       while (audio_stream && !finished) {
+               if((audio_time >= to_pts) ||
+                  (write_audio_frame())) {
                        finished = 1;
                }
        }
@@ -856,25 +854,31 @@ static void write_audio_frames()
 int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) 
 {
        AVFrame* avframe;
-       int success;
+       int success = 1;
 
        fprintf(stderr, "Writing frame %i, "
                "render width=%d, render height=%d\n", frame,
                rectx, recty);
 
-       write_audio_frames();
+// why is this done before writing the video frame and again at end_ffmpeg?
+//     write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base));
 
-       avframe= generate_video_frame((unsigned char*) pixels, reports);
-       success= (avframe && write_video_frame(rd, avframe, reports));
-
-       if (ffmpeg_autosplit) {
-               if (url_ftell(OUTFILE_PB) > FFMPEG_AUTOSPLIT_SIZE) {
-                       end_ffmpeg();
-                       ffmpeg_autosplit_count++;
-                       success &= start_ffmpeg_impl(rd, rectx, recty, reports);
+       if(video_stream)
+       {
+               avframe= generate_video_frame((unsigned char*) pixels, reports);
+               success= (avframe && write_video_frame(rd, avframe, reports));
+
+               if (ffmpeg_autosplit) {
+                       if (url_ftell(OUTFILE_PB) > FFMPEG_AUTOSPLIT_SIZE) {
+                               end_ffmpeg();
+                               ffmpeg_autosplit_count++;
+                               success &= start_ffmpeg_impl(rd, rectx, recty, reports);
+                       }
                }
        }
 
+       write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base));
+
        return success;
 }
 
@@ -885,9 +889,9 @@ void end_ffmpeg(void)
        
        fprintf(stderr, "Closing ffmpeg...\n");
 
-       if (audio_stream && video_stream) {
+/*     if (audio_stream) { SEE UPPER
                write_audio_frames();
-       }
+       }*/
 
        if(audio_mixdown_device)
        {
@@ -1259,8 +1263,8 @@ void ffmpeg_verify_image_type(RenderData *rd)
                }
        }
 
-       if(audio && rd->ffcodecdata.audio_codec <= 0) {
-               rd->ffcodecdata.audio_codec = CODEC_ID_MP2;
+       if(audio && rd->ffcodecdata.audio_codec < 0) {
+               rd->ffcodecdata.audio_codec = CODEC_ID_NONE;
                rd->ffcodecdata.audio_bitrate = 128;
        }
 }
index ed551e56fe940204eb1526960d9337eebdaeb00d..5938f9e6e2a49d345d26717a408eb0cc62062c00 100644 (file)
@@ -4138,14 +4138,14 @@ static void lib_link_scene(FileData *fd, Main *main)
                                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_handle= NULL;
+                                       seq->scene_sound = NULL;
                                        if(seq->type == SEQ_HD_SOUND)
                                                seq->type = SEQ_SOUND;
                                        else
                                                seq->sound= newlibadr(fd, sce->id.lib, seq->sound);
                                        if (seq->sound) {
                                                seq->sound->id.us++;
-                                               seq->sound_handle= sound_new_handle(sce, seq->sound, seq->startdisp, seq->enddisp, seq->startofs);
+                                               seq->scene_sound = sound_add_scene_sound(sce, seq, seq->startdisp, seq->enddisp, seq->startofs);
                                        }
                                }
                                seq->anim= 0;
@@ -4161,7 +4161,7 @@ static void lib_link_scene(FileData *fd, Main *main)
 #endif
 
                        if(sce->ed)
-                               seq_update_muting(sce->ed);
+                               seq_update_muting(sce, sce->ed);
                        
                        if(sce->nodetree) {
                                lib_link_ntree(fd, &sce->id, sce->nodetree);
@@ -4217,7 +4217,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        sce->obedit= NULL;
        sce->stats= 0;
 
-       memset(&sce->sound_handles, 0, sizeof(sce->sound_handles));
+       sound_create_scene(sce);
 
        /* set users to one by default, not in lib-link, this will increase it for compo nodes */
        sce->id.us= 1;
@@ -5200,6 +5200,7 @@ static void fix_relpaths_library(const char *basepath, Main *main)
 static void direct_link_sound(FileData *fd, bSound *sound)
 {
        sound->handle = NULL;
+       sound->playback_handle = NULL;
 
        sound->packedfile = direct_link_packedfile(fd, sound->packedfile);
        sound->newpackedfile = direct_link_packedfile(fd, sound->newpackedfile);
@@ -10565,6 +10566,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        /* put 2.50 compatibility code here until next subversion bump */
        {
                Scene *sce;
+               Sequence *seq;
 
                /* initialize to sane default so toggling on border shows something */
                for(sce = main->scene.first; sce; sce = sce->id.next) {
@@ -10575,6 +10577,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                sce->r.border.xmax= 1.0f;
                                sce->r.border.ymax= 1.0f;
                        }
+
+                       if((sce->r.ffcodecdata.flags & FFMPEG_MULTIPLEX_AUDIO) == 0)
+                               sce->r.ffcodecdata.audio_codec = 0x0; // CODEC_ID_NONE
+
+                       SEQ_BEGIN(sce->ed, seq) {
+                               seq->volume = 1.0f;
+                       }
+                       SEQ_END
                }
 
                /* sequencer changes */
index 82a2b615681006e5ea41efb19858a0f1ed382d11..8ac2bd5753a5ddb068cb8174ed745d0f68e2a3c1 100644 (file)
@@ -83,7 +83,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
        CFRA= RNA_int_get(op->ptr, "frame");
        
        /* do updates */
-       sound_scrub(C);
+       sound_seek_scene(C);
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
 }
 
index f7aeee14cb7a58bd9fb614f1df6b724f5a143ca0..53cd34c46f5b0534ed830a61ed54a93f84f4a5c9 100644 (file)
@@ -1513,9 +1513,11 @@ static int frame_offset_exec(bContext *C, wmOperator *op)
        int delta;
        
        delta = RNA_int_get(op->ptr, "delta");
-       
+
        CTX_data_scene(C)->r.cfra += delta;
        
+       sound_seek_scene(C);
+
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, CTX_data_scene(C));
        
        return OPERATOR_FINISHED;
@@ -2473,12 +2475,13 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
                        }
                }
                
+               if(sad->flag & ANIMPLAY_FLAG_JUMPED)
+                       sound_seek_scene(C);
+
                /* since we follow drawflags, we can't send notifier but tag regions ourselves */
 
                ED_update_for_newframe(C, 1);
                
-               sound_update_playing(C);
-
                for(sa= screen->areabase.first; sa; sa= sa->next) {
                        ARegion *ar;
                        for(ar= sa->regionbase.first; ar; ar= ar->next) {
@@ -2521,16 +2524,19 @@ static void SCREEN_OT_animation_step(wmOperatorType *ot)
 static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
 {
        bScreen *screen= CTX_wm_screen(C);
+       struct Scene* scene = CTX_data_scene(C);
        
        if(screen->animtimer) {
                /* stop playback now */
                ED_screen_animation_timer(C, 0, 0, 0);
-               sound_stop_all(C);
+               sound_stop_scene(scene);
        }
        else {
                ScrArea *sa= CTX_wm_area(C);
                int mode= (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1;
                int sync= -1;
+               if(mode == 1) // XXX only play audio forwards!?
+                       sound_play_scene(scene);
                
                if(RNA_property_is_set(op->ptr, "sync"))
                        sync= (RNA_boolean_get(op->ptr, "sync"));
index 064baafbd9561b40e8897587750a28d9bf355b6a..7398017a267b8648857e04655821973717699a06 100644 (file)
@@ -74,12 +74,12 @@ static int open_exec(bContext *C, wmOperator *op)
 
        sound = sound_new_file(CTX_data_main(C), path);
 
-       if (sound==NULL || sound->handle == NULL) {
+       if (sound==NULL || sound->playback_handle == NULL) {
                BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
                return OPERATOR_CANCELLED;
        }
 
-       info = AUD_getInfo(sound->handle);
+       info = AUD_getInfo(sound->playback_handle);
 
        if (info.specs.channels == AUD_CHANNELS_INVALID) {
                sound_delete(C, sound);
index 648a162890d57ebc66a5c068626c3d4f21744bc6..f8a12c566df8bfeaee195997a13568f612670e41 100644 (file)
@@ -77,7 +77,7 @@ static void graphview_cursor_apply(bContext *C, wmOperator *op)
         * NOTE: sync this part of the code with ANIM_OT_change_frame
         */
        CFRA= RNA_int_get(op->ptr, "frame");
-       sound_scrub(C);
+       sound_seek_scene(C);
        
        /* set the cursor value */
        sipo->cursorVal= RNA_float_get(op->ptr, "value");
index 359082c470abf648177b4d3dcd5581d36570063b..566abaa18c3edcffe6713ef24084b879f21ab10f 100644 (file)
@@ -215,7 +215,7 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
        else
                strcpy(seq->name+2, sce_seq->id.name+2);
        
-       calc_sequence_disp(seq);
+       calc_sequence_disp(scene, seq);
        sort_seq(scene);
        
        if (RNA_boolean_get(op->ptr, "replace_sel")) {
@@ -303,7 +303,7 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad
        }
 
        sort_seq(scene);
-       seq_update_muting(ed);
+       seq_update_muting(scene, ed);
 
        WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
 
@@ -428,7 +428,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
                }
        }
        
-       calc_sequence_disp(seq);
+       calc_sequence_disp(scene, seq);
 
        sort_seq(scene);
 
@@ -530,7 +530,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
 
        seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
 
-       calc_sequence(seq);
+       calc_sequence(scene, seq);
        
        /* basic defaults */
        seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
index b3682681fd70062e83c22f27c613936a570df225..5339acf74d927a1aa9cb1f114b236ec12fe4ba63 100644 (file)
@@ -49,7 +49,8 @@
 #include "BKE_sequencer.h"
 #include "BKE_scene.h"
 #include "BKE_utildefines.h"
+#include "BKE_sound.h"
+
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
 
@@ -172,6 +173,38 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, char *col)
        }
 }
 
+static void drawseqwave(Sequence *seq, float x1, float y1, float x2, float y2, float stepsize)
+{
+       /*
+       x1 is the starting x value to draw the wave,
+       x2 the end x value, same for y1 and y2
+       stepsize is width of a pixel.
+       */
+       if(seq->sound->cache)
+       {
+               int i;
+               int length = floor((x2-x1)/stepsize)+1;
+               float ymid = (y1+y2)/2;
+               float yscale = (y2-y1)/2;
+               float* samples = malloc(length * sizeof(float) * 2);
+               if(!samples)
+                       return;
+               if(sound_read_sound_buffer(seq->sound, samples, length) != length)
+               {
+                       free(samples);
+                       return;
+               }
+               glBegin(GL_LINES);
+               for(i = 0; i < length; i++)
+               {
+                       glVertex2f(x1+i*stepsize, ymid + samples[i * 2] * yscale);
+                       glVertex2f(x1+i*stepsize, ymid + samples[i * 2 + 1] * yscale);
+               }
+               glEnd();
+               free(samples);
+       }
+}
+
 static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, float x2, float y2)
 {
        /* Note, this used to use WHILE_SEQ, but it messes up the seq->depth value, (needed by transform when doing overlap checks)
@@ -557,6 +590,9 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, SpaceSeq *sseq, Sequence *
        x1= seq->startdisp;
        x2= seq->enddisp;
        
+       /* draw sound wave */
+       if(seq->type == SEQ_SOUND) drawseqwave(seq, x1, y1, x2, y2, (ar->v2d.cur.xmax - ar->v2d.cur.xmin)/ar->winx);
+
        get_seq_color3ubv(scene, seq, col);
        if (G.moving && (seq->flag & SELECT)) {
                if(seq->flag & SEQ_OVERLAP) {
index fb8f3b376838eb45e418fda0726604ba3243c186..4f19cfa86afa5cf9d31c3b33f215ec9bf66eb04a 100644 (file)
@@ -479,7 +479,7 @@ static void reload_sound_strip(Scene *scene, char *name)
                seqact->strip= seq->strip;
 
                seqact->len= seq->len;
-               calc_sequence(seqact);
+               calc_sequence(scene, seqact);
 
                seq->strip= 0;
                seq_free_sequence(scene, seq);
@@ -519,7 +519,7 @@ static void reload_image_strip(Scene *scene, char *name)
                seqact->strip= seq->strip;
 
                seqact->len= seq->len;
-               calc_sequence(seqact);
+               calc_sequence(scene, seqact);
 
                seq->strip= 0;
                seq_free_sequence(scene, seq);
@@ -857,8 +857,8 @@ static Sequence *dupli_seq(struct Scene *scene, Sequence *seq)
        } else if(seq->type == SEQ_SOUND) {
                seqn->strip->stripdata =
                                MEM_dupallocN(seq->strip->stripdata);
-               if(seq->sound_handle)
-                       seqn->sound_handle = sound_new_handle(scene, seqn->sound, seq->sound_handle->startframe, seq->sound_handle->endframe, seq->sound_handle->frameskip);
+               if(seq->scene_sound)
+                       seqn->scene_sound = sound_add_scene_sound(scene, seqn, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs);
 
                seqn->sound->id.us++;
        } else if(seq->type == SEQ_IMAGE) {
@@ -983,7 +983,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence * seq, int cutframe)
        }
        
        reload_sequence_new_file(scene, seq);
-       calc_sequence(seq);
+       calc_sequence(scene, seq);
 
        if (!skip_dup) {
                /* Duplicate AFTER the first change */
@@ -1022,7 +1022,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence * seq, int cutframe)
                }
                
                reload_sequence_new_file(scene, seqn);
-               calc_sequence(seqn);
+               calc_sequence(scene, seqn);
        }
        return seqn;
 }
@@ -1072,7 +1072,7 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence * seq, int cutframe)
                }
        }
        
-       calc_sequence(seq);
+       calc_sequence(scene, seq);
 
        if (!skip_dup) {
                /* Duplicate AFTER the first change */
@@ -1107,7 +1107,7 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence * seq, int cutframe)
                        seqn->startstill = 0;
                }
                
-               calc_sequence(seqn);
+               calc_sequence(scene, seqn);
        }
        return seqn;
 }
@@ -1161,7 +1161,7 @@ int insert_gap(Scene *scene, int gap, int cfra)
        SEQP_BEGIN(ed, seq) {
                if(seq->startdisp >= cfra) {
                        seq->start+= gap;
-                       calc_sequence(seq);
+                       calc_sequence(scene, seq);
                        done= 1;
                }
        }
@@ -1336,7 +1336,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
                                }
                                seq_tx_handle_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL);
                        }
-                       calc_sequence(seq);
+                       calc_sequence(scene, seq);
                }
        }
        SEQ_END
@@ -1351,11 +1351,11 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
                }
                else if(seq->type & SEQ_EFFECT) {
                        if(seq->seq1 && (seq->seq1->flag & SELECT)) 
-                               calc_sequence(seq);
+                               calc_sequence(scene, seq);
                        else if(seq->seq2 && (seq->seq2->flag & SELECT)) 
-                               calc_sequence(seq);
+                               calc_sequence(scene, seq);
                        else if(seq->seq3 && (seq->seq3->flag & SELECT)) 
-                               calc_sequence(seq);
+                               calc_sequence(scene, seq);
                }
        }
        SEQ_END;
@@ -1425,7 +1425,7 @@ static int sequencer_mute_exec(bContext *C, wmOperator *op)
                }
        }
        
-       seq_update_muting(ed);
+       seq_update_muting(scene, ed);
        WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
        
        return OPERATOR_FINISHED;
@@ -1476,7 +1476,7 @@ static int sequencer_unmute_exec(bContext *C, wmOperator *op)
                }
        }
        
-       seq_update_muting(ed);
+       seq_update_muting(scene, ed);
        WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
        
        return OPERATOR_FINISHED;
@@ -1623,8 +1623,6 @@ static int sequencer_refresh_all_exec(bContext *C, wmOperator *op)
 
        free_imbuf_seq(scene, &ed->seqbase, FALSE);
 
-       seqbase_sound_reload(scene, &ed->seqbase);
-
        WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
 
        return OPERATOR_FINISHED;
@@ -1840,7 +1838,7 @@ static int sequencer_delete_exec(bContext *C, wmOperator *op)
        /* updates lengths etc */
        seq= ed->seqbasep->first;
        while(seq) {
-               calc_sequence(seq);
+               calc_sequence(scene, seq);
                seq= seq->next;
        }
 
@@ -1848,7 +1846,7 @@ static int sequencer_delete_exec(bContext *C, wmOperator *op)
        ms= ed->metastack.last;
        while(ms) {
                ms->parseq->strip->len= 0;              /* force new alloc */
-               calc_sequence(ms->parseq);
+               calc_sequence(scene, ms->parseq);
                ms= ms->prev;
        }
 
@@ -1923,7 +1921,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
                                /* new stripdata */
                                strip_new->stripdata= se_new= MEM_callocN(sizeof(StripElem)*1, "stripelem");
                                strncpy(se_new->name, se->name, FILE_MAXFILE-1);
-                               calc_sequence(seq_new);
+                               calc_sequence(scene, seq_new);
                                seq_new->flag &= ~SEQ_OVERLAP;
                                if (seq_test_overlap(ed->seqbasep, seq_new)) {
                                        shuffle_seq(ed->seqbasep, seq_new, scene);
@@ -2011,7 +2009,7 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *op)
 
                /* recalc all: the meta can have effects connected to it */
                for(seq= ed->seqbasep->first; seq; seq= seq->next)
-                       calc_sequence(seq);
+                       calc_sequence(scene, seq);
 
                active_seq_set(scene, ms->parseq);
 
@@ -2022,7 +2020,7 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *op)
 
        }
 
-       seq_update_muting(ed);
+       seq_update_muting(scene, ed);
        WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
 
        return OPERATOR_FINISHED;
@@ -2081,7 +2079,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
                seq= next;
        }
        seqm->machine= channel_max;
-       calc_sequence(seqm);
+       calc_sequence(scene, seqm);
 
        seqm->strip= MEM_callocN(sizeof(Strip), "metastrip");
        seqm->strip->len= seqm->len;
@@ -2091,7 +2089,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
 
        if( seq_test_overlap(ed->seqbasep, seqm) ) shuffle_seq(ed->seqbasep, seqm, scene);
 
-       seq_update_muting(ed);
+       seq_update_muting(scene, ed);
 
        seqUniqueName(scene->ed->seqbasep, seqm);
 
@@ -2165,7 +2163,7 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *op)
        SEQ_END;
 
        sort_seq(scene);
-       seq_update_muting(ed);
+       seq_update_muting(scene, ed);
 
        WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene);
 
@@ -2521,13 +2519,13 @@ void SEQUENCER_OT_previous_edit(wmOperatorType *ot)
        /* properties */
 }
 
-static void swap_sequence(Sequence* seqa, Sequence* seqb)
+static void swap_sequence(Scene* scene, Sequence* seqa, Sequence* seqb)
 {
        int gap = seqb->startdisp - seqa->enddisp;
        seqb->start = seqa->start;
-       calc_sequence(seqb);
+       calc_sequence(scene, seqb);
        seqa->start = seqb->enddisp + gap;
-       calc_sequence(seqa);
+       calc_sequence(scene, seqa);
 }
 
 static Sequence* sequence_find_parent(Scene* scene, Sequence* child)
@@ -2571,17 +2569,17 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op)
 
                switch (side) {
                        case SEQ_SIDE_LEFT: 
-                               swap_sequence(seq, active_seq);
+                               swap_sequence(scene, seq, active_seq);
                                break;
                        case SEQ_SIDE_RIGHT: 
-                               swap_sequence(active_seq, seq);
+                               swap_sequence(scene, active_seq, seq);
                                break;
                }
 
                // XXX - should be a generic function
                for(iseq= scene->ed->seqbasep->first; iseq; iseq= iseq->next) {
                        if((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) {
-                               calc_sequence(iseq);
+                               calc_sequence(scene, iseq);
                        }
                }
 
@@ -2682,9 +2680,9 @@ static void seq_del_sound(Scene *scene, Sequence *seq)
                        seq_del_sound(scene, iseq);
                }
        }
-       else if(seq->sound_handle) {
-               sound_delete_handle(scene, seq->sound_handle);
-               seq->sound_handle= NULL;
+       else if(seq->scene_sound) {
+               sound_remove_scene_sound(scene, seq->scene_sound);
+               seq->scene_sound = NULL;
        }
 }
 
@@ -2733,19 +2731,19 @@ void SEQUENCER_OT_copy(wmOperatorType *ot)
        /* properties */
 }
 
-static void seq_offset(Sequence *seq, int ofs)
+static void seq_offset(Scene *scene, Sequence *seq, int ofs)
 {
        if(seq->type == SEQ_META) {
                Sequence *iseq;
                for(iseq= seq->seqbase.first; iseq; iseq= iseq->next) {
-                       seq_offset(iseq, ofs);
+                       seq_offset(scene, iseq, ofs);
                }
        }
        else {
                seq->start += ofs;
        }
 
-       calc_sequence_disp(seq);
+       calc_sequence_disp(scene, seq);
 }
 
 static int sequencer_paste_exec(bContext *C, wmOperator *op)
@@ -2764,7 +2762,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op)
        /* transform pasted strips before adding */
        if(ofs) {
                for(iseq= new.first; iseq; iseq= iseq->next) {
-                       seq_offset(iseq, ofs);
+                       seq_offset(scene, iseq, ofs);
                }
        }
 
index 15b812dc1f21d76f38e2c3ec3304ea1a2b0eb472..e93e9c42e10ef455e9811922e5b8b13e77db4ab6 100644 (file)
@@ -2369,10 +2369,10 @@ void flushTransSeq(TransInfo *t)
                                /* Calculate this strip and all nested strips
                                 * children are ALWAYS transformed first
                                 * so we dont need to do this in another loop. */
-                               calc_sequence(seq);
+                               calc_sequence(t->scene, seq);
                        }
                        else {
-                               calc_sequence_disp(seq);
+                               calc_sequence_disp(t->scene, seq);
                        }
                }
                seq_prev= seq;
@@ -2404,7 +2404,7 @@ void flushTransSeq(TransInfo *t)
 
                while(seq) {
                        if (seq->type == SEQ_META && seq->flag & SELECT)
-                               calc_sequence(seq);
+                               calc_sequence(t->scene, seq);
                        seq= seq->next;
                }
        }
@@ -4105,9 +4105,9 @@ static void freeSeqData(TransInfo *t)
                        for(seq= seqbasep->first; seq; seq= seq->next) {
                                /* We might want to build a list of effects that need to be updated during transform */
                                if(seq->type & SEQ_EFFECT) {
-                                       if              (seq->seq1 && seq->seq1->flag & SELECT) calc_sequence(seq);
-                                       else if (seq->seq2 && seq->seq2->flag & SELECT) calc_sequence(seq);
-                                       else if (seq->seq3 && seq->seq3->flag & SELECT) calc_sequence(seq);
+                                       if              (seq->seq1 && seq->seq1->flag & SELECT) calc_sequence(t->scene, seq);
+                                       else if (seq->seq2 && seq->seq2->flag & SELECT) calc_sequence(t->scene, seq);
+                                       else if (seq->seq3 && seq->seq3->flag & SELECT) calc_sequence(t->scene, seq);
                                }
                        }
 
@@ -4118,7 +4118,7 @@ static void freeSeqData(TransInfo *t)
                        for(a=0; a<t->total; a++, td++) {
                                seq= ((TransDataSeq *)td->extra)->seq;
                                if ((seq != seq_prev) && (seq->depth==0)) {
-                                       calc_sequence_disp(seq);
+                                       calc_sequence_disp(t->scene, seq);
                                }
                                seq_prev= seq;
                        }
index 63d3e7642637e53990538adcc892a6317fafe324..204af647b3a848c221bce88700bb9f978bc2ee1e 100644 (file)
@@ -758,7 +758,8 @@ typedef struct Scene {
        ListBase markers;
        ListBase transform_spaces;
        
-       ListBase sound_handles;
+       void *sound_scene;
+       void *sound_scene_handle;
        
        /* none of the dependancy graph  vars is mean to be saved */
        struct  DagForest *theDag;
@@ -1078,7 +1079,7 @@ typedef struct Scene {
 #define AUDIO_SYNC             2
 #define AUDIO_SCRUB            4
 
-#define FFMPEG_MULTIPLEX_AUDIO  1
+#define FFMPEG_MULTIPLEX_AUDIO  1 /* deprecated, you can choose none as audiocodec now */
 #define FFMPEG_AUTOSPLIT_OUTPUT 2
 
 /* Paint.flags */
index 0b45d62e347958884e9a8b8e78191213f209dff2..c93625e9c27a55ca12aea53d7a5f3cf7fe2e4572 100644 (file)
@@ -161,7 +161,9 @@ typedef struct Sequence {
        ListBase seqbase;       /* list of strips for metastrips */
 
        struct bSound *sound;   /* the linked "bSound" object */
-       struct SoundHandle *sound_handle;
+       void *scene_sound;
+       float volume, pad;
+
        float level, pan;       /* level in dB (0=full), pan -1..1 */
        int scenenr;          /* for scene selection */
        float strobe;
index 55b48e4aacd712dfbcc7186d51c7c02a3eb835fb..c0b8657618d747c5101a29d063834ba675888a58 100644 (file)
@@ -41,21 +41,6 @@ struct Ipo;
 struct PackedFile;
 struct SpaceLink;
 
-// runtime only - no saving
-typedef struct SoundHandle {
-       struct SoundHandle *next, *prev;
-       struct bSound *source;
-       void *handle;
-       int state;
-       int startframe;
-       int endframe;
-       int frameskip;
-       int mute;
-       int changed;
-       float volume;
-       float pad;
-} SoundHandle;
-
 typedef struct Sound3D
 {
        float min_gain;
@@ -98,19 +83,21 @@ typedef struct bSound {
        float max_gain;
        float distance;
        int flags;
+       int pad;
 
 /**    currently       int type;
        struct bSound *child_sound;*/
 
        /**
-        * Whether the sound has been changed and must be restarted if playing.
+        * The audaspace handle for cache.
         */
-       int changed;
+       void *cache;
 
        /**
-        * The audaspace handle for cache.
+        * The audaspace handle that should actually be played back.
+        * Should be cache if cache != NULL; otherwise it's handle
         */
-       void *cache;
+       void *playback_handle;
 
 /**    XXX unused currently    // SOUND_TYPE_LIMITER
        float start, end;*/
index 11aff7922c7e13724592fcdeb0318b87f71a76bd..452745ba364eeec3e5a6bd639e008d25367d79ce 100644 (file)
@@ -107,6 +107,7 @@ EnumPropertyItem snap_element_items[] = {
 #include "BKE_depsgraph.h"
 #include "BKE_image.h"
 #include "BKE_mesh.h"
+#include "BKE_sound.h"
 
 #include "BLI_threads.h"
 #include "BLI_editVert.h"
@@ -287,10 +288,11 @@ static void rna_Scene_preview_range_end_frame_set(PointerRNA *ptr, int value)
        data->r.pefra= value;
 }
 
-static void rna_Scene_frame_update(Main *bmain, Scene *unused, PointerRNA *ptr)
+static void rna_Scene_frame_update(bContext *C, PointerRNA *ptr)
 {
        //Scene *scene= ptr->id.data;
        //ED_update_for_newframe(C);
+       sound_seek_scene(C);
 }
 
 static int rna_Scene_active_keying_set_editable(PointerRNA *ptr)
@@ -1675,12 +1677,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 #ifdef WITH_FFMPEG
                {R_H264, "H264", ICON_FILE_MOVIE, "H.264", ""},
                {R_XVID, "XVID", ICON_FILE_MOVIE, "Xvid", ""},
-               // XXX broken
-#if 0
-#ifdef WITH_OGG
                {R_THEORA, "THEORA", ICON_FILE_MOVIE, "Ogg Theora", ""},
-#endif
-#endif
                {R_FFMPEG, "FFMPEG", ICON_FILE_MOVIE, "FFMpeg", ""},
 #endif
                {R_FRAMESERVER, "FRAMESERVER", ICON_FILE_SCRIPT, "Frame Server", ""},
@@ -1731,16 +1728,15 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
                {FFMPEG_DV, "DV", 0, "DV", ""},
                {FFMPEG_H264, "H264", 0, "H.264", ""},
                {FFMPEG_XVID, "XVID", 0, "Xvid", ""},
-               // XXX broken
-#if 0
-#ifdef WITH_OGG
                {FFMPEG_OGG, "OGG", 0, "Ogg", ""},
-#endif
-#endif
+               {FFMPEG_MKV, "MKV", 0, "Matroska", ""},
                {FFMPEG_FLV, "FLASH", 0, "Flash", ""},
+               {FFMPEG_WAV, "WAV", 0, "Wav", ""},
+               {FFMPEG_MP3, "MP3", 0, "Mp3", ""},
                {0, NULL, 0, NULL, NULL}};
-               
+
        static EnumPropertyItem ffmpeg_codec_items[] = {
+               {CODEC_ID_NONE, "NONE", 0, "None", ""},
                {CODEC_ID_MPEG1VIDEO, "MPEG1", 0, "MPEG-1", ""},
                {CODEC_ID_MPEG2VIDEO, "MPEG2", 0, "MPEG-2", ""},
                {CODEC_ID_MPEG4, "MPEG4", 0, "MPEG-4(divx)", ""},
@@ -1748,18 +1744,18 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
                {CODEC_ID_DVVIDEO, "DV", 0, "DV", ""},
                {CODEC_ID_H264, "H264", 0, "H.264", ""},
                {CODEC_ID_XVID, "XVID", 0, "Xvid", ""},
-#ifdef WITH_OGG
                {CODEC_ID_THEORA, "THEORA", 0, "Theora", ""},
-#endif
                {CODEC_ID_FLV1, "FLASH", 0, "Flash Video", ""},
                {0, NULL, 0, NULL, NULL}};
-               
+
        static EnumPropertyItem ffmpeg_audio_codec_items[] = {
+               {CODEC_ID_NONE, "NONE", 0, "None", ""},
                {CODEC_ID_MP2, "MP2", 0, "MP2", ""},
                {CODEC_ID_MP3, "MP3", 0, "MP3", ""},
                {CODEC_ID_AC3, "AC3", 0, "AC3", ""},
                {CODEC_ID_AAC, "AAC", 0, "AAC", ""},
                {CODEC_ID_VORBIS, "VORBIS", 0, "Vorbis", ""},
+               {CODEC_ID_FLAC, "FLAC", 0, "FLAC", ""},
                {CODEC_ID_PCM_S16LE, "PCM", 0, "PCM", ""},
                {0, NULL, 0, NULL, NULL}};
 #endif
@@ -1992,7 +1988,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
        RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
        
        /* FFMPEG Audio*/
-       
        prop= RNA_def_property(srna, "ffmpeg_audio_codec", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_bitflag_sdna(prop, NULL, "ffcodecdata.audio_codec");
        RNA_def_property_enum_items(prop, ffmpeg_audio_codec_items);
@@ -2005,11 +2000,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Bitrate", "Audio bitrate(kb/s)");
        RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
        
-       prop= RNA_def_property(srna, "ffmpeg_multiplex_audio", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "ffcodecdata.flags", FFMPEG_MULTIPLEX_AUDIO);
-       RNA_def_property_ui_text(prop, "Multiplex Audio", "Interleave audio with the output video");
-       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
-
        prop= RNA_def_property(srna, "ffmpeg_audio_mixrate", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "ffcodecdata.audio_mixrate");
        RNA_def_property_range(prop, 8000, 192000);
@@ -2636,6 +2626,7 @@ void RNA_def_scene(BlenderRNA *brna)
        RNA_def_property_int_sdna(prop, NULL, "r.cfra");
        RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
        RNA_def_property_ui_text(prop, "Current Frame", "");
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
        RNA_def_property_update(prop, NC_SCENE|ND_FRAME, "rna_Scene_frame_update");
        
        prop= RNA_def_property(srna, "start_frame", PROP_INT, PROP_TIME);
index 7ffaa4d478bbb32117dee5f7f36af4b0ff1f8083..00a156cf820e073b4ab365b1a42ba987c32ce2c6 100644 (file)
@@ -93,7 +93,7 @@ static void rna_Sequence_frame_change_update(Scene *scene, Sequence *seq)
 {
        Editing *ed= seq_give_editing(scene, FALSE);
        ListBase *seqbase= seq_seqbase(&ed->seqbase, seq);
-       calc_sequence_disp(seq);
+       calc_sequence_disp(scene, seq);
 
        if(seq_test_overlap(seqbase, seq)) {
                shuffle_seq(seqbase, seq, scene); // XXX - BROKEN!, uses context seqbasep
@@ -351,14 +351,14 @@ static void rna_Sequence_update(Main *bmain, Scene *scene, PointerRNA *ptr)
        free_imbuf_seq(scene, &ed->seqbase, FALSE);
 
        if(RNA_struct_is_a(ptr->type, &RNA_SoundSequence))
-               seq_update_sound(ptr->data);
+               seq_update_sound(scene, ptr->data);
 }
 
 static void rna_Sequence_mute_update(Main *bmain, Scene *scene, PointerRNA *ptr)
 {
        Editing *ed= seq_give_editing(scene, FALSE);
 
-       seq_update_muting(ed);
+       seq_update_muting(scene, ed);
        rna_Sequence_update(bmain, scene, ptr);
 }
 
@@ -606,24 +606,28 @@ static void rna_def_sequence(BlenderRNA *brna)
        prop= RNA_def_property(srna, "length", PROP_INT, PROP_TIME);
        RNA_def_property_int_sdna(prop, NULL, "len");
        RNA_def_property_range(prop, 1, MAXFRAME);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_ui_text(prop, "Length", "The length of the contents of this strip before the handles are applied");
        RNA_def_property_int_funcs(prop, "rna_Sequence_length_get", "rna_Sequence_length_set",NULL);
        RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
        
        prop= RNA_def_property(srna, "start_frame", PROP_INT, PROP_TIME);
        RNA_def_property_int_sdna(prop, NULL, "start");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_ui_text(prop, "Start Frame", "");
        RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_start_frame_set",NULL); // overlap tests and calc_seq_disp
        RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
        
        prop= RNA_def_property(srna, "start_frame_final", PROP_INT, PROP_TIME);
        RNA_def_property_int_sdna(prop, NULL, "startdisp");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_ui_text(prop, "Start Frame", "Start frame displayed in the sequence editor after offsets are applied, setting this is equivilent to moving the handle, not the actual start frame.");
        RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_start_frame_final_set", NULL); // overlap tests and calc_seq_disp
        RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
 
        prop= RNA_def_property(srna, "end_frame_final", PROP_INT, PROP_TIME);
        RNA_def_property_int_sdna(prop, NULL, "enddisp");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_ui_text(prop, "End Frame", "End frame displayed in the sequence editor after offsets are applied.");
        RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_end_frame_final_set", NULL); // overlap tests and calc_seq_disp
        RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
@@ -949,6 +953,12 @@ static void rna_def_sound(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Sound", "Sound datablock used by this sequence.");
        RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
 
+       prop= RNA_def_property(srna, "volume", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "volume");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Volume", "Playback volume of the sound");
+       RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
+
        prop= RNA_def_property(srna, "filename", PROP_STRING, PROP_FILEPATH);
        RNA_def_property_string_sdna(prop, NULL, "strip->stripdata->name");
        RNA_def_property_ui_text(prop, "Filename", "");
@@ -961,14 +971,6 @@ static void rna_def_sound(BlenderRNA *brna)
        RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
        
        rna_def_input(srna);
-       
-       RNA_def_struct_sdna_from(srna, "SoundHandle", "sound_handle");
-       
-       prop= RNA_def_property(srna, "volume", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_float_sdna(prop, NULL, "volume");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
-       RNA_def_property_ui_text(prop, "Volume", "Playback volume of the sound");
-       RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
 }
 
 static void rna_def_effect(BlenderRNA *brna)
index a06454760630159c7f1290b76aadc88c61bb14cb..29332effa293f80e620ea42788afd0cfce3aa759 100644 (file)
@@ -394,7 +394,7 @@ void BL_ConvertActuators(char* maggiename,
                                                                                "\" has no sound datablock." << std::endl;
                                        }
                                        else
-                                               snd_sound = sound->cache ? sound->cache : sound->handle;
+                                               snd_sound = sound->playback_handle;
                                        KX_SoundActuator* tmpsoundact =
                                                new KX_SoundActuator(gameobj,
                                                snd_sound,
index 40d2339b81630453ed86520085a8e8da413f7ed6..bf7d890f53bc770194a21256550081949151c42e 100644 (file)
@@ -187,7 +187,7 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
                        case KX_SOUNDACT_LOOPBIDIRECTIONAL:
                                {
                                        // stop the looping so that the sound stops when it finished
-                                       AUD_stopLoop(m_handle);
+                                       AUD_setLoop(m_handle, 0, -1);
                                        break;
                                }
                        default: