2.5 Audio:

- 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
This commit is contained in:
Joerg Mueller 2010-02-07 23:41:17 +00:00
parent 2f72b91a54
commit 9827a3e9ea
37 changed files with 1108 additions and 514 deletions

@ -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);

@ -46,6 +46,11 @@ private:
*/
int m_loop;
/**
* The left samples.
*/
int m_samples;
public:
/**
* Creates a new loop reader.

@ -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;

@ -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;
}

@ -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

@ -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);

@ -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.

@ -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);
}

@ -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

@ -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;
}

@ -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

@ -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);

@ -294,7 +294,11 @@ typedef struct
union
{
// loop reader
int loopcount;
struct
{
int loopcount;
float time;
};
// volume reader
float volume;

@ -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()

@ -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);

@ -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);
struct SoundHandle* sound_new_handle(struct Scene *scene, struct bSound* sound, int startframe, int endframe, int frameskip);
void sound_delete_handle(struct Scene *scene, struct SoundHandle *handle);
void sound_update_playing(struct bContext *C);
void sound_scrub(struct bContext *C);
#ifdef AUD_CAPI
AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, int end, float volume);
AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume);
#endif
void sound_stop_all(struct bContext *C);
void sound_create_scene(struct Scene *scene);
void sound_destroy_scene(struct Scene *scene);
void* sound_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip);
void sound_remove_scene_sound(struct Scene *scene, void* handle);
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);
int sound_read_sound_buffer(struct bSound* sound, float* buffer, int length);
#endif

@ -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

@ -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;
}

@ -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) {

@ -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);
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_setDeviceVolume(mixdown, volume);
BLI_addtail(handles, handle);
AUD_playDevice(mixdown, scene->sound_scene, start / FPS);
return handle;
return mixdown;
}
void sound_delete_handle(struct Scene *scene, struct SoundHandle *handle)
void sound_create_scene(struct Scene *scene)
{
if(handle == NULL)
return;
if(handle->handle)
AUD_stop(handle->handle);
BLI_freelinkN(&scene->sound_handles, handle);
scene->sound_scene = AUD_createSequencer(scene, (AUD_volumeFunction)&sound_get_volume);
}
void sound_stop_all(struct bContext *C)
void sound_destroy_scene(struct Scene *scene)
{
SoundHandle *handle;
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;
}
}
if(scene->sound_scene_handle)
AUD_stop(scene->sound_scene_handle);
if(scene->sound_scene)
AUD_destroySequencer(scene->sound_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)
{
SoundHandle *handle;
Scene* scene = CTX_data_scene(C);
int cfra = CFRA;
float fps = FPS;
int action;
return AUD_addSequencer(scene->sound_scene, &(sequence->sound->playback_handle), startframe / FPS, endframe / FPS, frameskip / FPS, sequence);
}
void sound_remove_scene_sound(struct Scene *scene, void* handle)
{
AUD_removeSequencer(scene->sound_scene, handle);
}
void sound_mute_scene_sound(struct Scene *scene, void* handle, char mute)
{
AUD_muteSequencer(scene->sound_scene, handle, mute);
}
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_start_play_scene(struct Scene *scene)
{
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(!scene->sound_scene_handle || AUD_getStatus(scene->sound_scene_handle) == AUD_STATUS_INVALID)
sound_start_play_scene(scene);
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);
}
}
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;
AUD_pause(scene->sound_scene_handle);
}
void sound_seek_scene(struct bContext *C)
{
struct Scene *scene = CTX_data_scene(C);
AUD_lock();
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);
}
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_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);
AUD_unlock();
}
AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, int end, float volume)
int sound_read_sound_buffer(bSound* sound, float* buffer, int length)
{
AUD_Device* mixdown = AUD_openReadDevice(specs);
SoundHandle *handle;
float fps = FPS;
AUD_Sound *limiter, *delayer;
int frameskip, s, e;
end++;
AUD_setDeviceVolume(mixdown, volume);
for(handle = scene->sound_handles.first; handle; handle = handle->next)
{
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);
}
}
return mixdown;
AUD_readSound(sound->cache, buffer, length);
}

@ -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(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);
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;
}
}

@ -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 */

@ -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);
}

@ -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"));

@ -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);

@ -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");

@ -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");

@ -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) {

@ -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);
}
}

@ -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;
}

@ -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 */

@ -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;

@ -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,20 +83,22 @@ 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.
*/
int changed;
/**
* The audaspace handle for cache.
*/
void *cache;
/**
* The audaspace handle that should actually be played back.
* Should be cache if cache != NULL; otherwise it's handle
*/
void *playback_handle;
/** XXX unused currently // SOUND_TYPE_LIMITER
float start, end;*/
} bSound;

@ -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);

@ -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)

@ -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,

@ -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: