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:
Joerg Mueller
2011-07-28 13:58:59 +00:00
parent 90b64737f1
commit bd6ca0570e
29 changed files with 439 additions and 62 deletions

View File

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

View File

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

View File

@@ -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);
@@ -184,6 +184,9 @@ FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *pro
PointerRNA ptr;
PropertyRNA *prop;
char *path;
if(driven)
*driven = 0;
/* only use the current action ??? */
if (ELEM(NULL, adt, adt->action))
@@ -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);
}

View File

@@ -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));
@@ -1000,6 +1001,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...

View File

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

View File

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

View File

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

View File

@@ -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)) {
@@ -11750,7 +11744,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
/* put compatibility code here until next subversion bump */
{
{
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! */

View File

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

View File

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

View File

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

View File

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

View File

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