sound-equalizer #105613

Merged
Richard Antalik merged 18 commits from :sound-equalizer into main 2023-08-30 22:36:44 +02:00
29 changed files with 863 additions and 123 deletions
Showing only changes of commit 135e27e7ef - Show all commits

View File

@ -34,6 +34,11 @@ if(NOT DEFINED AUDASPACE_STANDALONE)
set(AUDASPACE_STANDALONE TRUE)
endif()
if(DEFINED FFTW3_INCLUDE_DIRS)
set(FFTW_FOUND TRUE)
endif()
# sources
set(SRC
@ -62,6 +67,7 @@ set(SRC
src/fx/Effect.cpp
src/fx/EffectReader.cpp
src/fx/Envelope.cpp
src/fx/Equalizer.cpp
src/fx/Fader.cpp
src/fx/FaderReader.cpp
src/fx/HighpassCalculator.cpp
@ -174,6 +180,7 @@ set(PUBLIC_HDR
include/fx/Effect.h
include/fx/EffectReader.h
include/fx/Envelope.h
include/fx/Equalizer.h
include/fx/Fader.h
include/fx/FaderReader.h
include/fx/HighpassCalculator.h
@ -500,6 +507,7 @@ if(WITH_FFMPEG)
endif()
endif()
message(WARNING "WITH_FFTW: ${WITH_FFTW}")
# FFTW
if(WITH_FFTW)
if(AUDASPACE_STANDALONE)
@ -507,6 +515,7 @@ if(WITH_FFTW)
endif()
if(FFTW_FOUND)
message(WARNING "FFTW Found")
set(FFTW_SRC
src/fx/BinauralSound.cpp
src/fx/BinauralReader.cpp
@ -535,8 +544,12 @@ if(WITH_FFTW)
add_definitions(-DWITH_CONVOLUTION)
list(APPEND INCLUDE ${FFTW_INCLUDE_DIR})
list(APPEND LIBRARIES ${FFTW_LIBRARY})
list(APPEND INCLUDE ${FFTW3_INCLUDE_DIRS})
list(APPEND LIBRARIES ${FFTW3_LIBRARIES})
message(WARNING "INCLUDE: ${INCLUDE}")
message(WARNING "LIBRARIES: ${LIBRARIES}")
list(APPEND SRC ${FFTW_SRC})
list(APPEND HDR ${FFTW_HDR})

View File

@ -26,6 +26,7 @@
#include "fx/ADSR.h"
#include "fx/Delay.h"
#include "fx/Envelope.h"
#include "fx/Equalizer.h"
#include "fx/Fader.h"
#include "fx/Highpass.h"
#include "fx/IIRFilter.h"
@ -779,4 +780,14 @@ AUD_API AUD_Sound* AUD_Sound_equalize(AUD_Sound* sound, float *definition, int s
return equalizer;
}
#else
AUD_API AUD_Sound* AUD_Sound_equalize(AUD_Sound* sound, float *definition, int size, float maxFreqEq, int sizeConversion)
{
assert(sound);
return sound;
}
#endif

View File

@ -394,19 +394,19 @@ extern AUD_API int AUD_SoundList_addSound(AUD_Sound* list, AUD_Sound* sound);
*/
extern AUD_API AUD_Sound* AUD_Sound_mutable(AUD_Sound* sound);
/*
* Creates an Equalizer for the sound
* \param sound The handle of the sound
* \param definition buffer of size*sizeof(float) with the array of equalization values
* \param maxFreqEq Maximum frequency refered by the array
* \param sizeConversion Size of the transformation. Must be 2^number (for example 1024, 2048,...)
* \return A handle to the Equalizer refered to that sound
*/
extern AUD_API AUD_Sound* AUD_Sound_equalize(AUD_Sound* sound, float *definition, int size, float maxFreqEq, int sizeConversion);
#ifdef WITH_CONVOLUTION
extern AUD_API AUD_Sound* AUD_Sound_Convolver(AUD_Sound* sound, AUD_ImpulseResponse* filter, AUD_ThreadPool* threadPool);
extern AUD_API AUD_Sound* AUD_Sound_Binaural(AUD_Sound* sound, AUD_HRTF* hrtfs, AUD_Source* source, AUD_ThreadPool* threadPool);
/**
* Creates an Equalizer for the sound
* \param sound The handle of the sound
* \param definition buffer of size*sizeof(float) with the array of equalization values
* \param maxFreqEq Maximum frequency refered by the array
* \param sizeConversion Size of the transformation. Must be 2^number (for example 1024, 2048,...)
* \return A handle to the Equalizer refered to that sound
*/
extern AUD_API AUD_Sound* AUD_Sound_equalize(AUD_Sound* sound, float *definition, int size, float maxFreqEq, int sizeConversion);
#endif
#ifdef __cplusplus

View File

@ -7,7 +7,7 @@ set(SHARED_LIBRARY FALSE) # "Build Shared Library"
set(WITH_C TRUE) # "Build C Module"
set(WITH_DOCS FALSE) # "Build C++ HTML Documentation with Doxygen"
set(WITH_FFMPEG ${WITH_CODEC_FFMPEG}) # "Build With FFMPEG"
set(WITH_FFTW FALSE) # "Build With FFTW"
set(WITH_FFTW TRUE) # "Build With FFTW"
set(WITH_LIBSNDFILE ${WITH_CODEC_SNDFILE}) # "Build With LibSndFile"
set(SEPARATE_C FALSE) # "Build C Binding as separate library"
set(PLUGIN_COREAUDIO FALSE) # "Build CoreAudio Plugin"

View File

@ -123,8 +123,18 @@
AUD_NAMESPACE_BEGIN
/// Sample type.(float samples)
// double samples because of the fftw3 library
typedef float sample_t;
// Indicates that the FFT library uses "double"
#define AUDASPACE_FFTW
#ifdef AUDASPACE_FFTW
typedef double fft_real;
#else
typedef float fft_real;
#endif
/// Sample data type (format samples)
typedef unsigned char data_t;

View File

@ -45,6 +45,18 @@ private:
*/
int m_N;
#ifdef AUDASPACE_FFTW
/**
* The plan to transform the input to the frequency domain.
*/
fftw_plan m_fftPlanR2C;
/**
* The plan to transform the input to the time domain again.
*/
fftw_plan m_fftPlanC2R;
#else
/**
* The plan to transform the input to the frequency domain.
*/
@ -54,6 +66,7 @@ private:
* The plan to transform the input to the time domain again.
*/
fftwf_plan m_fftPlanC2R;
#endif
/**
* The size of a buffer for its use with the FFT plan (in bytes).

View File

@ -12,7 +12,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
******************************************************************************/
#include "sequence/SequenceEntry.h"
#include "sequence/SequenceReader.h"

View File

@ -21,23 +21,18 @@
#include <mutex>
#include "util/Buffer.h"
#define KEEP_TIME 10
#define POSITION_EPSILON (1.0 / static_cast<double>(RATE_48000))
AUD_NAMESPACE_BEGIN
void SequenceHandle::start()
void SequenceHandle::createHandles()
{
// we already tried to start, aborting
if(!m_valid)
return;
// in case the sound is playing, we need to stop first
stop();
std::lock_guard<ILockable> lock(*m_entry);
// let's try playing
if(m_entry->m_sound.get())
{
try
@ -53,7 +48,19 @@ void SequenceHandle::start()
// after starting we have to set the properties, so let's ensure that
m_status--;
}
}
void SequenceHandle::start()
{
// we already tried to start, aborting
if(!m_valid)
return;
// in case the sound is playing, we need to stop first
stop();
createHandles();
// if the sound could not be played, we invalidate
m_valid = m_handle.get();
}

View File

@ -26,6 +26,9 @@ class ReadDevice;
class IHandle;
class I3DHandle;
class SequenceEntry;
class IReader;
class EqualizerReader;
class ISound;
/**
* Represents a playing sequenced entry.
@ -73,6 +76,10 @@ private:
*/
bool updatePosition(double position);
/**
* Creates the handles needed to play the sound
*/
void createHandles();
public:
/**
* Creates a new sequenced handle.

View File

@ -22,20 +22,41 @@ FFTPlan::FFTPlan(double measureTime) :
{
}
// internal_buffer = fftw_malloc(sizeof(fftw_complex)*m_N); // I think that with m_N should be enough
#ifdef AUDASPACE_FFTW
FFTPlan::FFTPlan(int n, double measureTime) :
m_N(n), m_bufferSize(((n/2)+1)*2*sizeof(fftwf_complex))
m_N(n), m_bufferSize((( n / 2) + 1) * 2 * sizeof(fftw_complex))
{
fftw_set_timelimit(measureTime);
void* buf = fftw_malloc(sizeof(fftw_complex)*m_bufferSize);
m_fftPlanR2C = fftw_plan_dft_r2c_1d(m_N, (fft_real *)buf, (fftw_complex *)buf, FFTW_EXHAUSTIVE);
m_fftPlanC2R = fftw_plan_dft_c2r_1d(m_N, (fftw_complex *)buf, (fft_real *)buf, FFTW_EXHAUSTIVE);
fftw_free(buf);
}
#else
FFTPlan::FFTPlan(int n, double measureTime) :
m_N(n), m_bufferSize((( n / 2) + 1) * 2 * sizeof(fftwf_complex))
{
fftwf_set_timelimit(measureTime);
void* buf = fftwf_malloc(m_bufferSize);
m_fftPlanR2C = fftwf_plan_dft_r2c_1d(m_N, (float*)buf, (fftwf_complex*)buf, FFTW_EXHAUSTIVE);
m_fftPlanC2R = fftwf_plan_dft_c2r_1d(m_N, (fftwf_complex*)buf, (float*)buf, FFTW_EXHAUSTIVE);
fftwf_free(buf);
void* buf = fftw_malloc(sizeof(fftwf_complex) * m_bufferSize);
m_fftPlanR2C = fftwf_plan_dft_r2c_1d(m_N, (fft_real *)buf, (fftwf_complex *)buf, FFTW_EXHAUSTIVE);
m_fftPlanC2R = fftwf_plan_dft_c2r_1d(m_N, (fftwf_complex *)buf, (fft_real *)buf, FFTW_EXHAUSTIVE);
fftw_free(buf);
}
#endif
FFTPlan::~FFTPlan()
{
fftwf_destroy_plan(m_fftPlanC2R);
fftwf_destroy_plan(m_fftPlanR2C);
#ifdef AUDASPACE_FFTW
fftw_destroy_plan(m_fftPlanC2R);
fftw_destroy_plan(m_fftPlanR2C);
#else
fftwf_destroy_plan(m_fftPlanC2R);
fftwf_destroy_plan(m_fftPlanR2C);
#endif
}
int FFTPlan::getSize()
@ -43,24 +64,85 @@ int FFTPlan::getSize()
return m_N;
}
/*
* Input is Float / Double .... (sample_t)
* Output is fftwf_complex / fftw_complex / ...
*/
void FFTPlan::FFT(void* buffer)
{
fftwf_execute_dft_r2c(m_fftPlanR2C, (float*)buffer, (fftwf_complex*)buffer);
#ifdef AUDASPACE_FFTW
void *internal_buffer = &(((fftwf_complex *)buffer)[m_bufferSize]);
// Translate forward
sample_t *pt_buffer = (sample_t *)buffer;
fft_real *internal_pt_buffer = (fft_real *)internal_buffer;
// Translate from float to wide float
for(int i = 0; i < m_N; i++)
//internal_pt_buffer[i]=(fft_real)pt_buffer[i];
*internal_pt_buffer++ = (fft_real)(*pt_buffer++);
fftw_execute_dft_r2c(m_fftPlanR2C, (fft_real *)internal_buffer,
(fftw_complex *)internal_buffer);
// Translate backward
fftwf_complex *pt_buffer2 = (fftwf_complex *)buffer;
fftw_complex *internal_pt_buffer2 = (fftw_complex *)internal_buffer;
for(int i = 0; i < m_N; i++) {
pt_buffer2[i][0] = (sample_t)internal_pt_buffer2[i][0];
pt_buffer2[i][1] = (sample_t)internal_pt_buffer2[i][1];
}
#else
fftwf_execute_dft_r2c(m_fftPlanR2C, (fft_real *)buffer,
(fftwf_complex *)buffer);
#endif
}
void FFTPlan::IFFT(void* buffer)
/*
* Input is fftwf_complex / fftw_complex / ...
* Output is Float / Double .... (sample_t)
*/
void FFTPlan::IFFT(void *buffer)
{
fftwf_execute_dft_c2r(m_fftPlanC2R, (fftwf_complex*)buffer, (float*)buffer);
#ifdef AUDASPACE_FFTW
void *internal_buffer = &(((fftwf_complex *)buffer)[m_bufferSize]);
// Translate forward
fftwf_complex *pt_buffer = (fftwf_complex *)buffer;
fftw_complex *internal_pt_buffer = (fftw_complex *)internal_buffer;
for(int i = 0; i < m_N; i++) {
internal_pt_buffer[i][0] = (fft_real)pt_buffer[i][0];
internal_pt_buffer[i][1] = (fft_real)pt_buffer[i][1];
}
fftw_execute_dft_c2r(m_fftPlanC2R, (fftw_complex *)internal_buffer,
(fft_real *)internal_buffer);
sample_t *pt_buffer2 = (sample_t *)buffer;
fft_real *internal_pt_buffer2 = (fft_real *)internal_buffer;
for(int i = 0; i < m_N; i++)
pt_buffer2[i] = (sample_t)internal_pt_buffer2[i];
#else
fftwf_execute_dft_c2r(m_fftPlanC2R, (fftwf_complex *)buffer,
(fft_real *)buffer);
#endif
}
void* FFTPlan::getBuffer()
void *FFTPlan::getBuffer()
{
return fftwf_malloc(m_bufferSize);
#ifdef AUDASPACE_FFTW
return fftw_malloc(sizeof(fftwf_complex) * m_bufferSize +
sizeof(fftw_complex) * m_bufferSize);
#else
return fftw_malloc(sizeof(fftwf_complex) * m_bufferSize);
#endif
}
void FFTPlan::freeBuffer(void* buffer)
void FFTPlan::freeBuffer(void *buffer)
{
fftwf_free(buffer);
fftw_free(buffer);
}
AUD_NAMESPACE_END

View File

@ -960,7 +960,11 @@ class SEQUENCER_MT_strip(Menu):
if strip_type != 'SOUND':
layout.separator()
layout.operator_menu_enum("sequencer.strip_modifier_add", "type", text="Add Modifier")
layout.operator_menu_enum("sequencer.strip_video_modifier_add", "type", text="Add Modifier")
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
else:
layout.separator()
layout.operator_menu_enum("sequencer.strip_sound_modifier_add", "type", text="Add Modifier")
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
if strip_type in {
@ -1101,17 +1105,19 @@ class SEQUENCER_MT_context_menu(Menu):
if strip_type != 'SOUND':
layout.separator()
layout.operator_menu_enum("sequencer.strip_modifier_add", "type", text="Add Modifier")
layout.operator_menu_enum("sequencer.strip_video_modifier_add", "type", text="Add Modifier")
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
if selected_sequences_count >= 2:
layout.separator()
col = layout.column()
col.menu("SEQUENCER_MT_add_transitions", text="Add Transition")
elif selected_sequences_count >= 2:
else:
layout.separator()
layout.operator("sequencer.crossfade_sounds", text="Crossfade Sounds")
layout.operator_menu_enum("sequencer.strip_sound_modifier_add", "type", text="Add Modifier")
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
if selected_sequences_count >= 2:
layout.separator()
layout.operator("sequencer.crossfade_sounds", text="Crossfade Sounds")
if selected_sequences_count >= 1:
col = layout.column()
@ -2500,8 +2506,13 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
strip = context.active_sequence_strip
ed = context.scene.sequence_editor
if strip.type == 'SOUND':
sound = strip.sound
else:
sound = None
layout.prop(strip, "use_linear_modifiers")
if sound is None:
layout.prop(strip, "use_linear_modifiers")
layout.operator_menu_enum("sequencer.strip_modifier_add", "type")
layout.operator("sequencer.strip_modifier_copy")
@ -2528,45 +2539,66 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
row.operator("sequencer.strip_modifier_remove", text="", icon='X', emboss=False).name = mod.name
if mod.show_expanded:
row = box.row()
row.prop(mod, "input_mask_type", expand=True)
if mod.input_mask_type == 'STRIP':
sequences_object = ed
if ed.meta_stack:
sequences_object = ed.meta_stack[-1]
box.prop_search(mod, "input_mask_strip", sequences_object, "sequences", text="Mask")
else:
box.prop(mod, "input_mask_id")
if sound is None:
row = box.row()
row.prop(mod, "mask_time", expand=True)
row.prop(mod, "input_mask_type", expand=True)
if mod.type == 'COLOR_BALANCE':
box.prop(mod, "color_multiply")
draw_color_balance(box, mod.color_balance)
elif mod.type == 'CURVES':
box.template_curve_mapping(mod, "curve_mapping", type='COLOR', show_tone=True)
elif mod.type == 'HUE_CORRECT':
box.template_curve_mapping(mod, "curve_mapping", type='HUE')
elif mod.type == 'BRIGHT_CONTRAST':
col = box.column()
col.prop(mod, "bright")
col.prop(mod, "contrast")
elif mod.type == 'WHITE_BALANCE':
col = box.column()
col.prop(mod, "white_value")
elif mod.type == 'TONEMAP':
col = box.column()
col.prop(mod, "tonemap_type")
if mod.tonemap_type == 'RD_PHOTORECEPTOR':
col.prop(mod, "intensity")
if mod.input_mask_type == 'STRIP':
sequences_object = ed
if ed.meta_stack:
sequences_object = ed.meta_stack[-1]
box.prop_search(mod, "input_mask_strip", sequences_object, "sequences", text="Mask")
else:
box.prop(mod, "input_mask_id")
row = box.row()
row.prop(mod, "mask_time", expand=True)
if mod.type == 'COLOR_BALANCE':
box.prop(mod, "color_multiply")
draw_color_balance(box, mod.color_balance)
elif mod.type == 'CURVES':
box.template_curve_mapping(mod, "curve_mapping", type='COLOR', show_tone=True)
elif mod.type == 'HUE_CORRECT':
box.template_curve_mapping(mod, "curve_mapping", type='HUE')
elif mod.type == 'BRIGHT_CONTRAST':
col = box.column()
col.prop(mod, "bright")
col.prop(mod, "contrast")
col.prop(mod, "adaptation")
col.prop(mod, "correction")
elif mod.tonemap_type == 'RH_SIMPLE':
col.prop(mod, "key")
col.prop(mod, "offset")
col.prop(mod, "gamma")
elif mod.type == 'WHITE_BALANCE':
col = box.column()
col.prop(mod, "white_value")
elif mod.type == 'TONEMAP':
col = box.column()
col.prop(mod, "tonemap_type")
if mod.tonemap_type == 'RD_PHOTORECEPTOR':
col.prop(mod, "intensity")
col.prop(mod, "contrast")
col.prop(mod, "adaptation")
col.prop(mod, "correction")
elif mod.tonemap_type == 'RH_SIMPLE':
col.prop(mod, "key")
col.prop(mod, "offset")
col.prop(mod, "gamma")
else:
if mod.type == 'SOUND_EQUALIZER':
eq_row = box.row()
# eq_graphs = eq_row.operator_menu_enum("sequencer.strip_modifier_equalizer_redefine", "graphs")
# eq_graphs.name = mod.name
flow = box.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
for i in range(len(mod.graphics)):
soundEq = mod.graphics[i]
col = flow.column()
box = col.box()
split = box.split(factor=0.4)
split.label(text = "{:.2f}".format(soundEq.curve_mapping.clip_min_x))
split.label(text = "Hz")
split.alignment = "RIGHT"
split.label(text = "{:.2f}".format(soundEq.curve_mapping.clip_max_x))
box.template_curve_mapping(soundEq, "curve_mapping",
type='NONE', levels=False, brush=True, use_negative_slope=True, show_tone=False)
second_row = col.row()
second_row.label(text = "dB")
second_row.alignment = "CENTER"
class SEQUENCER_PT_annotation(AnnotationDataPanel, SequencerButtonsPanel_Output, Panel):

View File

@ -23,8 +23,13 @@ struct ImBuf;
struct Scopes;
struct rctf;
void BKE_curvemapping_set_defaults(
struct CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy);
void BKE_curvemapping_set_defaults(struct CurveMapping *cumap,
int tot,
float minx,
float miny,
float maxx,
float maxy,
short default_handle_type);
struct CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy);
void BKE_curvemapping_free_data(struct CurveMapping *cumap);
void BKE_curvemapping_free(struct CurveMapping *cumap);

View File

@ -126,6 +126,7 @@ void BKE_sound_update_scene_listener(struct Scene *scene);
void *BKE_sound_scene_add_scene_sound(
struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip);
void *BKE_sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence);
void *BKE_sound_add_scene_sound(
@ -144,8 +145,14 @@ void BKE_sound_move_scene_sound(const struct Scene *scene,
double audio_offset);
void BKE_sound_move_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence);
/* Join the Sequence with the structure in Audaspace, the second parameter is a bSound */
void BKE_sound_update_scene_sound(void *handle, struct bSound *sound);
/* Join the Sequence with the structure in Audaspace, the second parameter is the AUD_Sound created
* in Audaspace previously
*/
void BKE_sound_update_sequence_handle(void *handle, void *sound_handle);
void BKE_sound_set_cfra(int cfra);
void BKE_sound_set_scene_volume(struct Scene *scene, float volume);

View File

@ -791,7 +791,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
/* Curve. */
custom_curve = brush->gpencil_settings->curve_sensitivity;
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
BKE_curvemapping_init(custom_curve);
brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_INK);
@ -828,7 +828,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
/* Curve. */
custom_curve = brush->gpencil_settings->curve_sensitivity;
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
BKE_curvemapping_init(custom_curve);
brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_INKNOISE);
@ -865,7 +865,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
/* Curve. */
custom_curve = brush->gpencil_settings->curve_sensitivity;
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
BKE_curvemapping_init(custom_curve);
brush_gpencil_curvemap_reset(custom_curve->cm, 4, GPCURVE_PRESET_MARKER);
@ -901,12 +901,12 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
/* Curve. */
custom_curve = brush->gpencil_settings->curve_sensitivity;
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
BKE_curvemapping_init(custom_curve);
brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_CHISEL_SENSIVITY);
custom_curve = brush->gpencil_settings->curve_strength;
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
BKE_curvemapping_init(custom_curve);
brush_gpencil_curvemap_reset(custom_curve->cm, 4, GPCURVE_PRESET_CHISEL_STRENGTH);

View File

@ -34,9 +34,14 @@
/* ***************** operations on full struct ************* */
void BKE_curvemapping_set_defaults(
CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy)
{
void BKE_curvemapping_set_defaults(CurveMapping *cumap,
int tot,
float minx,
float miny,
float maxx,
float maxy,
short default_handle_type)
{
int a;
float clipminx, clipminy, clipmaxx, clipmaxy;
@ -57,13 +62,23 @@ void BKE_curvemapping_set_defaults(
cumap->bwmul[0] = cumap->bwmul[1] = cumap->bwmul[2] = 1.0f;
for (a = 0; a < tot; a++) {
if (default_handle_type == HD_VECT) {
cumap->cm[a].default_handle_type = CUMA_HANDLE_VECTOR;
}
else if (default_handle_type == HD_AUTO_ANIM) {
cumap->cm[a].default_handle_type = CUMA_HANDLE_AUTO_ANIM;
}
cumap->cm[a].totpoint = 2;
cumap->cm[a].curve = MEM_callocN(2 * sizeof(CurveMapPoint), "curve points");
cumap->cm[a].curve[0].x = minx;
cumap->cm[a].curve[0].y = miny;
cumap->cm[a].curve[0].flag |= default_handle_type;
cumap->cm[a].curve[1].x = maxx;
cumap->cm[a].curve[1].y = maxy;
cumap->cm[a].curve[1].flag |= default_handle_type;
}
cumap->changed_timestamp = 0;
@ -75,7 +90,7 @@ CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx,
cumap = MEM_callocN(sizeof(CurveMapping), "new curvemap");
BKE_curvemapping_set_defaults(cumap, tot, minx, miny, maxx, maxy);
BKE_curvemapping_set_defaults(cumap, tot, minx, miny, maxx, maxy, HD_AUTO);
return cumap;
}
@ -233,6 +248,7 @@ CurveMapPoint *BKE_curvemap_insert(CurveMap *cuma, float x, float y)
cmp[a].x = x;
cmp[a].y = y;
cmp[a].flag = CUMA_SELECT;
cmp[a].flag |= cuma->default_handle_type;
foundloc = true;
newcmp = &cmp[a];
}
@ -292,6 +308,10 @@ void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope
cuma->curve = MEM_callocN(cuma->totpoint * sizeof(CurveMapPoint), "curve points");
for (int i = 0; i < cuma->totpoint; i++) {
cuma->curve[i].flag = cuma->default_handle_type;
}
switch (preset) {
case CURVE_PRESET_LINE:
cuma->curve[0].x = clipr->xmin;
@ -299,6 +319,8 @@ void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope
cuma->curve[1].x = clipr->xmax;
cuma->curve[1].y = clipr->ymin;
if (slope == CURVEMAP_SLOPE_POS_NEG) {
cuma->curve[0].flag &= ~CUMA_HANDLE_AUTO_ANIM;
cuma->curve[1].flag &= ~CUMA_HANDLE_AUTO_ANIM;
cuma->curve[0].flag |= CUMA_HANDLE_VECTOR;
cuma->curve[1].flag |= CUMA_HANDLE_VECTOR;
}

View File

@ -155,7 +155,7 @@ static void scene_init_data(ID *id)
BLI_strncpy(scene->r.bake.filepath, U.renderdir, sizeof(scene->r.bake.filepath));
mblur_shutter_curve = &scene->r.mblur_shutter_curve;
BKE_curvemapping_set_defaults(mblur_shutter_curve, 1, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemapping_set_defaults(mblur_shutter_curve, 1, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
BKE_curvemapping_init(mblur_shutter_curve);
BKE_curvemap_reset(mblur_shutter_curve->cm,
&mblur_shutter_curve->clipr,

View File

@ -791,6 +791,11 @@ void BKE_sound_update_scene_sound(void *handle, bSound *sound)
AUD_SequenceEntry_setSound(handle, sound->playback_handle);
}
void BKE_sound_update_sequence_handle(void *handle, void *sound_handle)
{
AUD_SequenceEntry_setSound(handle, sound_handle);
}
void BKE_sound_set_cfra(int cfra)
{
sound_cfra = cfra;

View File

@ -1103,7 +1103,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
Scene *scene;
for (scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
CurveMapping *curve_mapping = &scene->r.mblur_shutter_curve;
BKE_curvemapping_set_defaults(curve_mapping, 1, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemapping_set_defaults(curve_mapping, 1, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
BKE_curvemapping_init(curve_mapping);
BKE_curvemap_reset(
curve_mapping->cm, &curve_mapping->clipr, CURVE_PRESET_MAX, CURVEMAP_SLOPE_POS_NEG);

View File

@ -277,6 +277,7 @@ void SEQUENCER_OT_strip_modifier_add(struct wmOperatorType *ot);
void SEQUENCER_OT_strip_modifier_remove(struct wmOperatorType *ot);
void SEQUENCER_OT_strip_modifier_move(struct wmOperatorType *ot);
void SEQUENCER_OT_strip_modifier_copy(struct wmOperatorType *ot);
void SEQUENCER_OT_strip_modifier_equalizer_redefine(struct wmOperatorType *ot);
/* sequencer_view.c */

View File

@ -10,6 +10,8 @@
#include "DNA_scene_types.h"
#include "DEG_depsgraph.h"
#include "BKE_context.h"
#include "WM_api.h"
@ -23,28 +25,13 @@
#include "SEQ_relations.h"
#include "SEQ_select.h"
#include "SEQ_sequencer.h"
#include "SEQ_sound.h"
/* Own include. */
#include "sequencer_intern.h"
/*********************** Add modifier operator *************************/
static bool strip_modifier_active_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
Editing *ed = SEQ_editing_get(scene);
if (ed) {
Sequence *seq = SEQ_select_active_get(scene);
if (seq) {
return SEQ_sequence_supports_modifiers(seq);
}
}
return false;
}
static int strip_modifier_add_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@ -59,6 +46,21 @@ static int strip_modifier_add_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static const EnumPropertyItem *filter_modifiers_by_sequence_type(bContext *C,
PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop),
bool *UNUSED(r_free))
{
Scene *scene = CTX_data_scene(C);
Sequence *seq = SEQ_select_active_get(scene);
if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM)) {
return rna_enum_sequence_sound_modifier_type_items;
}
else {
return rna_enum_sequence_video_modifier_type_items;
}
}
void SEQUENCER_OT_strip_modifier_add(wmOperatorType *ot)
{
PropertyRNA *prop;
@ -70,7 +72,10 @@ void SEQUENCER_OT_strip_modifier_add(wmOperatorType *ot)
/* api callbacks */
ot->exec = strip_modifier_add_exec;
ot->poll = strip_modifier_active_poll;
/*
* No poll because a modifier can be applied to any kind of strip
*/
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@ -78,13 +83,15 @@ void SEQUENCER_OT_strip_modifier_add(wmOperatorType *ot)
/* properties */
prop = RNA_def_enum(ot->srna,
"type",
rna_enum_sequence_modifier_type_items,
seqModifierType_ColorBalance,
DummyRNA_NULL_items,
0,
"Type",
"");
RNA_def_enum_funcs(prop, filter_modifiers_by_sequence_type);
ot->prop = prop;
}
/*********************** Remove modifier operator *************************/
static int strip_modifier_remove_exec(bContext *C, wmOperator *op)
@ -104,7 +111,12 @@ static int strip_modifier_remove_exec(bContext *C, wmOperator *op)
BLI_remlink(&seq->modifiers, smd);
SEQ_modifier_free(smd);
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM)) {
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS | ID_RECALC_AUDIO);
}
else {
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
}
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@ -121,7 +133,9 @@ void SEQUENCER_OT_strip_modifier_remove(wmOperatorType *ot)
/* api callbacks */
ot->exec = strip_modifier_remove_exec;
ot->poll = strip_modifier_active_poll;
/*
* No poll is needed because all kind of strips can have their modifiers erased
*/
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@ -167,7 +181,13 @@ static int strip_modifier_move_exec(bContext *C, wmOperator *op)
}
}
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM)) {
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS | ID_RECALC_AUDIO);
}
else {
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
}
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@ -190,7 +210,10 @@ void SEQUENCER_OT_strip_modifier_move(wmOperatorType *ot)
/* api callbacks */
ot->exec = strip_modifier_move_exec;
ot->poll = strip_modifier_active_poll;
/*
* No poll is needed because all strips can have modifiers
*/
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@ -220,11 +243,20 @@ static int strip_modifier_copy_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
int isSound = ELEM(seq->type, SEQ_TYPE_SOUND_RAM);
LISTBASE_FOREACH (Sequence *, seq_iter, SEQ_active_seqbase_get(ed)) {
if (seq_iter->flag & SELECT) {
if (seq_iter == seq) {
continue;
}
int seq_iter_is_sound =ELEM(seq_iter->type, SEQ_TYPE_SOUND_RAM);
/* If original is sound, only copy to "sound" strips
* If original is not sound, only copy to "not sound" strips
*/
if(isSound != seq_iter_is_sound)
continue;
if (type == SEQ_MODIFIER_COPY_REPLACE) {
if (seq_iter->modifiers.first) {
@ -243,7 +275,14 @@ static int strip_modifier_copy_exec(bContext *C, wmOperator *op)
}
}
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM)) {
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS | ID_RECALC_AUDIO);
}
else {
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
}
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@ -269,7 +308,9 @@ void SEQUENCER_OT_strip_modifier_copy(wmOperatorType *ot)
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = strip_modifier_copy_exec;
ot->poll = strip_modifier_active_poll;
/*
* No poll is needed because all kind of strips can have modifier
*/
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@ -277,3 +318,63 @@ void SEQUENCER_OT_strip_modifier_copy(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", type_items, SEQ_MODIFIER_COPY_REPLACE, "Type", "");
}
static int strip_modifier_equalizer_redefine_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Sequence *seq = SEQ_select_active_get(scene);
SequenceModifierData *smd;
char name[MAX_NAME];
RNA_string_get(op->ptr, "name", name);
int number = RNA_enum_get(op->ptr, "graphs");
smd = SEQ_modifier_find_by_name(seq, name);
if (!smd) {
return OPERATOR_CANCELLED;
}
SEQ_sound_equalizermodifier_set_graphs((SoundEqualizerModifierData *)smd, number);
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
}
void SEQUENCER_OT_strip_modifier_equalizer_redefine(wmOperatorType *ot)
{
static const EnumPropertyItem enum_modifier_equalizer_presets_items[] = {
{1, "SIMPLE", 0, "Unique", "One unique graphical definition"},
{2, "DOUBLE", 0, "Double", "Graphical definition in 2 sections"},
{3, "TRIPLE", 0, "Triplet", "Graphical definition in 3 sections"},
{0, NULL, 0, NULL, NULL},
};
PropertyRNA *prop;
/* identifiers */
ot->name = "Redefine equalizer graphs";
ot->idname = "SEQUENCER_OT_strip_modifier_equalizer_redefine";
ot->description = "Redefine equalizer graphs";
/* api callbacks */
ot->exec = strip_modifier_equalizer_redefine_exec;
/*
* No poll because a modifier can be applied to any kind of strip
*/
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
prop = RNA_def_enum(ot->srna,
"graphs",
enum_modifier_equalizer_presets_items,
1,
"Graphs",
"Number of graphs");
ot->prop = prop;
prop = RNA_def_string(ot->srna, "name", "Name", MAX_NAME, "Name", "Name of modifier to redefine");
RNA_def_property_flag(prop, PROP_HIDDEN);
}

View File

@ -102,6 +102,7 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_strip_modifier_remove);
WM_operatortype_append(SEQUENCER_OT_strip_modifier_move);
WM_operatortype_append(SEQUENCER_OT_strip_modifier_copy);
WM_operatortype_append(SEQUENCER_OT_strip_modifier_equalizer_redefine);
/* sequencer_view.h */
WM_operatortype_append(SEQUENCER_OT_sample);

View File

@ -59,6 +59,8 @@ typedef struct CurveMap {
/** For RGB curves, pre-multiplied extrapolation vector. */
float premul_ext_in[2];
float premul_ext_out[2];
short default_handle_type;
char _pad[6];
} CurveMap;
typedef struct CurveMapping {

View File

@ -516,6 +516,23 @@ enum {
/** \} */
/** \name Sound Modifiers
* \{ */
typedef struct EQCurveMappingData{
struct EQCurveMappingData *next, *prev;
struct CurveMapping curve_mapping;
} EQCurveMappingData;
typedef struct SoundEqualizerModifierData{
SequenceModifierData modifier;
/* EQCurveMappingData */
ListBase graphics;
} SoundEqualizerModifierData;
/** \} */
/* -------------------------------------------------------------------- */
/** \name Scopes
* \{ */
@ -729,6 +746,7 @@ enum {
seqModifierType_Mask = 5,
seqModifierType_WhiteBalance = 6,
seqModifierType_Tonemap = 7,
seqModifierType_SoundEqualizer = 8,
/* Keep last. */
NUM_SEQUENCE_MODIFIER_TYPES,
};

View File

@ -42,6 +42,8 @@ DEF_ENUM(rna_enum_object_modifier_type_items)
DEF_ENUM(rna_enum_constraint_type_items)
DEF_ENUM(rna_enum_boidrule_type_items)
DEF_ENUM(rna_enum_sequence_modifier_type_items)
DEF_ENUM(rna_enum_sequence_video_modifier_type_items)
DEF_ENUM(rna_enum_sequence_sound_modifier_type_items)
DEF_ENUM(rna_enum_object_greasepencil_modifier_type_items)
DEF_ENUM(rna_enum_object_shaderfx_type_items)

View File

@ -69,6 +69,23 @@ const EnumPropertyItem rna_enum_sequence_modifier_type_items[] = {
{seqModifierType_Mask, "MASK", ICON_NONE, "Mask", ""},
{seqModifierType_Tonemap, "TONEMAP", ICON_NONE, "Tone Map", ""},
{seqModifierType_WhiteBalance, "WHITE_BALANCE", ICON_NONE, "White Balance", ""},
{seqModifierType_SoundEqualizer, "SOUND_EQUALIZER", ICON_NONE, "Sound Equalizer", ""},
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_sequence_video_modifier_type_items[] = {
{seqModifierType_BrightContrast, "BRIGHT_CONTRAST", ICON_NONE, "Bright/Contrast", ""},
{seqModifierType_ColorBalance, "COLOR_BALANCE", ICON_NONE, "Color Balance", ""},
{seqModifierType_Curves, "CURVES", ICON_NONE, "Curves", ""},
{seqModifierType_HueCorrect, "HUE_CORRECT", ICON_NONE, "Hue Correct", ""},
{seqModifierType_Mask, "MASK", ICON_NONE, "Mask", ""},
{seqModifierType_Tonemap, "TONEMAP", ICON_NONE, "Tone Map", ""},
{seqModifierType_WhiteBalance, "WHITE_BALANCE", ICON_NONE, "White Balance", ""},
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_sequence_sound_modifier_type_items[] = {
{seqModifierType_SoundEqualizer, "SOUND_EQUALIZER", ICON_NONE, "Equalizer", ""},
{0, NULL, 0, NULL, NULL},
};
@ -86,6 +103,8 @@ const EnumPropertyItem rna_enum_strip_color_items[] = {
{0, NULL, 0, NULL, NULL},
};
#ifdef RNA_RUNTIME
# include "BKE_global.h"
@ -1274,6 +1293,8 @@ static StructRNA *rna_SequenceModifier_refine(struct PointerRNA *ptr)
return &RNA_WhiteBalanceModifier;
case seqModifierType_Tonemap:
return &RNA_SequencerTonemapModifierData;
case seqModifierType_SoundEqualizer:
return &RNA_SoundEqualizerModifier;
default:
return &RNA_SequenceModifier;
}
@ -1332,14 +1353,33 @@ static void rna_SequenceModifier_name_set(PointerRNA *ptr, const char *value)
}
}
static void rna_SequenceModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
static void rna_SequenceModifier_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
/* strip from other scenes could be modified, so using active scene is not reliable */
Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = SEQ_editing_get(scene);
Sequence *seq = sequence_get_by_modifier(ed, ptr->data);
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS | ID_RECALC_AUDIO);
DEG_relations_tag_update(bmain);
}
else
{
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
}
}
/*
* Update of Curve in an EQ Sound Modifier
*/
static void rna_SequenceModifier_EQCurveMapping_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->owner_id;
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS | ID_RECALC_AUDIO);
DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
}
static bool rna_SequenceModifier_otherSequence_poll(PointerRNA *ptr, PointerRNA value)
@ -1454,6 +1494,7 @@ static void rna_Sequence_separate(ID *id, Sequence *seqm, Main *bmain)
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
}
/* Find channel owner. If NULL, owner is `Editing`, otherwise it's `Sequence`. */
static Sequence *rna_SeqTimelineChannel_owner_get(Editing *ed, SeqTimelineChannel *channel)
{
@ -1541,6 +1582,20 @@ static char *rna_SeqTimelineChannel_path(const PointerRNA *ptr)
}
}
static EQCurveMappingData *rna_Sequence_SoundEqualizer_Curve_add(SoundEqualizerModifierData *semd,
bContext *UNUSED(C), float min_freq, float max_freq)
{
EQCurveMappingData *eqcmd= SEQ_sound_equalizermodifier_add_graph(semd, min_freq, max_freq);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
return eqcmd;
}
static void rna_Sequence_SoundEqualizer_Curve_clear(SoundEqualizerModifierData *semd, bContext *UNUSED(C))
{
SEQ_sound_equalizermodifier_free((SequenceModifierData *)semd);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
}
#else
static void rna_def_strip_element(BlenderRNA *brna)
@ -3722,6 +3777,75 @@ static void rna_def_modifiers(BlenderRNA *brna)
rna_def_tonemap_modifier(brna);
}
static void rna_def_graphical_sound_equalizer(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
/* Define Sound EQ */
srna = RNA_def_struct(brna, "EQCurveMappingData", NULL);
RNA_def_struct_sdna(srna, "EQCurveMappingData");
RNA_def_struct_ui_text(srna, "EQCurveMappingData", "EQCurveMappingData");
prop = RNA_def_property(srna, "curve_mapping", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "curve_mapping");
RNA_def_property_struct_type(prop, "CurveMapping");
RNA_def_property_ui_text(prop, "Curve Mapping", "");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_EQCurveMapping_update");
}
static void rna_def_sound_equalizer_modifier(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
srna = RNA_def_struct(brna, "SoundEqualizerModifier", "SequenceModifier");
RNA_def_struct_sdna(srna, "SoundEqualizerModifierData");
RNA_def_struct_ui_text(srna, "SoundEqualizerModifier", "Equalize audio");
/* Sound Equalizers*/
prop = RNA_def_property(srna, "graphics", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "EQCurveMappingData");
RNA_def_property_ui_text(prop, "Graphical definition equalization", "Graphical definition equalization");
/* add band*/
func = RNA_def_function(srna, "new_graphic", "rna_Sequence_SoundEqualizer_Curve_add");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
RNA_def_function_ui_description(func, "Add a new EQ band");
parm = RNA_def_float(func, "min_freq", SOUND_EQUALIZER_DEFAULT_MIN_FREQ,
0.0, SOUND_EQUALIZER_DEFAULT_MAX_FREQ, /* Hard min and max */
"Minimum Frequency", "Minimum Frequency",
0.0, SOUND_EQUALIZER_DEFAULT_MAX_FREQ); /* Soft min and max */
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_float(func, "max_freq", SOUND_EQUALIZER_DEFAULT_MAX_FREQ,
0.0, SOUND_EQUALIZER_DEFAULT_MAX_FREQ, /* Hard min and max */
"Maximum Frequency", "Maximum Frequency",
0.0, SOUND_EQUALIZER_DEFAULT_MAX_FREQ); /* Soft min and max */
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
/* return type */
parm = RNA_def_pointer(func, "graphic_eqs", "EQCurveMappingData", "", "Newly created graphical Equalizer definition");
RNA_def_function_return(func, parm);
/* clear all modifiers */
func = RNA_def_function(srna, "clear_soundeqs", "rna_Sequence_SoundEqualizer_Curve_clear");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
RNA_def_function_ui_description(func, "Remove all graphical equalizers from the Equalizer modifier");
rna_def_graphical_sound_equalizer(brna);
}
static void rna_def_sound_modifiers(BlenderRNA *brna)
{
rna_def_sound_equalizer_modifier(brna);
}
void RNA_def_sequencer(BlenderRNA *brna)
{
rna_def_color_balance(brna);
@ -3747,6 +3871,7 @@ void RNA_def_sequencer(BlenderRNA *brna)
rna_def_effect(brna);
rna_def_effects(brna);
rna_def_modifiers(brna);
rna_def_sound_modifiers(brna);
}
#endif

View File

@ -15,12 +15,51 @@ struct Main;
struct Scene;
struct Sequence;
struct bSound;
struct SequencerSoundEqualizer;
struct BlendWriter;
struct BlendDataReader;
struct ListBase;
struct SoundEqualizerModifierData;
#define SOUND_EQUALIZER_DEFAULT_MIN_FREQ 30.0
#define SOUND_EQUALIZER_DEFAULT_MAX_FREQ 20000.0
#define SOUND_EQUALIZER_DEFAULT_MAX_DB 35.0
#define SOUND_EQUALIZER_SIZE_CONVERSION 2048
#define SOUND_EQUALIZER_SIZE_DEFINITION 1000
void SEQ_sound_update_bounds_all(struct Scene *scene);
void SEQ_sound_update_bounds(struct Scene *scene, struct Sequence *seq);
void SEQ_sound_update(struct Scene *scene, struct bSound *sound);
void SEQ_sound_update_length(struct Main *bmain, struct Scene *scene);
float SEQ_sound_pitch_get(const struct Scene *scene, const struct Sequence *seq);
struct EQCurveMappingData *SEQ_sound_equalizer_add(struct SoundEqualizerModifierData *semd,
float minX,
float maxX);
void SEQ_sound_blend_write(struct BlendWriter *writer, struct ListBase *soundbase);
void SEQ_sound_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb);
void *SEQ_sound_modifier_recreator(struct Sequence *seq,
struct SequenceModifierData *smd,
void *sound);
void SEQ_sound_equalizermodifier_init_data(struct SequenceModifierData *smd);
void SEQ_sound_equalizermodifier_free(struct SequenceModifierData *smd);
void SEQ_sound_equalizermodifier_copy_data(struct SequenceModifierData *target,
struct SequenceModifierData *smd);
void *SEQ_sound_equalizermodifier_recreator(struct Sequence *seq,
struct SequenceModifierData *smd,
void *sound);
void SEQ_sound_equalizermodifier_set_graphs(struct SoundEqualizerModifierData *semd, int number);
const struct SoundModifierWorkerInfo *SEQ_sound_modifier_worker_info_get(int type);
struct EQCurveMappingData *SEQ_sound_equalizermodifier_add_graph(
struct SoundEqualizerModifierData *semd, float min_freq, float max_freq);
void SEQ_sound_equalizermodifier_remove_graph(struct SoundEqualizerModifierData *semd,
struct EQCurveMappingData *gsed);
typedef struct SoundModifierWorkerInfo {
int type;
void *(*recreator)(struct Sequence *seq, struct SequenceModifierData *smd, void *sound);
} SoundModifierWorkerInfo;
#ifdef __cplusplus
}

View File

@ -30,6 +30,7 @@
#include "SEQ_modifier.h"
#include "SEQ_render.h"
#include "SEQ_sound.h"
#include "BLO_read_write.h"
@ -741,7 +742,7 @@ static void curves_init_data(SequenceModifierData *smd)
{
CurvesModifierData *cmd = (CurvesModifierData *)smd;
BKE_curvemapping_set_defaults(&cmd->curve_mapping, 4, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemapping_set_defaults(&cmd->curve_mapping, 4, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
}
static void curves_free_data(SequenceModifierData *smd)
@ -860,7 +861,7 @@ static void hue_correct_init_data(SequenceModifierData *smd)
HueCorrectModifierData *hcmd = (HueCorrectModifierData *)smd;
int c;
BKE_curvemapping_set_defaults(&hcmd->curve_mapping, 1, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemapping_set_defaults(&hcmd->curve_mapping, 1, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
hcmd->curve_mapping.preset = CURVE_PRESET_MID9;
for (c = 0; c < 3; c++) {
@ -1370,6 +1371,15 @@ static SequenceModifierTypeInfo seqModifier_Tonemap = {
/*apply*/ tonemapmodifier_apply,
};
static SequenceModifierTypeInfo seqModifier_SoundEqualizer = {
CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Equalizer"), /* name */
"SoundEqualizerModifierData", /* struct_name */
sizeof(SoundEqualizerModifierData), /* struct_size */
SEQ_sound_equalizermodifier_init_data, /* init_data */
SEQ_sound_equalizermodifier_free, /* free_data */
SEQ_sound_equalizermodifier_copy_data, /* copy_data */
NULL, /* apply */
};
/** \} */
/* -------------------------------------------------------------------- */
@ -1387,6 +1397,7 @@ static void sequence_modifier_type_info_init(void)
INIT_TYPE(Mask);
INIT_TYPE(WhiteBalance);
INIT_TYPE(Tonemap);
INIT_TYPE(SoundEqualizer);
#undef INIT_TYPE
}
@ -1586,6 +1597,13 @@ void SEQ_modifier_blend_write(BlendWriter *writer, ListBase *modbase)
BKE_curvemapping_blend_write(writer, &hcmd->curve_mapping);
}
else if (smd->type == seqModifierType_SoundEqualizer) {
SoundEqualizerModifierData *semd = (SoundEqualizerModifierData *)smd;
LISTBASE_FOREACH (EQCurveMappingData *, eqcmd, &semd->graphics) {
BLO_write_struct_by_name(writer, "EQCurveMappingData", eqcmd);
BKE_curvemapping_blend_write(writer, &eqcmd->curve_mapping);
}
}
}
else {
BLO_write_struct(writer, SequenceModifierData, smd);
@ -1612,6 +1630,13 @@ void SEQ_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb)
BKE_curvemapping_blend_read(reader, &hcmd->curve_mapping);
}
else if (smd->type == seqModifierType_SoundEqualizer) {
SoundEqualizerModifierData *semd = (SoundEqualizerModifierData *)smd;
BLO_read_list(reader, &semd->graphics);
LISTBASE_FOREACH (EQCurveMappingData *, eqcmd, &semd->graphics) {
BKE_curvemapping_blend_read(reader, &eqcmd->curve_mapping);
}
}
}
}

View File

@ -987,6 +987,17 @@ static bool seq_update_seq_cb(Sequence *seq, void *user_data)
if (scene->id.recalc & ID_RECALC_AUDIO || seq->sound->id.recalc & ID_RECALC_AUDIO) {
BKE_sound_update_scene_sound(seq->scene_sound, seq->sound);
}
void *sound = seq->sound->playback_handle;
if(!BLI_listbase_is_empty(&seq->modifiers))
{
SequenceModifierData *smd;
for (smd= seq->modifiers.first; smd; smd= smd->next) {
sound = SEQ_sound_modifier_recreator(seq, smd, sound);
}
}
BKE_sound_update_sequence_handle(seq->scene_sound, sound);
}
BKE_sound_set_scene_sound_volume(
seq->scene_sound, seq->volume, (seq->flag & SEQ_AUDIO_VOLUME_ANIMATED) != 0);

View File

@ -8,7 +8,11 @@
*/
#include <math.h>
#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_sound_types.h"
@ -16,10 +20,15 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLO_read_write.h"
#include "BKE_colortools.h"
#include "BKE_main.h"
#include "BKE_scene.h"
#include "BKE_sound.h"
#include "AUD_Sound.h"
#include "SEQ_sound.h"
#include "SEQ_time.h"
@ -28,6 +37,9 @@
/* Unlike _update_sound_ functions,
* these ones take info from audaspace to update sequence length! */
const SoundModifierWorkerInfo workersSoundModifiers[] = {
{seqModifierType_SoundEqualizer, SEQ_sound_equalizermodifier_recreator}, {0, NULL}};
#ifdef WITH_AUDASPACE
static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene, ListBase *seqbase)
{
@ -144,3 +156,192 @@ float SEQ_sound_pitch_get(const Scene *scene, const Sequence *seq)
}
return seq->speed_factor;
}
struct EQCurveMappingData *SEQ_sound_equalizer_add(SoundEqualizerModifierData *semd,
float minX,
float maxX)
{
EQCurveMappingData *eqcmd;
if (maxX < 0)
maxX = SOUND_EQUALIZER_DEFAULT_MAX_FREQ;
if (minX < 0)
minX = 0.0;
/* It's the same as BKE_curvemapping_add , but changing the name */
eqcmd = MEM_callocN(sizeof(EQCurveMappingData), "Equalizer");
BKE_curvemapping_set_defaults(&eqcmd->curve_mapping,
1, /* tot*/
minX,
-SOUND_EQUALIZER_DEFAULT_MAX_DB, /* Min x, y */
maxX,
SOUND_EQUALIZER_DEFAULT_MAX_DB, /* Max x, y */
HD_AUTO_ANIM);
eqcmd->curve_mapping.preset = CURVE_PRESET_CONSTANT_MEDIAN;
rctf clipr;
clipr.xmin = minX;
clipr.xmax = maxX;
clipr.ymin = 0.0;
clipr.ymax = 0.0;
BKE_curvemap_reset(&eqcmd->curve_mapping.cm[0], &clipr, CURVE_PRESET_CONSTANT_MEDIAN, 0);
BLI_addtail(&semd->graphics, eqcmd);
return eqcmd;
}
void SEQ_sound_equalizermodifier_set_graphs(struct SoundEqualizerModifierData *semd, int number)
{
SEQ_sound_equalizermodifier_free((SequenceModifierData *)semd);
if (number == 1) {
SEQ_sound_equalizer_add(
semd, SOUND_EQUALIZER_DEFAULT_MIN_FREQ, SOUND_EQUALIZER_DEFAULT_MAX_FREQ);
}
else if (number == 2) {
SEQ_sound_equalizer_add(semd, 30.0, 2000.0);
SEQ_sound_equalizer_add(semd, 2000.1, 20000.0);
}
else if (number == 3) {
SEQ_sound_equalizer_add(semd, 30.0, 1000.0);
SEQ_sound_equalizer_add(semd, 1000.1, 5000.0);
SEQ_sound_equalizer_add(semd, 5000.1, 20000.0);
}
}
EQCurveMappingData *SEQ_sound_equalizermodifier_add_graph(struct SoundEqualizerModifierData *semd,
float min_freq,
float max_freq)
{
if (min_freq < 0.0)
return NULL;
if (max_freq < 0.0)
return NULL;
if (max_freq <= min_freq)
return NULL;
return SEQ_sound_equalizer_add(semd, min_freq, max_freq);
}
void SEQ_sound_equalizermodifier_remove_graph(struct SoundEqualizerModifierData *semd,
struct EQCurveMappingData *eqcmd)
{
BLI_remlink_safe(&semd->graphics, eqcmd);
MEM_freeN(eqcmd);
}
void SEQ_sound_equalizermodifier_init_data(SequenceModifierData *smd)
{
SoundEqualizerModifierData *semd = (SoundEqualizerModifierData *)smd;
SEQ_sound_equalizer_add(semd, SOUND_EQUALIZER_DEFAULT_MIN_FREQ, SOUND_EQUALIZER_DEFAULT_MAX_FREQ);
}
void SEQ_sound_equalizermodifier_free(SequenceModifierData *smd)
{
SoundEqualizerModifierData *semd = (SoundEqualizerModifierData *)smd;
EQCurveMappingData *eqcmd, *eqcmd_next;
for (eqcmd = semd->graphics.first; eqcmd; eqcmd = eqcmd_next) {
eqcmd_next = eqcmd->next;
BKE_curvemapping_free_data(&eqcmd->curve_mapping);
MEM_freeN(eqcmd);
}
BLI_listbase_clear(&semd->graphics);
}
void SEQ_sound_equalizermodifier_copy_data(struct SequenceModifierData *target,
struct SequenceModifierData *smd)
{
SoundEqualizerModifierData *semd = (SoundEqualizerModifierData *)smd;
SoundEqualizerModifierData *semd_target = (SoundEqualizerModifierData *)target;
EQCurveMappingData *eqcmd, *eqcmd_n;
BLI_listbase_clear(&semd_target->graphics);
for (eqcmd = semd->graphics.first; eqcmd; eqcmd = eqcmd->next) {
eqcmd_n = MEM_dupallocN(eqcmd);
BKE_curvemapping_copy_data(&eqcmd_n->curve_mapping, &eqcmd->curve_mapping);
eqcmd_n->next = eqcmd_n->prev = NULL;
BLI_addtail(&semd_target->graphics, eqcmd_n);
}
}
void *SEQ_sound_equalizermodifier_recreator(struct Sequence *seq,
struct SequenceModifierData *smd,
void *sound)
{
UNUSED_VARS(seq);
SoundEqualizerModifierData *semd = (SoundEqualizerModifierData *)smd;
// No Equalizer definition
if (BLI_listbase_is_empty(&semd->graphics)) {
return sound;
}
float *buf = (float *)MEM_callocN(sizeof(float) * SOUND_EQUALIZER_SIZE_DEFINITION,
"eqrecreator");
CurveMapping *eq_mapping;
CurveMap *cm;
float minX;
float maxX;
float interval = SOUND_EQUALIZER_DEFAULT_MAX_FREQ / (float)SOUND_EQUALIZER_SIZE_DEFINITION;
// Visit all equalizer definitions
LISTBASE_FOREACH (EQCurveMappingData *, mapping, &semd->graphics) {
eq_mapping = &mapping->curve_mapping;
BKE_curvemapping_init(eq_mapping);
cm = eq_mapping->cm;
minX = eq_mapping->curr.xmin;
maxX = eq_mapping->curr.xmax;
int idx = (int)ceil(minX / interval);
int i = idx;
for (; i * interval <= maxX && i < SOUND_EQUALIZER_SIZE_DEFINITION; i++) {
float freq = i * interval;
float val = BKE_curvemap_evaluateF(eq_mapping, cm, freq);
if (fabs(val) > SOUND_EQUALIZER_DEFAULT_MAX_DB)
val = (val / fabs(val)) * SOUND_EQUALIZER_DEFAULT_MAX_DB;
buf[i] = val;
/* To soften lower limit, but not the first position which is the constant value */
if (i == idx && i > 2) {
buf[i-1] = 0.5 * (buf[i] + buf[i-1]);
}
}
/* To soften higher limit */
if (i < SOUND_EQUALIZER_SIZE_DEFINITION)
buf[i] = 0.5 * (buf[i] + buf[i-1]);
}
AUD_Sound *equ = AUD_Sound_equalize(sound,
buf,
SOUND_EQUALIZER_SIZE_DEFINITION,
SOUND_EQUALIZER_DEFAULT_MAX_FREQ,
SOUND_EQUALIZER_SIZE_CONVERSION);
MEM_freeN(buf);
return equ;
}
const struct SoundModifierWorkerInfo *SEQ_sound_modifier_worker_info_get(int type)
{
for (int i = 0; workersSoundModifiers[i].type > 0; i++) {
if (workersSoundModifiers[i].type == type)
return &workersSoundModifiers[i];
}
return NULL;
}
void *SEQ_sound_modifier_recreator(struct Sequence *seq,
struct SequenceModifierData *smd,
void *sound)
{
if (!(smd->flag & SEQUENCE_MODIFIER_MUTE)) {
const SoundModifierWorkerInfo *smwi = SEQ_sound_modifier_worker_info_get(smd->type);
return smwi->recreator(seq, smd, sound);
}
return sound;
}