forked from bartvdbraak/blender
3D Audio GSoC:
Implemented basic audio animation. * AnimatableProperty: Propper cache writing and spline interpolation for reading (the solution for stair steps in audio animation) * Animatable properties so far are: volume, pitch, panning * Users note: Changing the pitch of a sound results in wrong seeking, due to the resulting playback length difference. * Users note: Panning only works for mono sources, values are in the range [-2..2], this basically controls the angle of the sound, 0 is front, -1 left, 1 right and 2 and -2 are back. Typical stereo panning only supports [-1..1]. * Disabled animation of audio related ffmpeg output parameters. * Scene Audio Panel: 3D Listener settings also for Renderer, new Volume property (animatable!), Update/Bake buttons for animation problems, moved sampling rate and channel count here
This commit is contained in:
parent
90b64737f1
commit
bd6ca0570e
@ -32,6 +32,7 @@
|
||||
#include "AUD_AnimateableProperty.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
AUD_AnimateableProperty::AUD_AnimateableProperty(int count) :
|
||||
AUD_Buffer(count * sizeof(float)), m_count(count), m_isAnimated(false), m_changed(false)
|
||||
@ -78,16 +79,85 @@ void AUD_AnimateableProperty::write(const float* data, int position, int count)
|
||||
lock();
|
||||
|
||||
m_isAnimated = true;
|
||||
m_changed = true;
|
||||
|
||||
int pos = getSize() / (sizeof(float) * m_count);
|
||||
|
||||
assureSize((count + position) * m_count * sizeof(float), true);
|
||||
memcpy(getBuffer() + position * m_count, data, count * m_count * sizeof(float));
|
||||
|
||||
float* buf = getBuffer();
|
||||
|
||||
memcpy(buf + position * m_count, data, count * m_count * sizeof(float));
|
||||
|
||||
for(int i = pos; i < position; i++)
|
||||
memcpy(buf + i * m_count, buf + (pos - 1) * m_count, m_count * sizeof(float));
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
const float* AUD_AnimateableProperty::read(int position) const
|
||||
void AUD_AnimateableProperty::read(float position, float* out)
|
||||
{
|
||||
return getBuffer() + position * m_count;
|
||||
lock();
|
||||
|
||||
if(!m_isAnimated)
|
||||
{
|
||||
memcpy(out, getBuffer(), m_count * sizeof(float));
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
float last = (getSize() / (sizeof(float) * m_count) - 1);
|
||||
float t = position - floor(position);
|
||||
|
||||
if(position > last)
|
||||
{
|
||||
position = last;
|
||||
t = 0;
|
||||
}
|
||||
|
||||
if(t == 0)
|
||||
{
|
||||
memcpy(out, getBuffer() + int(floor(position)) * m_count, m_count * sizeof(float));
|
||||
}
|
||||
else
|
||||
{
|
||||
int pos = int(floor(position)) * m_count;
|
||||
float t2 = t * t;
|
||||
float t3 = t2 * t;
|
||||
float m0, m1;
|
||||
float* p0;
|
||||
float* p1 = getBuffer() + pos;
|
||||
float* p2;
|
||||
float* p3;
|
||||
|
||||
if(pos == 0)
|
||||
p0 = p1;
|
||||
else
|
||||
p0 = p1 - m_count;
|
||||
|
||||
if(pos > last)
|
||||
{
|
||||
p3 = p2 = p1;
|
||||
}
|
||||
else
|
||||
{
|
||||
p2 = p1 + m_count;
|
||||
if(pos + m_count > last)
|
||||
p3 = p2;
|
||||
else
|
||||
p3 = p2 + m_count;
|
||||
}
|
||||
|
||||
for(int i = 0; i < m_count; i++)
|
||||
{
|
||||
m0 = (p2[i] - p0[i]) / 2.0f;
|
||||
m1 = (p3[i] - p1[i]) / 2.0f;
|
||||
|
||||
out[i] = (2 * t3 - 3 * t2 + 1) * p0[i] + (-2 * t3 + 3 * t2) * p1[i] +
|
||||
(t3 - 2 * t2 + t) * m0 + (t3 - t2) * m1;
|
||||
}
|
||||
}
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
bool AUD_AnimateableProperty::isAnimated() const
|
||||
@ -97,6 +167,9 @@ bool AUD_AnimateableProperty::isAnimated() const
|
||||
|
||||
bool AUD_AnimateableProperty::hasChanged()
|
||||
{
|
||||
if(m_isAnimated)
|
||||
return true;
|
||||
|
||||
bool result = m_changed;
|
||||
m_changed = false;
|
||||
return result;
|
||||
|
@ -84,7 +84,7 @@ public:
|
||||
|
||||
void write(const float* data, int position, int count);
|
||||
|
||||
const float* read(int position) const;
|
||||
void read(float position, float* out);
|
||||
|
||||
bool isAnimated() const;
|
||||
|
||||
|
@ -938,6 +938,24 @@ void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound)
|
||||
(*entry)->setSound(AUD_Sound());
|
||||
}
|
||||
|
||||
void AUD_setSequenceAnimData(AUD_SEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated)
|
||||
{
|
||||
AUD_AnimateableProperty* prop = (*entry)->getAnimProperty(type);
|
||||
if(animated)
|
||||
prop->write(data, frame, 1);
|
||||
else
|
||||
prop->write(data);
|
||||
}
|
||||
|
||||
void AUD_setSequencerAnimData(AUD_Sound* sequencer, AUD_AnimateablePropertyType type, int frame, float* data, char animated)
|
||||
{
|
||||
AUD_AnimateableProperty* prop = ((AUD_SequencerFactory*)sequencer->get())->getAnimProperty(type);
|
||||
if(animated)
|
||||
prop->write(data, frame, 1);
|
||||
else
|
||||
prop->write(data);
|
||||
}
|
||||
|
||||
void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer)
|
||||
{
|
||||
((AUD_SequencerFactory*)sequencer->get())->setSpecs(AUD_device->getSpecs().specs);
|
||||
|
@ -471,6 +471,10 @@ extern void AUD_muteSequence(AUD_SEntry* entry, char mute);
|
||||
|
||||
extern void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound);
|
||||
|
||||
extern void AUD_setSequenceAnimData(AUD_SEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated);
|
||||
|
||||
extern void AUD_setSequencerAnimData(AUD_Sound* sequencer, AUD_AnimateablePropertyType type, int frame, float* data, char animated);
|
||||
|
||||
extern void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer);
|
||||
|
||||
extern void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs);
|
||||
|
@ -45,7 +45,7 @@ AUD_SequencerEntry::AUD_SequencerEntry(AUD_Reference<AUD_IFactory> sound, float
|
||||
m_end(end),
|
||||
m_skip(skip),
|
||||
m_muted(false),
|
||||
m_relative(false),
|
||||
m_relative(true),
|
||||
m_volume_max(1.0f),
|
||||
m_volume_min(0),
|
||||
m_distance_max(std::numeric_limits<float>::max()),
|
||||
@ -72,10 +72,13 @@ void AUD_SequencerEntry::setSound(AUD_Reference<AUD_IFactory> sound)
|
||||
|
||||
void AUD_SequencerEntry::move(float begin, float end, float skip)
|
||||
{
|
||||
if(m_begin != begin || m_skip != skip || m_end != end)
|
||||
{
|
||||
m_begin = begin;
|
||||
m_skip = skip;
|
||||
m_end = end;
|
||||
m_pos_status++;
|
||||
}
|
||||
}
|
||||
|
||||
void AUD_SequencerEntry::mute(bool mute)
|
||||
@ -88,6 +91,25 @@ int AUD_SequencerEntry::getID() const
|
||||
return m_id;
|
||||
}
|
||||
|
||||
AUD_AnimateableProperty* AUD_SequencerEntry::getAnimProperty(AUD_AnimateablePropertyType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case AUD_AP_VOLUME:
|
||||
return &m_volume;
|
||||
case AUD_AP_PITCH:
|
||||
return &m_pitch;
|
||||
case AUD_AP_PANNING:
|
||||
return &m_panning;
|
||||
case AUD_AP_LOCATION:
|
||||
return &m_location;
|
||||
case AUD_AP_ORIENTATION:
|
||||
return &m_orientation;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool AUD_SequencerEntry::isRelative()
|
||||
{
|
||||
return m_relative;
|
||||
|
@ -76,6 +76,8 @@ public:
|
||||
|
||||
int getID() const;
|
||||
|
||||
AUD_AnimateableProperty* getAnimProperty(AUD_AnimateablePropertyType type);
|
||||
|
||||
/**
|
||||
* Checks whether the source location, velocity and orientation are relative
|
||||
* to the listener.
|
||||
|
@ -48,6 +48,8 @@ AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, float fps, bool mute
|
||||
{
|
||||
AUD_Quaternion q;
|
||||
m_orientation.write(q.get());
|
||||
float f = 1;
|
||||
m_volume.write(&f);
|
||||
}
|
||||
|
||||
AUD_SequencerFactory::~AUD_SequencerFactory()
|
||||
|
@ -66,7 +66,7 @@ void AUD_SequencerHandle::stop()
|
||||
m_handle->stop();
|
||||
}
|
||||
|
||||
void AUD_SequencerHandle::update(float position)
|
||||
void AUD_SequencerHandle::update(float position, float frame)
|
||||
{
|
||||
if(!m_handle.isNull())
|
||||
{
|
||||
@ -111,7 +111,16 @@ void AUD_SequencerHandle::update(float position)
|
||||
m_status = m_entry->m_status;
|
||||
}
|
||||
|
||||
// AUD_XXX TODO: Animation data
|
||||
float value;
|
||||
|
||||
m_entry->m_volume.read(frame, &value);
|
||||
m_handle->setVolume(value);
|
||||
m_entry->m_pitch.read(frame, &value);
|
||||
m_handle->setPitch(value);
|
||||
m_entry->m_panning.read(frame, &value);
|
||||
AUD_SoftwareDevice::setPanning(m_handle.get(), value);
|
||||
|
||||
// AUD_XXX: TODO: animation data
|
||||
|
||||
if(m_entry->m_muted)
|
||||
m_handle->setVolume(0);
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
~AUD_SequencerHandle();
|
||||
int compare(AUD_Reference<AUD_SequencerEntry> entry) const;
|
||||
void stop();
|
||||
void update(float position);
|
||||
void update(float position, float frame);
|
||||
void seek(float position);
|
||||
};
|
||||
|
||||
|
@ -144,19 +144,27 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
AUD_Specs specs = m_factory->m_specs;
|
||||
int pos = 0;
|
||||
float time = float(m_position) / float(specs.rate);
|
||||
int len;
|
||||
float value, frame;
|
||||
int len, cfra;
|
||||
|
||||
while(pos < length)
|
||||
{
|
||||
len = int(ceil((int(floor(time * m_factory->m_fps)) + 1) / m_factory->m_fps * specs.rate)) - m_position;
|
||||
frame = time * m_factory->m_fps;
|
||||
cfra = int(floor(frame));
|
||||
|
||||
len = int(ceil((cfra + 1) / m_factory->m_fps * specs.rate)) - m_position;
|
||||
len = AUD_MIN(length - pos, len);
|
||||
len = AUD_MAX(len, 1);
|
||||
|
||||
for(AUD_HandleIterator it = m_handles.begin(); it != m_handles.end(); it++)
|
||||
{
|
||||
(*it)->update(time);
|
||||
(*it)->update(time, frame);
|
||||
}
|
||||
|
||||
m_factory->m_volume.read(frame, &value);
|
||||
|
||||
m_device.setVolume(value);
|
||||
|
||||
m_device.read(reinterpret_cast<data_t*>(buffer + specs.channels * pos), len);
|
||||
|
||||
pos += len;
|
||||
|
@ -62,8 +62,8 @@ typedef enum
|
||||
/******************************************************************************/
|
||||
|
||||
AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, AUD_Reference<AUD_ResampleReader> resampler, AUD_Reference<AUD_ChannelMapperReader> mapper, bool keep) :
|
||||
m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_volume(1.0f), m_loopcount(0),
|
||||
m_relative(false), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()),
|
||||
m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_user_pan(0.0f), m_volume(1.0f), m_loopcount(0),
|
||||
m_relative(true), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()),
|
||||
m_distance_reference(1.0f), m_attenuation(1.0f), m_cone_angle_outer(M_PI), m_cone_angle_inner(M_PI), m_cone_volume_outer(0),
|
||||
m_flags(AUD_RENDER_CONE), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), m_device(device)
|
||||
{
|
||||
@ -211,7 +211,7 @@ void AUD_SoftwareDevice::AUD_SoftwareHandle::update()
|
||||
m_mapper->setMonoAngle(phi);
|
||||
}
|
||||
else
|
||||
m_mapper->setMonoAngle(0);
|
||||
m_mapper->setMonoAngle(m_relative ? m_user_pan * M_PI / 2.0 : 0);
|
||||
}
|
||||
|
||||
void AUD_SoftwareDevice::AUD_SoftwareHandle::setSpecs(AUD_Specs specs)
|
||||
@ -768,6 +768,12 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
|
||||
unlock();
|
||||
}
|
||||
|
||||
void AUD_SoftwareDevice::setPanning(AUD_IHandle* handle, float pan)
|
||||
{
|
||||
AUD_SoftwareDevice::AUD_SoftwareHandle* h = dynamic_cast<AUD_SoftwareDevice::AUD_SoftwareHandle*>(handle);
|
||||
h->m_user_pan = pan;
|
||||
}
|
||||
|
||||
void AUD_SoftwareDevice::setSpecs(AUD_Specs specs)
|
||||
{
|
||||
m_specs.specs = specs;
|
||||
|
@ -81,6 +81,9 @@ protected:
|
||||
/// The user set volume of the source.
|
||||
float m_user_volume;
|
||||
|
||||
/// The user set panning for non-3D sources
|
||||
float m_user_pan;
|
||||
|
||||
/// The calculated final volume of the source.
|
||||
float m_volume;
|
||||
|
||||
@ -278,6 +281,9 @@ private:
|
||||
int m_flags;
|
||||
|
||||
public:
|
||||
|
||||
static void setPanning(AUD_IHandle* handle, float pan);
|
||||
|
||||
virtual AUD_DeviceSpecs getSpecs() const;
|
||||
virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false);
|
||||
virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false);
|
||||
|
@ -360,21 +360,6 @@ class RENDER_PT_game_display(RenderButtonsPanel, bpy.types.Panel):
|
||||
flow.prop(gs, "show_mouse", text="Mouse Cursor")
|
||||
|
||||
|
||||
class RENDER_PT_game_sound(RenderButtonsPanel, bpy.types.Panel):
|
||||
bl_label = "Sound"
|
||||
COMPAT_ENGINES = {'BLENDER_GAME'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
scene = context.scene
|
||||
|
||||
layout.prop(scene, "audio_distance_model")
|
||||
|
||||
layout.prop(scene, "audio_doppler_speed", text="Speed")
|
||||
layout.prop(scene, "audio_doppler_factor")
|
||||
|
||||
|
||||
class WorldButtonsPanel():
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
|
@ -595,11 +595,8 @@ class RENDER_PT_encoding(RenderButtonsPanel, bpy.types.Panel):
|
||||
|
||||
col = split.column()
|
||||
col.prop(rd, "ffmpeg_audio_bitrate")
|
||||
col.prop(rd, "ffmpeg_audio_mixrate")
|
||||
|
||||
col = split.column()
|
||||
col.prop(rd, "ffmpeg_audio_volume", slider=True)
|
||||
col.prop(rd, "ffmpeg_audio_channels")
|
||||
|
||||
|
||||
class RENDER_PT_bake(RenderButtonsPanel, bpy.types.Panel):
|
||||
|
@ -43,6 +43,32 @@ class SCENE_PT_scene(SceneButtonsPanel, bpy.types.Panel):
|
||||
layout.prop(scene, "background_set", text="Background")
|
||||
|
||||
|
||||
class SCENE_PT_audio(SceneButtonsPanel, bpy.types.Panel):
|
||||
bl_label = "Audio"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
scene = context.scene
|
||||
rd = context.scene.render
|
||||
|
||||
layout.prop(scene, "audio_distance_model")
|
||||
|
||||
layout.prop(scene, "audio_doppler_speed", text="Speed")
|
||||
layout.prop(scene, "audio_doppler_factor")
|
||||
|
||||
layout.prop(scene, "audio_volume")
|
||||
layout.operator("sound.update_animation_flags")
|
||||
layout.operator("sound.bake_animation")
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.prop(rd, "ffmpeg_audio_mixrate", text="Rate")
|
||||
col = split.column()
|
||||
col.prop(rd, "ffmpeg_audio_channels", text="")
|
||||
|
||||
|
||||
class SCENE_PT_unit(SceneButtonsPanel, bpy.types.Panel):
|
||||
bl_label = "Units"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER'}
|
||||
|
@ -640,6 +640,8 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, bpy.types.Panel):
|
||||
|
||||
layout.prop(strip, "volume")
|
||||
layout.prop(strip, "attenuation")
|
||||
layout.prop(strip, "pitch")
|
||||
layout.prop(strip, "pan")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Trim Duration:")
|
||||
|
@ -199,7 +199,7 @@ struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int
|
||||
struct FCurve *iter_step_fcurve (struct FCurve *fcu_iter, const char rna_path[]);
|
||||
|
||||
/* high level function to get an fcurve from C without having the rna */
|
||||
struct FCurve *id_data_find_fcurve(ID *id, void *data, struct StructRNA *type, const char *prop_name, int index);
|
||||
struct FCurve *id_data_find_fcurve(ID *id, void *data, struct StructRNA *type, const char *prop_name, int index, char *driven);
|
||||
|
||||
/* Get list of LinkData's containing pointers to the F-Curves which control the types of data indicated
|
||||
* e.g. numMatches = list_find_data_fcurves(matches, &act->curves, "pose.bones[", "MyFancyBone");
|
||||
|
@ -96,6 +96,16 @@ void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, i
|
||||
|
||||
void sound_update_scene_sound(void* handle, struct bSound* sound);
|
||||
|
||||
void sound_set_cfra(int cfra);
|
||||
|
||||
void sound_set_scene_volume(struct Scene *scene, float volume);
|
||||
|
||||
void sound_set_scene_sound_volume(void* handle, float volume, char animated);
|
||||
|
||||
void sound_set_scene_sound_pitch(void* handle, float pitch, char animated);
|
||||
|
||||
void sound_set_scene_sound_pan(void* handle, float pan, char animated);
|
||||
|
||||
void sound_update_sequencer(struct Main* main, struct bSound* sound);
|
||||
|
||||
void sound_play_scene(struct Scene *scene);
|
||||
|
@ -174,7 +174,7 @@ void copy_fcurves (ListBase *dst, ListBase *src)
|
||||
/* ----------------- Finding F-Curves -------------------------- */
|
||||
|
||||
/* high level function to get an fcurve from C without having the rna */
|
||||
FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *prop_name, int index)
|
||||
FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *prop_name, int index, char *driven)
|
||||
{
|
||||
/* anim vars */
|
||||
AnimData *adt= BKE_animdata_from_id(id);
|
||||
@ -185,6 +185,9 @@ FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *pro
|
||||
PropertyRNA *prop;
|
||||
char *path;
|
||||
|
||||
if(driven)
|
||||
*driven = 0;
|
||||
|
||||
/* only use the current action ??? */
|
||||
if (ELEM(NULL, adt, adt->action))
|
||||
return NULL;
|
||||
@ -201,11 +204,12 @@ FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *pro
|
||||
fcu= list_find_fcurve(&adt->action->curves, path, index);
|
||||
|
||||
/* if not animated, check if driven */
|
||||
#if 0
|
||||
if ((fcu == NULL) && (adt->drivers.first)) {
|
||||
fcu= list_find_fcurve(&adt->drivers, path, but->rnaindex);
|
||||
fcu= list_find_fcurve(&adt->drivers, path, index);
|
||||
if(fcu && driven)
|
||||
*driven = 1;
|
||||
fcu = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
MEM_freeN(path);
|
||||
}
|
||||
|
@ -473,9 +473,10 @@ Scene *add_scene(const char *name)
|
||||
|
||||
BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine));
|
||||
|
||||
sce->audio.distance_model = 2.0;
|
||||
sce->audio.doppler_factor = 1.0;
|
||||
sce->audio.speed_of_sound = 343.3;
|
||||
sce->audio.distance_model = 2.0f;
|
||||
sce->audio.doppler_factor = 1.0f;
|
||||
sce->audio.speed_of_sound = 343.3f;
|
||||
sce->audio.volume = 1.0f;
|
||||
|
||||
BLI_strncpy(sce->r.pic, U.renderdir, sizeof(sce->r.pic));
|
||||
|
||||
@ -1001,6 +1002,8 @@ void scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
|
||||
float ctime = BKE_curframe(sce);
|
||||
Scene *sce_iter;
|
||||
|
||||
sound_set_cfra(sce->r.cfra);
|
||||
|
||||
/* clear animation overrides */
|
||||
// XXX TODO...
|
||||
|
||||
|
@ -3163,7 +3163,7 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force)
|
||||
|
||||
/* XXX - new in 2.5x. should we use the animation system this way?
|
||||
* The fcurve is needed because many frames need evaluating at once - campbell */
|
||||
fcu= id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0);
|
||||
fcu= id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL);
|
||||
|
||||
|
||||
if (!v->frameMap || v->length != seq->len) {
|
||||
|
@ -1775,7 +1775,7 @@ static ImBuf* seq_render_effect_strip_impl(
|
||||
facf= fac;
|
||||
}
|
||||
else {
|
||||
fcu = id_data_find_fcurve(&context.scene->id, seq, &RNA_Sequence, "effect_fader", 0);
|
||||
fcu = id_data_find_fcurve(&context.scene->id, seq, &RNA_Sequence, "effect_fader", 0, NULL);
|
||||
if (fcu) {
|
||||
fac = facf = evaluate_fcurve(fcu, cfra);
|
||||
if( context.scene->r.mode & R_FIELDS ) {
|
||||
@ -3496,6 +3496,7 @@ Sequence *alloc_sequence(ListBase *lb, int cfra, int machine)
|
||||
seq->mul= 1.0;
|
||||
seq->blend_opacity = 100.0;
|
||||
seq->volume = 1.0f;
|
||||
seq->pitch = 1.0f;
|
||||
seq->scene_sound = NULL;
|
||||
|
||||
return seq;
|
||||
|
@ -32,10 +32,11 @@
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_packedFile.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_sequencer.h"
|
||||
|
||||
// evil global ;-)
|
||||
static int sound_cfra;
|
||||
|
||||
struct bSound* sound_new_file(struct Main *bmain, const char *filename)
|
||||
{
|
||||
@ -411,6 +412,31 @@ void sound_update_scene_sound(void* handle, struct bSound* sound)
|
||||
AUD_updateSequenceSound(handle, sound->playback_handle);
|
||||
}
|
||||
|
||||
void sound_set_cfra(int cfra)
|
||||
{
|
||||
sound_cfra = cfra;
|
||||
}
|
||||
|
||||
void sound_set_scene_volume(struct Scene *scene, float volume)
|
||||
{
|
||||
AUD_setSequencerAnimData(scene->sound_scene, AUD_AP_VOLUME, CFRA, &volume, (scene->audio.flag & AUDIO_VOLUME_ANIMATED) != 0);
|
||||
}
|
||||
|
||||
void sound_set_scene_sound_volume(void* handle, float volume, char animated)
|
||||
{
|
||||
AUD_setSequenceAnimData(handle, AUD_AP_VOLUME, sound_cfra, &volume, animated);
|
||||
}
|
||||
|
||||
void sound_set_scene_sound_pitch(void* handle, float pitch, char animated)
|
||||
{
|
||||
AUD_setSequenceAnimData(handle, AUD_AP_PITCH, sound_cfra, &pitch, animated);
|
||||
}
|
||||
|
||||
void sound_set_scene_sound_pan(void* handle, float pan, char animated)
|
||||
{
|
||||
AUD_setSequenceAnimData(handle, AUD_AP_PANNING, sound_cfra, &pan, animated);
|
||||
}
|
||||
|
||||
void sound_update_sequencer(struct Main* main, struct bSound* sound)
|
||||
{
|
||||
struct Scene* scene;
|
||||
|
@ -11507,12 +11507,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
kb->slidermax = kb->slidermin + 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Scene *scene;
|
||||
for (scene=main->scene.first; scene; scene=scene->id.next)
|
||||
scene->r.ffcodecdata.audio_channels = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 1)) {
|
||||
@ -11751,6 +11745,20 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
|
||||
{
|
||||
|
||||
{
|
||||
Scene *scene;
|
||||
Sequence *seq;
|
||||
|
||||
for (scene=main->scene.first; scene; scene=scene->id.next)
|
||||
{
|
||||
scene->r.ffcodecdata.audio_channels = 2;
|
||||
scene->audio.volume = 1.0f;
|
||||
SEQ_BEGIN(scene->ed, seq) {
|
||||
seq->pitch = 1.0f;
|
||||
}
|
||||
SEQ_END
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_packedFile_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
@ -49,11 +50,14 @@
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_packedFile.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_sound.h"
|
||||
#include "BKE_sequencer.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
@ -293,6 +297,97 @@ static void SOUND_OT_unpack(wmOperatorType *ot)
|
||||
RNA_def_string(ot->srna, "id", "", MAX_ID_NAME-2, "Sound Name", "Sound datablock name to unpack."); /* XXX, weark!, will fail with library, name collisions */
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
static int update_animation_flags_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Sequence* seq;
|
||||
Scene* scene = CTX_data_scene(C);
|
||||
struct FCurve* fcu;
|
||||
char driven;
|
||||
|
||||
SEQ_BEGIN(scene->ed, seq) {
|
||||
fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "volume", 0, &driven);
|
||||
if(fcu || driven)
|
||||
seq->flag |= SEQ_AUDIO_VOLUME_ANIMATED;
|
||||
else
|
||||
seq->flag &= ~SEQ_AUDIO_VOLUME_ANIMATED;
|
||||
|
||||
fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pitch", 0, &driven);
|
||||
if(fcu || driven)
|
||||
seq->flag |= SEQ_AUDIO_PITCH_ANIMATED;
|
||||
else
|
||||
seq->flag &= ~SEQ_AUDIO_PITCH_ANIMATED;
|
||||
|
||||
fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "pan", 0, &driven);
|
||||
if(fcu || driven)
|
||||
seq->flag |= SEQ_AUDIO_PAN_ANIMATED;
|
||||
else
|
||||
seq->flag &= ~SEQ_AUDIO_PAN_ANIMATED;
|
||||
}
|
||||
SEQ_END
|
||||
|
||||
fcu = id_data_find_fcurve(&scene->id, scene, &RNA_Scene, "audio_volume", 0, &driven);
|
||||
if(fcu || driven)
|
||||
scene->audio.flag |= AUDIO_VOLUME_ANIMATED;
|
||||
else
|
||||
scene->audio.flag &= ~AUDIO_VOLUME_ANIMATED;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void SOUND_OT_update_animation_flags(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Update animation";
|
||||
ot->description= "Update animation flags";
|
||||
ot->idname= "SOUND_OT_update_animation_flags";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= update_animation_flags_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER;
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
static int bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Main* bmain = CTX_data_main(C);
|
||||
Scene* scene = CTX_data_scene(C);
|
||||
int oldfra = scene->r.cfra;
|
||||
int cfra;
|
||||
|
||||
update_animation_flags_exec(C, NULL);
|
||||
|
||||
for(cfra = scene->r.sfra; cfra <= scene->r.efra; cfra++)
|
||||
{
|
||||
scene->r.cfra = cfra;
|
||||
scene_update_for_newframe(bmain, scene, scene->lay);
|
||||
}
|
||||
|
||||
scene->r.cfra = oldfra;
|
||||
scene_update_for_newframe(bmain, scene, scene->lay);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void SOUND_OT_bake_animation(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Bake animation";
|
||||
ot->description= "Bakes the animation cache so that it's up to date";
|
||||
ot->idname= "SOUND_OT_bake_animation";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= bake_animation_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER;
|
||||
}
|
||||
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
void ED_operatortypes_sound(void)
|
||||
@ -300,4 +395,6 @@ void ED_operatortypes_sound(void)
|
||||
WM_operatortype_append(SOUND_OT_open);
|
||||
WM_operatortype_append(SOUND_OT_pack);
|
||||
WM_operatortype_append(SOUND_OT_unpack);
|
||||
WM_operatortype_append(SOUND_OT_update_animation_flags);
|
||||
WM_operatortype_append(SOUND_OT_bake_animation);
|
||||
}
|
||||
|
@ -149,6 +149,8 @@ typedef struct AudioData {
|
||||
int distance_model;
|
||||
short flag;
|
||||
short pad;
|
||||
float volume;
|
||||
float pad2;
|
||||
} AudioData;
|
||||
|
||||
typedef struct SceneRenderLayer {
|
||||
@ -1131,9 +1133,10 @@ typedef struct Scene {
|
||||
#define F_DUPLI 3
|
||||
|
||||
/* audio->flag */
|
||||
#define AUDIO_MUTE 1
|
||||
#define AUDIO_SYNC 2
|
||||
#define AUDIO_SCRUB 4
|
||||
#define AUDIO_MUTE (1<<0)
|
||||
#define AUDIO_SYNC (1<<1)
|
||||
#define AUDIO_SCRUB (1<<2)
|
||||
#define AUDIO_VOLUME_ANIMATED (1<<3)
|
||||
|
||||
#define FFMPEG_MULTIPLEX_AUDIO 1 /* deprecated, you can choose none as audiocodec now */
|
||||
#define FFMPEG_AUTOSPLIT_OUTPUT 2
|
||||
|
@ -155,7 +155,7 @@ typedef struct Sequence {
|
||||
void *scene_sound;
|
||||
float volume;
|
||||
|
||||
float level, pan; /* level in dB (0=full), pan -1..1 */
|
||||
float pitch, pan; /* pitch (-0.1..10), pan -2..2 */
|
||||
int scenenr; /* for scene selection */
|
||||
int multicam_source; /* for multicam source selection */
|
||||
float strobe;
|
||||
@ -284,6 +284,11 @@ typedef struct SpeedControlVars {
|
||||
#define SEQ_USE_PROXY_CUSTOM_FILE (1<<21)
|
||||
#define SEQ_USE_EFFECT_DEFAULT_FADE (1<<22)
|
||||
|
||||
// flags for whether those properties are animated or not
|
||||
#define SEQ_AUDIO_VOLUME_ANIMATED (1<<24)
|
||||
#define SEQ_AUDIO_PITCH_ANIMATED (1<<25)
|
||||
#define SEQ_AUDIO_PAN_ANIMATED (1<<26)
|
||||
|
||||
#define SEQ_INVALID_EFFECT (1<<31)
|
||||
|
||||
/* convenience define for all selection flags */
|
||||
|
@ -337,6 +337,15 @@ static void rna_Scene_fps_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *
|
||||
sound_update_fps(scene);
|
||||
}
|
||||
|
||||
static void rna_Scene_volume_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
Scene *scene= (Scene*)(ptr->data);
|
||||
|
||||
scene->audio.volume = value;
|
||||
if(scene->sound_scene)
|
||||
sound_set_scene_volume(scene, value);
|
||||
}
|
||||
|
||||
static void rna_Scene_framelen_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
|
||||
{
|
||||
scene->r.framelen= (float)scene->r.framapto/(float)scene->r.images;
|
||||
@ -2469,30 +2478,35 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
|
||||
/* 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_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_enum_items(prop, ffmpeg_audio_codec_items);
|
||||
RNA_def_property_ui_text(prop, "Audio Codec", "FFMpeg audio codec to use");
|
||||
RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "ffmpeg_audio_bitrate", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "ffcodecdata.audio_bitrate");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_range(prop, 32, 384);
|
||||
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_audio_mixrate", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "ffcodecdata.audio_mixrate");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_range(prop, 8000, 192000);
|
||||
RNA_def_property_ui_text(prop, "Samplerate", "Audio samplerate(samples/s)");
|
||||
RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "ffmpeg_audio_volume", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "ffcodecdata.audio_volume");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Volume", "Audio volume");
|
||||
RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "ffmpeg_audio_channels", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "ffcodecdata.audio_channels");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_enum_items(prop, audio_channel_items);
|
||||
RNA_def_property_ui_text(prop, "Audio Channels", "Sets the audio channel count");
|
||||
#endif
|
||||
@ -3464,6 +3478,13 @@ void RNA_def_scene(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Distance Model", "Distance model for distance attenuation calculation");
|
||||
RNA_def_property_update(prop, NC_SCENE, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "audio_volume", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "audio.volume");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "Volume", "Audio volume");
|
||||
RNA_def_property_update(prop, NC_SCENE, NULL);
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_Scene_volume_set", NULL);
|
||||
|
||||
/* Game Settings */
|
||||
prop= RNA_def_property(srna, "game_settings", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_sequencer.h"
|
||||
#include "BKE_sound.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
@ -527,6 +528,33 @@ static void rna_Sequence_attenuation_set(PointerRNA *ptr, float value)
|
||||
seq->volume = from_dB(value);
|
||||
}
|
||||
|
||||
static void rna_Sequence_volume_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
Sequence *seq= (Sequence*)(ptr->data);
|
||||
|
||||
seq->volume = value;
|
||||
if(seq->scene_sound)
|
||||
sound_set_scene_sound_volume(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_VOLUME_ANIMATED) != 0);
|
||||
}
|
||||
|
||||
static void rna_Sequence_pitch_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
Sequence *seq= (Sequence*)(ptr->data);
|
||||
|
||||
seq->pitch = value;
|
||||
if(seq->scene_sound)
|
||||
sound_set_scene_sound_pitch(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_PITCH_ANIMATED) != 0);
|
||||
}
|
||||
|
||||
static void rna_Sequence_pan_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
Sequence *seq= (Sequence*)(ptr->data);
|
||||
|
||||
seq->pan = value;
|
||||
if(seq->scene_sound)
|
||||
sound_set_scene_sound_pan(seq->scene_sound, value, (seq->flag & SEQ_AUDIO_PAN_ANIMATED) != 0);
|
||||
}
|
||||
|
||||
|
||||
static int rna_Sequence_input_count_get(PointerRNA *ptr)
|
||||
{
|
||||
@ -558,9 +586,6 @@ static void rna_Sequence_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *p
|
||||
Editing *ed= seq_give_editing(scene, FALSE);
|
||||
|
||||
free_imbuf_seq(scene, &ed->seqbase, FALSE, TRUE);
|
||||
|
||||
if(RNA_struct_is_a(ptr->type, &RNA_SoundSequence))
|
||||
seq_update_sound_bounds(scene, ptr->data);
|
||||
}
|
||||
|
||||
static void rna_Sequence_update_reopen_files(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
|
||||
@ -1368,13 +1393,27 @@ static void rna_def_sound(BlenderRNA *brna)
|
||||
RNA_def_property_float_sdna(prop, NULL, "volume");
|
||||
RNA_def_property_range(prop, 0.0f, 100.0f);
|
||||
RNA_def_property_ui_text(prop, "Volume", "Playback volume of the sound");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_volume_set", NULL);
|
||||
RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
|
||||
|
||||
prop= RNA_def_property(srna, "attenuation", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, -100.0f, +40.0f);
|
||||
RNA_def_property_ui_text(prop, "Attenuation/dB", "Attenuation in decibel");
|
||||
RNA_def_property_float_funcs(prop, "rna_Sequence_attenuation_get", "rna_Sequence_attenuation_set", NULL);
|
||||
RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
|
||||
|
||||
prop= RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "pitch");
|
||||
RNA_def_property_range(prop, 0.1f, 10.0f);
|
||||
RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pitch_set", NULL);
|
||||
RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
|
||||
|
||||
prop= RNA_def_property(srna, "pan", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "pan");
|
||||
RNA_def_property_range(prop, -2.0f, 2.0f);
|
||||
RNA_def_property_ui_text(prop, "Pan", "Playback panning of the sound (only for Mono sources)");
|
||||
RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pan_set", NULL);
|
||||
RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
|
||||
|
||||
prop= RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
|
||||
|
Loading…
Reference in New Issue
Block a user