forked from bartvdbraak/blender
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:
parent
2f72b91a54
commit
9827a3e9ea
@ -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.
|
||||
|
109
intern/audaspace/intern/AUD_SequencerFactory.cpp
Normal file
109
intern/audaspace/intern/AUD_SequencerFactory.cpp
Normal file
@ -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);
|
||||
}
|
77
intern/audaspace/intern/AUD_SequencerFactory.h
Normal file
77
intern/audaspace/intern/AUD_SequencerFactory.h
Normal file
@ -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
|
245
intern/audaspace/intern/AUD_SequencerReader.cpp
Normal file
245
intern/audaspace/intern/AUD_SequencerReader.cpp
Normal file
@ -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;
|
||||
}
|
102
intern/audaspace/intern/AUD_SequencerReader.h
Normal file
102
intern/audaspace/intern/AUD_SequencerReader.h
Normal file
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user