New upstream version 24.0.1+dfsg1

This commit is contained in:
Sebastian Ramacher 2019-09-22 23:19:10 +02:00
parent b14f9eae6d
commit 5a730d6ec3
842 changed files with 42245 additions and 33385 deletions

View file

@ -9,28 +9,28 @@
#define MSEC_TO_NSEC 1000000ULL
#endif
#define SETTING_DELAY_MS "delay_ms"
#define SETTING_DELAY_MS "delay_ms"
#define TEXT_DELAY_MS obs_module_text("DelayMs")
#define TEXT_DELAY_MS obs_module_text("DelayMs")
struct async_delay_data {
obs_source_t *context;
obs_source_t *context;
/* contains struct obs_source_frame* */
struct circlebuf video_frames;
struct circlebuf video_frames;
/* stores the audio data */
struct circlebuf audio_frames;
struct obs_audio_data audio_output;
struct circlebuf audio_frames;
struct obs_audio_data audio_output;
uint64_t last_video_ts;
uint64_t last_audio_ts;
uint64_t interval;
uint64_t samplerate;
bool video_delay_reached;
bool audio_delay_reached;
bool reset_video;
bool reset_audio;
uint64_t last_video_ts;
uint64_t last_audio_ts;
uint64_t interval;
uint64_t samplerate;
bool video_delay_reached;
bool audio_delay_reached;
bool reset_video;
bool reset_audio;
};
static const char *async_delay_filter_name(void *unused)
@ -40,13 +40,13 @@ static const char *async_delay_filter_name(void *unused)
}
static void free_video_data(struct async_delay_data *filter,
obs_source_t *parent)
obs_source_t *parent)
{
while (filter->video_frames.size) {
struct obs_source_frame *frame;
circlebuf_pop_front(&filter->video_frames, &frame,
sizeof(struct obs_source_frame*));
sizeof(struct obs_source_frame *));
obs_source_release_frame(parent, frame);
}
}
@ -64,7 +64,7 @@ static void free_audio_data(struct async_delay_data *filter)
struct obs_audio_data audio;
circlebuf_pop_front(&filter->audio_frames, &audio,
sizeof(struct obs_audio_data));
sizeof(struct obs_audio_data));
free_audio_packet(&audio);
}
}
@ -72,8 +72,9 @@ static void free_audio_data(struct async_delay_data *filter)
static void async_delay_filter_update(void *data, obs_data_t *settings)
{
struct async_delay_data *filter = data;
uint64_t new_interval = (uint64_t)obs_data_get_int(settings,
SETTING_DELAY_MS) * MSEC_TO_NSEC;
uint64_t new_interval =
(uint64_t)obs_data_get_int(settings, SETTING_DELAY_MS) *
MSEC_TO_NSEC;
if (new_interval < filter->interval)
free_video_data(filter, obs_filter_get_parent(filter->context));
@ -86,7 +87,7 @@ static void async_delay_filter_update(void *data, obs_data_t *settings)
}
static void *async_delay_filter_create(obs_data_t *settings,
obs_source_t *context)
obs_source_t *context)
{
struct async_delay_data *filter = bzalloc(sizeof(*filter));
struct obs_audio_info oai;
@ -114,8 +115,9 @@ static obs_properties_t *async_delay_filter_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
obs_properties_add_int(props, SETTING_DELAY_MS, TEXT_DELAY_MS,
0, 20000, 1);
obs_property_t *p = obs_properties_add_int(props, SETTING_DELAY_MS,
TEXT_DELAY_MS, 0, 20000, 1);
obs_property_int_set_suffix(p, " ms");
UNUSED_PARAMETER(data);
return props;
@ -138,8 +140,8 @@ static inline bool is_timestamp_jump(uint64_t ts, uint64_t prev_ts)
return ts < prev_ts || (ts - prev_ts) > SEC_TO_NSEC;
}
static struct obs_source_frame *async_delay_filter_video(void *data,
struct obs_source_frame *frame)
static struct obs_source_frame *
async_delay_filter_video(void *data, struct obs_source_frame *frame)
{
struct async_delay_data *filter = data;
obs_source_t *parent = obs_filter_get_parent(filter->context);
@ -156,16 +158,16 @@ static struct obs_source_frame *async_delay_filter_video(void *data,
filter->last_video_ts = frame->timestamp;
circlebuf_push_back(&filter->video_frames, &frame,
sizeof(struct obs_source_frame*));
sizeof(struct obs_source_frame *));
circlebuf_peek_front(&filter->video_frames, &output,
sizeof(struct obs_source_frame*));
sizeof(struct obs_source_frame *));
cur_interval = frame->timestamp - output->timestamp;
if (!filter->video_delay_reached && cur_interval < filter->interval)
return NULL;
circlebuf_pop_front(&filter->video_frames, NULL,
sizeof(struct obs_source_frame*));
sizeof(struct obs_source_frame *));
if (!filter->video_delay_reached)
filter->video_delay_reached = true;
@ -179,8 +181,8 @@ static struct obs_source_frame *async_delay_filter_video(void *data,
/* #define DELAY_AUDIO */
#ifdef DELAY_AUDIO
static struct obs_audio_data *async_delay_filter_audio(void *data,
struct obs_audio_data *audio)
static struct obs_audio_data *
async_delay_filter_audio(void *data, struct obs_audio_data *audio)
{
struct async_delay_data *filter = data;
struct obs_audio_data cached = *audio;
@ -204,8 +206,8 @@ static struct obs_audio_data *async_delay_filter_audio(void *data,
if (!audio->data[i])
break;
cached.data[i] = bmemdup(audio->data[i],
audio->frames * sizeof(float));
cached.data[i] =
bmemdup(audio->data[i], audio->frames * sizeof(float));
}
free_audio_packet(&filter->audio_output);
@ -228,17 +230,17 @@ static struct obs_audio_data *async_delay_filter_audio(void *data,
#endif
struct obs_source_info async_delay_filter = {
.id = "async_delay_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_ASYNC,
.get_name = async_delay_filter_name,
.create = async_delay_filter_create,
.destroy = async_delay_filter_destroy,
.update = async_delay_filter_update,
.get_properties = async_delay_filter_properties,
.filter_video = async_delay_filter_video,
.id = "async_delay_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_ASYNC,
.get_name = async_delay_filter_name,
.create = async_delay_filter_create,
.destroy = async_delay_filter_destroy,
.update = async_delay_filter_update,
.get_properties = async_delay_filter_properties,
.filter_video = async_delay_filter_video,
#ifdef DELAY_AUDIO
.filter_audio = async_delay_filter_audio,
.filter_audio = async_delay_filter_audio,
#endif
.filter_remove = async_delay_filter_remove
.filter_remove = async_delay_filter_remove,
};

View file

@ -3,6 +3,8 @@
#include <graphics/vec2.h>
#include <graphics/vec4.h>
/* clang-format off */
#define SETTING_OPACITY "opacity"
#define SETTING_CONTRAST "contrast"
#define SETTING_BRIGHTNESS "brightness"
@ -23,31 +25,33 @@
#define TEXT_SMOOTHNESS obs_module_text("Smoothness")
#define TEXT_SPILL obs_module_text("ColorSpillReduction")
/* clang-format on */
struct chroma_key_filter_data {
obs_source_t *context;
obs_source_t *context;
gs_effect_t *effect;
gs_effect_t *effect;
gs_eparam_t *color_param;
gs_eparam_t *contrast_param;
gs_eparam_t *brightness_param;
gs_eparam_t *gamma_param;
gs_eparam_t *color_param;
gs_eparam_t *contrast_param;
gs_eparam_t *brightness_param;
gs_eparam_t *gamma_param;
gs_eparam_t *pixel_size_param;
gs_eparam_t *chroma_param;
gs_eparam_t *similarity_param;
gs_eparam_t *smoothness_param;
gs_eparam_t *spill_param;
gs_eparam_t *pixel_size_param;
gs_eparam_t *chroma_param;
gs_eparam_t *similarity_param;
gs_eparam_t *smoothness_param;
gs_eparam_t *spill_param;
struct vec4 color;
float contrast;
float brightness;
float gamma;
struct vec4 color;
float contrast;
float brightness;
float gamma;
struct vec2 chroma;
float similarity;
float smoothness;
float spill;
struct vec2 chroma;
float similarity;
float smoothness;
float spill;
};
static const char *chroma_key_name(void *unused)
@ -56,23 +60,23 @@ static const char *chroma_key_name(void *unused)
return obs_module_text("ChromaKeyFilter");
}
static const float yuv_mat[16] = {0.182586f, -0.100644f, 0.439216f, 0.0f,
0.614231f, -0.338572f, -0.398942f, 0.0f,
0.062007f, 0.439216f, -0.040274f, 0.0f,
0.062745f, 0.501961f, 0.501961f, 1.0f};
static const float yuv_mat[16] = {0.182586f, -0.100644f, 0.439216f, 0.0f,
0.614231f, -0.338572f, -0.398942f, 0.0f,
0.062007f, 0.439216f, -0.040274f, 0.0f,
0.062745f, 0.501961f, 0.501961f, 1.0f};
static inline void color_settings_update(
struct chroma_key_filter_data *filter, obs_data_t *settings)
static inline void color_settings_update(struct chroma_key_filter_data *filter,
obs_data_t *settings)
{
uint32_t opacity = (uint32_t)obs_data_get_int(settings,
SETTING_OPACITY);
uint32_t opacity =
(uint32_t)obs_data_get_int(settings, SETTING_OPACITY);
uint32_t color = 0xFFFFFF | (((opacity * 255) / 100) << 24);
double contrast = obs_data_get_double(settings, SETTING_CONTRAST);
double brightness = obs_data_get_double(settings, SETTING_BRIGHTNESS);
double gamma = obs_data_get_double(settings, SETTING_GAMMA);
contrast = (contrast < 0.0) ?
(1.0 / (-contrast + 1.0)) : (contrast + 1.0);
contrast = (contrast < 0.0) ? (1.0 / (-contrast + 1.0))
: (contrast + 1.0);
brightness *= 0.5;
@ -85,16 +89,16 @@ static inline void color_settings_update(
vec4_from_rgba(&filter->color, color);
}
static inline void chroma_settings_update(
struct chroma_key_filter_data *filter, obs_data_t *settings)
static inline void chroma_settings_update(struct chroma_key_filter_data *filter,
obs_data_t *settings)
{
int64_t similarity = obs_data_get_int(settings, SETTING_SIMILARITY);
int64_t smoothness = obs_data_get_int(settings, SETTING_SMOOTHNESS);
int64_t spill = obs_data_get_int(settings, SETTING_SPILL);
uint32_t key_color = (uint32_t)obs_data_get_int(settings,
SETTING_KEY_COLOR);
const char *key_type = obs_data_get_string(settings,
SETTING_COLOR_TYPE);
uint32_t key_color =
(uint32_t)obs_data_get_int(settings, SETTING_KEY_COLOR);
const char *key_type =
obs_data_get_string(settings, SETTING_COLOR_TYPE);
struct vec4 key_rgb;
struct vec4 key_color_v4;
struct matrix4 yuv_mat_m4;
@ -150,24 +154,24 @@ static void *chroma_key_create(obs_data_t *settings, obs_source_t *context)
filter->effect = gs_effect_create_from_file(effect_path, NULL);
if (filter->effect) {
filter->color_param = gs_effect_get_param_by_name(
filter->effect, "color");
filter->contrast_param = gs_effect_get_param_by_name(
filter->effect, "contrast");
filter->color_param =
gs_effect_get_param_by_name(filter->effect, "color");
filter->contrast_param =
gs_effect_get_param_by_name(filter->effect, "contrast");
filter->brightness_param = gs_effect_get_param_by_name(
filter->effect, "brightness");
filter->gamma_param = gs_effect_get_param_by_name(
filter->effect, "gamma");
filter->effect, "brightness");
filter->gamma_param =
gs_effect_get_param_by_name(filter->effect, "gamma");
filter->chroma_param = gs_effect_get_param_by_name(
filter->effect, "chroma_key");
filter->effect, "chroma_key");
filter->pixel_size_param = gs_effect_get_param_by_name(
filter->effect, "pixel_size");
filter->effect, "pixel_size");
filter->similarity_param = gs_effect_get_param_by_name(
filter->effect, "similarity");
filter->effect, "similarity");
filter->smoothness_param = gs_effect_get_param_by_name(
filter->effect, "smoothness");
filter->spill_param = gs_effect_get_param_by_name(
filter->effect, "spill");
filter->effect, "smoothness");
filter->spill_param =
gs_effect_get_param_by_name(filter->effect, "spill");
}
obs_leave_graphics();
@ -192,7 +196,7 @@ static void chroma_key_render(void *data, gs_effect_t *effect)
struct vec2 pixel_size;
if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
OBS_ALLOW_DIRECT_RENDERING))
OBS_ALLOW_DIRECT_RENDERING))
return;
vec2_set(&pixel_size, 1.0f / (float)width, 1.0f / (float)height);
@ -213,13 +217,13 @@ static void chroma_key_render(void *data, gs_effect_t *effect)
}
static bool key_type_changed(obs_properties_t *props, obs_property_t *p,
obs_data_t *settings)
obs_data_t *settings)
{
const char *type = obs_data_get_string(settings, SETTING_COLOR_TYPE);
bool custom = strcmp(type, "custom") == 0;
obs_property_set_visible(obs_properties_get(props, SETTING_KEY_COLOR),
custom);
custom);
UNUSED_PARAMETER(p);
return true;
@ -229,9 +233,10 @@ static obs_properties_t *chroma_key_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
obs_property_t *p = obs_properties_add_list(props,
SETTING_COLOR_TYPE, TEXT_COLOR_TYPE,
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
obs_property_t *p = obs_properties_add_list(props, SETTING_COLOR_TYPE,
TEXT_COLOR_TYPE,
OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(p, obs_module_text("Green"), "green");
obs_property_list_add_string(p, obs_module_text("Blue"), "blue");
obs_property_list_add_string(p, obs_module_text("Magenta"), "magenta");
@ -241,20 +246,20 @@ static obs_properties_t *chroma_key_properties(void *data)
obs_properties_add_color(props, SETTING_KEY_COLOR, TEXT_KEY_COLOR);
obs_properties_add_int_slider(props, SETTING_SIMILARITY,
TEXT_SIMILARITY, 1, 1000, 1);
TEXT_SIMILARITY, 1, 1000, 1);
obs_properties_add_int_slider(props, SETTING_SMOOTHNESS,
TEXT_SMOOTHNESS, 1, 1000, 1);
obs_properties_add_int_slider(props, SETTING_SPILL,
TEXT_SPILL, 1, 1000, 1);
TEXT_SMOOTHNESS, 1, 1000, 1);
obs_properties_add_int_slider(props, SETTING_SPILL, TEXT_SPILL, 1, 1000,
1);
obs_properties_add_int_slider(props, SETTING_OPACITY, TEXT_OPACITY,
0, 100, 1);
obs_properties_add_float_slider(props, SETTING_CONTRAST,
TEXT_CONTRAST, -1.0, 1.0, 0.01);
obs_properties_add_int_slider(props, SETTING_OPACITY, TEXT_OPACITY, 0,
100, 1);
obs_properties_add_float_slider(props, SETTING_CONTRAST, TEXT_CONTRAST,
-1.0, 1.0, 0.01);
obs_properties_add_float_slider(props, SETTING_BRIGHTNESS,
TEXT_BRIGHTNESS, -1.0, 1.0, 0.01);
obs_properties_add_float_slider(props, SETTING_GAMMA,
TEXT_GAMMA, -1.0, 1.0, 0.01);
TEXT_BRIGHTNESS, -1.0, 1.0, 0.01);
obs_properties_add_float_slider(props, SETTING_GAMMA, TEXT_GAMMA, -1.0,
1.0, 0.01);
UNUSED_PARAMETER(data);
return props;
@ -274,14 +279,14 @@ static void chroma_key_defaults(obs_data_t *settings)
}
struct obs_source_info chroma_key_filter = {
.id = "chroma_key_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = chroma_key_name,
.create = chroma_key_create,
.destroy = chroma_key_destroy,
.video_render = chroma_key_render,
.update = chroma_key_update,
.get_properties = chroma_key_properties,
.get_defaults = chroma_key_defaults
.id = "chroma_key_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = chroma_key_name,
.create = chroma_key_create,
.destroy = chroma_key_destroy,
.video_render = chroma_key_render,
.update = chroma_key_update,
.get_properties = chroma_key_properties,
.get_defaults = chroma_key_defaults,
};

View file

@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <graphics/matrix4.h>
#include <graphics/quat.h>
/* clang-format off */
#define SETTING_GAMMA "gamma"
#define SETTING_CONTRAST "contrast"
@ -35,39 +36,41 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define TEXT_OPACITY obs_module_text("Opacity")
#define TEXT_COLOR obs_module_text("Color")
/* clang-format on */
struct color_correction_filter_data {
obs_source_t *context;
obs_source_t *context;
gs_effect_t *effect;
gs_effect_t *effect;
gs_eparam_t *gamma_param;
gs_eparam_t *final_matrix_param;
gs_eparam_t *gamma_param;
gs_eparam_t *final_matrix_param;
struct vec3 gamma;
float contrast;
float brightness;
float saturation;
float hue_shift;
float opacity;
struct vec4 color;
struct vec3 gamma;
float contrast;
float brightness;
float saturation;
float hue_shift;
float opacity;
struct vec4 color;
/* Pre-Computes */
struct matrix4 con_matrix;
struct matrix4 bright_matrix;
struct matrix4 sat_matrix;
struct matrix4 hue_op_matrix;
struct matrix4 color_matrix;
struct matrix4 final_matrix;
struct matrix4 con_matrix;
struct matrix4 bright_matrix;
struct matrix4 sat_matrix;
struct matrix4 hue_op_matrix;
struct matrix4 color_matrix;
struct matrix4 final_matrix;
struct vec3 rot_quaternion;
float rot_quaternion_w;
struct vec3 cross;
struct vec3 square;
struct vec3 wimag;
struct vec3 diag;
struct vec3 a_line;
struct vec3 b_line;
struct vec3 half_unit;
struct vec3 rot_quaternion;
float rot_quaternion_w;
struct vec3 cross;
struct vec3 square;
struct vec3 wimag;
struct vec3 diag;
struct vec3 a_line;
struct vec3 b_line;
struct vec3 half_unit;
};
static const float root3 = 0.57735f;
@ -101,22 +104,31 @@ static void color_correction_filter_update(void *data, obs_data_t *settings)
vec3_set(&filter->gamma, (float)gamma, (float)gamma, (float)gamma);
/* Build our contrast number. */
filter->contrast = (float)obs_data_get_double(settings,
SETTING_CONTRAST) + 1.0f;
filter->contrast =
(float)obs_data_get_double(settings, SETTING_CONTRAST) + 1.0f;
float one_minus_con = (1.0f - filter->contrast) / 2.0f;
/* Now let's build our Contrast matrix. */
filter->con_matrix = (struct matrix4)
{
filter->contrast, 0.0f, 0.0f, 0.0f,
0.0f, filter->contrast, 0.0f, 0.0f,
0.0f, 0.0f, filter->contrast, 0.0f,
one_minus_con, one_minus_con, one_minus_con, 1.0f
};
filter->con_matrix = (struct matrix4){filter->contrast,
0.0f,
0.0f,
0.0f,
0.0f,
filter->contrast,
0.0f,
0.0f,
0.0f,
0.0f,
filter->contrast,
0.0f,
one_minus_con,
one_minus_con,
one_minus_con,
1.0f};
/* Build our brightness number. */
filter->brightness = (float)obs_data_get_double(settings,
SETTING_BRIGHTNESS);
filter->brightness =
(float)obs_data_get_double(settings, SETTING_BRIGHTNESS);
/*
* Now let's build our Brightness matrix.
@ -129,49 +141,57 @@ static void color_correction_filter_update(void *data, obs_data_t *settings)
filter->bright_matrix.t.z = filter->brightness;
/* Build our Saturation number. */
filter->saturation = (float)obs_data_get_double(settings,
SETTING_SATURATION) + 1.0f;
filter->saturation =
(float)obs_data_get_double(settings, SETTING_SATURATION) + 1.0f;
/* Factor in the selected color weights. */
float one_minus_sat_red = (1.0f - filter->saturation) * red_weight;
float one_minus_sat_green = (1.0f - filter->saturation) * green_weight;
float one_minus_sat_blue = (1.0f - filter->saturation) * blue_weight;
float sat_val_red = one_minus_sat_red + filter->saturation;
float sat_val_red = one_minus_sat_red + filter->saturation;
float sat_val_green = one_minus_sat_green + filter->saturation;
float sat_val_blue = one_minus_sat_blue + filter->saturation;
float sat_val_blue = one_minus_sat_blue + filter->saturation;
/* Now we build our Saturation matrix. */
filter->sat_matrix = (struct matrix4)
{
sat_val_red, one_minus_sat_red, one_minus_sat_red, 0.0f,
one_minus_sat_green, sat_val_green, one_minus_sat_green, 0.0f,
one_minus_sat_blue, one_minus_sat_blue, sat_val_blue, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
filter->sat_matrix = (struct matrix4){sat_val_red,
one_minus_sat_red,
one_minus_sat_red,
0.0f,
one_minus_sat_green,
sat_val_green,
one_minus_sat_green,
0.0f,
one_minus_sat_blue,
one_minus_sat_blue,
sat_val_blue,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f};
/* Build our Hue number. */
filter->hue_shift = (float)obs_data_get_double(settings,
SETTING_HUESHIFT);
filter->hue_shift =
(float)obs_data_get_double(settings, SETTING_HUESHIFT);
/* Build our Transparency number. */
filter->opacity = (float)obs_data_get_int(settings,
SETTING_OPACITY) * 0.01f;
filter->opacity =
(float)obs_data_get_int(settings, SETTING_OPACITY) * 0.01f;
/* Hue is the radian of 0 to 360 degrees. */
float half_angle = 0.5f * (float)(filter->hue_shift / (180.0f / M_PI));
/* Pseudo-Quaternion To Matrix. */
float rot_quad1 = root3 * (float)sin(half_angle);
vec3_set(&filter->rot_quaternion, rot_quad1, rot_quad1,
rot_quad1);
vec3_set(&filter->rot_quaternion, rot_quad1, rot_quad1, rot_quad1);
filter->rot_quaternion_w = (float)cos(half_angle);
vec3_mul(&filter->cross, &filter->rot_quaternion,
&filter->rot_quaternion);
&filter->rot_quaternion);
vec3_mul(&filter->square, &filter->rot_quaternion,
&filter->rot_quaternion);
&filter->rot_quaternion);
vec3_mulf(&filter->wimag, &filter->rot_quaternion,
filter->rot_quaternion_w);
filter->rot_quaternion_w);
vec3_mulf(&filter->square, &filter->square, 2.0f);
vec3_sub(&filter->diag, &filter->half_unit, &filter->square);
@ -179,29 +199,28 @@ static void color_correction_filter_update(void *data, obs_data_t *settings)
vec3_sub(&filter->b_line, &filter->cross, &filter->wimag);
/* Now we build our Hue and Opacity matrix. */
filter->hue_op_matrix = (struct matrix4)
{
filter->diag.x * 2.0f,
filter->b_line.z * 2.0f,
filter->a_line.y * 2.0f,
0.0f,
filter->hue_op_matrix = (struct matrix4){filter->diag.x * 2.0f,
filter->b_line.z * 2.0f,
filter->a_line.y * 2.0f,
0.0f,
filter->a_line.z * 2.0f,
filter->diag.y * 2.0f,
filter->b_line.x * 2.0f,
0.0f,
filter->a_line.z * 2.0f,
filter->diag.y * 2.0f,
filter->b_line.x * 2.0f,
0.0f,
filter->b_line.y * 2.0f,
filter->a_line.x * 2.0f,
filter->diag.z * 2.0f,
0.0f,
filter->b_line.y * 2.0f,
filter->a_line.x * 2.0f,
filter->diag.z * 2.0f,
0.0f,
0.0f, 0.0f, 0.0f, filter->opacity
};
0.0f,
0.0f,
0.0f,
filter->opacity};
/* Now get the overlay color data. */
uint32_t color = (uint32_t)obs_data_get_int(settings,
SETTING_COLOR);
uint32_t color = (uint32_t)obs_data_get_int(settings, SETTING_COLOR);
vec4_from_rgba(&filter->color, color);
/*
@ -214,26 +233,22 @@ static void color_correction_filter_update(void *data, obs_data_t *settings)
filter->color_matrix.y.y = filter->color.y;
filter->color_matrix.z.z = filter->color.z;
filter->color_matrix.t.x = filter->color.w *
filter->color.x;
filter->color_matrix.t.y = filter->color.w *
filter->color.y;
filter->color_matrix.t.z = filter->color.w *
filter->color.z;
filter->color_matrix.t.x = filter->color.w * filter->color.x;
filter->color_matrix.t.y = filter->color.w * filter->color.y;
filter->color_matrix.t.z = filter->color.w * filter->color.z;
/* First we apply the Contrast & Brightness matrix. */
matrix4_mul(&filter->final_matrix, &filter->bright_matrix,
&filter->con_matrix);
&filter->con_matrix);
/* Now we apply the Saturation matrix. */
matrix4_mul(&filter->final_matrix, &filter->final_matrix,
&filter->sat_matrix);
&filter->sat_matrix);
/* Next we apply the Hue+Opacity matrix. */
matrix4_mul(&filter->final_matrix, &filter->final_matrix,
&filter->hue_op_matrix);
&filter->hue_op_matrix);
/* Lastly we apply the Color Wash matrix. */
matrix4_mul(&filter->final_matrix, &filter->final_matrix,
&filter->color_matrix);
&filter->color_matrix);
}
/*
@ -261,7 +276,7 @@ static void color_correction_filter_destroy(void *data)
* actual rendering code.
*/
static void *color_correction_filter_create(obs_data_t *settings,
obs_source_t *context)
obs_source_t *context)
{
/*
* Because of limitations of pre-c99 compilers, you can't create an
@ -294,9 +309,9 @@ static void *color_correction_filter_create(obs_data_t *settings,
/* If the filter is active pass the parameters to the filter. */
if (filter->effect) {
filter->gamma_param = gs_effect_get_param_by_name(
filter->effect, SETTING_GAMMA);
filter->effect, SETTING_GAMMA);
filter->final_matrix_param = gs_effect_get_param_by_name(
filter->effect, "color_matrix");
filter->effect, "color_matrix");
}
obs_leave_graphics();
@ -328,12 +343,13 @@ static void color_correction_filter_render(void *data, gs_effect_t *effect)
struct color_correction_filter_data *filter = data;
if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
OBS_ALLOW_DIRECT_RENDERING))
OBS_ALLOW_DIRECT_RENDERING))
return;
/* Now pass the interface variables to the .effect file. */
gs_effect_set_vec3(filter->gamma_param, &filter->gamma);
gs_effect_set_matrix4(filter->final_matrix_param, &filter->final_matrix);
gs_effect_set_matrix4(filter->final_matrix_param,
&filter->final_matrix);
obs_source_process_filter_end(filter->context, filter->effect, 0, 0);
@ -350,19 +366,19 @@ static obs_properties_t *color_correction_filter_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
obs_properties_add_float_slider(props, SETTING_GAMMA,
TEXT_GAMMA, -3.0, 3.0, 0.01);
obs_properties_add_float_slider(props, SETTING_GAMMA, TEXT_GAMMA, -3.0,
3.0, 0.01);
obs_properties_add_float_slider(props, SETTING_CONTRAST,
TEXT_CONTRAST, -2.0, 2.0, 0.01);
obs_properties_add_float_slider(props, SETTING_CONTRAST, TEXT_CONTRAST,
-2.0, 2.0, 0.01);
obs_properties_add_float_slider(props, SETTING_BRIGHTNESS,
TEXT_BRIGHTNESS, -1.0, 1.0, 0.01);
TEXT_BRIGHTNESS, -1.0, 1.0, 0.01);
obs_properties_add_float_slider(props, SETTING_SATURATION,
TEXT_SATURATION, -1.0, 5.0, 0.01);
obs_properties_add_float_slider(props, SETTING_HUESHIFT,
TEXT_HUESHIFT, -180.0, 180.0, 0.01);
obs_properties_add_int_slider(props, SETTING_OPACITY,
TEXT_OPACITY, 0, 100, 1);
TEXT_SATURATION, -1.0, 5.0, 0.01);
obs_properties_add_float_slider(props, SETTING_HUESHIFT, TEXT_HUESHIFT,
-180.0, 180.0, 0.01);
obs_properties_add_int_slider(props, SETTING_OPACITY, TEXT_OPACITY, 0,
100, 1);
obs_properties_add_color(props, SETTING_COLOR, TEXT_COLOR);
@ -382,8 +398,7 @@ static void color_correction_filter_defaults(obs_data_t *settings)
obs_data_set_default_double(settings, SETTING_GAMMA, 0.0);
obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0);
obs_data_set_default_double(settings, SETTING_BRIGHTNESS, 0.0);
obs_data_set_default_double(settings,
SETTING_SATURATION, 0.0);
obs_data_set_default_double(settings, SETTING_SATURATION, 0.0);
obs_data_set_default_double(settings, SETTING_HUESHIFT, 0.0);
obs_data_set_default_double(settings, SETTING_OPACITY, 100.0);
obs_data_set_default_int(settings, SETTING_COLOR, 0xFFFFFF);
@ -409,5 +424,5 @@ struct obs_source_info color_filter = {
.video_render = color_correction_filter_render,
.update = color_correction_filter_update,
.get_properties = color_correction_filter_properties,
.get_defaults = color_correction_filter_defaults
.get_defaults = color_correction_filter_defaults,
};

View file

@ -2,20 +2,24 @@
#include <graphics/image-file.h>
#include <util/dstr.h>
/* clang-format off */
#define SETTING_IMAGE_PATH "image_path"
#define SETTING_CLUT_AMOUNT "clut_amount"
#define TEXT_IMAGE_PATH obs_module_text("Path")
#define TEXT_AMOUNT obs_module_text("Amount")
struct lut_filter_data {
obs_source_t *context;
gs_effect_t *effect;
gs_texture_t *target;
gs_image_file_t image;
/* clang-format on */
char *file;
float clut_amount;
struct lut_filter_data {
obs_source_t *context;
gs_effect_t *effect;
gs_texture_t *target;
gs_image_file_t image;
char *file;
float clut_amount;
};
static const char *color_grade_filter_get_name(void *unused)
@ -89,9 +93,9 @@ static obs_properties_t *color_grade_filter_properties(void *data)
dstr_resize(&path, slash - path.array + 1);
obs_properties_add_path(props, SETTING_IMAGE_PATH, TEXT_IMAGE_PATH,
OBS_PATH_FILE, filter_str.array, path.array);
obs_properties_add_float_slider(props, SETTING_CLUT_AMOUNT,
TEXT_AMOUNT, 0, 1, 0.01);
OBS_PATH_FILE, filter_str.array, path.array);
obs_properties_add_float_slider(props, SETTING_CLUT_AMOUNT, TEXT_AMOUNT,
0, 1, 0.01);
dstr_free(&filter_str);
dstr_free(&path);
@ -100,8 +104,8 @@ static obs_properties_t *color_grade_filter_properties(void *data)
return props;
}
static void *color_grade_filter_create(
obs_data_t *settings, obs_source_t *context)
static void *color_grade_filter_create(obs_data_t *settings,
obs_source_t *context)
{
struct lut_filter_data *filter =
bzalloc(sizeof(struct lut_filter_data));
@ -136,7 +140,7 @@ static void color_grade_filter_render(void *data, gs_effect_t *effect)
}
if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
OBS_ALLOW_DIRECT_RENDERING))
OBS_ALLOW_DIRECT_RENDERING))
return;
param = gs_effect_get_param_by_name(filter->effect, "clut");
@ -151,14 +155,14 @@ static void color_grade_filter_render(void *data, gs_effect_t *effect)
}
struct obs_source_info color_grade_filter = {
.id = "clut_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = color_grade_filter_get_name,
.create = color_grade_filter_create,
.destroy = color_grade_filter_destroy,
.update = color_grade_filter_update,
.get_defaults = color_grade_filter_defaults,
.get_properties = color_grade_filter_properties,
.video_render = color_grade_filter_render
.id = "clut_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = color_grade_filter_get_name,
.create = color_grade_filter_create,
.destroy = color_grade_filter_destroy,
.update = color_grade_filter_update,
.get_defaults = color_grade_filter_defaults,
.get_properties = color_grade_filter_properties,
.video_render = color_grade_filter_render,
};

View file

@ -3,6 +3,8 @@
#include <graphics/vec2.h>
#include <graphics/vec4.h>
/* clang-format off */
#define SETTING_OPACITY "opacity"
#define SETTING_CONTRAST "contrast"
#define SETTING_BRIGHTNESS "brightness"
@ -21,28 +23,30 @@
#define TEXT_SIMILARITY obs_module_text("Similarity")
#define TEXT_SMOOTHNESS obs_module_text("Smoothness")
/* clang-format on */
struct color_key_filter_data {
obs_source_t *context;
obs_source_t *context;
gs_effect_t *effect;
gs_effect_t *effect;
gs_eparam_t *color_param;
gs_eparam_t *contrast_param;
gs_eparam_t *brightness_param;
gs_eparam_t *gamma_param;
gs_eparam_t *color_param;
gs_eparam_t *contrast_param;
gs_eparam_t *brightness_param;
gs_eparam_t *gamma_param;
gs_eparam_t *key_color_param;
gs_eparam_t *similarity_param;
gs_eparam_t *smoothness_param;
gs_eparam_t *key_color_param;
gs_eparam_t *similarity_param;
gs_eparam_t *smoothness_param;
struct vec4 color;
float contrast;
float brightness;
float gamma;
struct vec4 color;
float contrast;
float brightness;
float gamma;
struct vec4 key_color;
float similarity;
float smoothness;
struct vec4 key_color;
float similarity;
float smoothness;
};
static const char *color_key_name(void *unused)
@ -51,18 +55,18 @@ static const char *color_key_name(void *unused)
return obs_module_text("ColorKeyFilter");
}
static inline void color_settings_update(
struct color_key_filter_data *filter, obs_data_t *settings)
static inline void color_settings_update(struct color_key_filter_data *filter,
obs_data_t *settings)
{
uint32_t opacity = (uint32_t)obs_data_get_int(settings,
SETTING_OPACITY);
uint32_t opacity =
(uint32_t)obs_data_get_int(settings, SETTING_OPACITY);
uint32_t color = 0xFFFFFF | (((opacity * 255) / 100) << 24);
double contrast = obs_data_get_double(settings, SETTING_CONTRAST);
double brightness = obs_data_get_double(settings, SETTING_BRIGHTNESS);
double gamma = obs_data_get_double(settings, SETTING_GAMMA);
contrast = (contrast < 0.0) ?
(1.0 / (-contrast + 1.0)) : (contrast + 1.0);
contrast = (contrast < 0.0) ? (1.0 / (-contrast + 1.0))
: (contrast + 1.0);
brightness *= 0.5;
@ -75,15 +79,15 @@ static inline void color_settings_update(
vec4_from_rgba(&filter->color, color);
}
static inline void key_settings_update(
struct color_key_filter_data *filter, obs_data_t *settings)
static inline void key_settings_update(struct color_key_filter_data *filter,
obs_data_t *settings)
{
int64_t similarity = obs_data_get_int(settings, SETTING_SIMILARITY);
int64_t smoothness = obs_data_get_int(settings, SETTING_SMOOTHNESS);
uint32_t key_color = (uint32_t)obs_data_get_int(settings,
SETTING_KEY_COLOR);
const char *key_type = obs_data_get_string(settings,
SETTING_COLOR_TYPE);
uint32_t key_color =
(uint32_t)obs_data_get_int(settings, SETTING_KEY_COLOR);
const char *key_type =
obs_data_get_string(settings, SETTING_COLOR_TYPE);
if (strcmp(key_type, "green") == 0)
key_color = 0x00FF00;
@ -133,20 +137,20 @@ static void *color_key_create(obs_data_t *settings, obs_source_t *context)
filter->effect = gs_effect_create_from_file(effect_path, NULL);
if (filter->effect) {
filter->color_param = gs_effect_get_param_by_name(
filter->effect, "color");
filter->contrast_param = gs_effect_get_param_by_name(
filter->effect, "contrast");
filter->color_param =
gs_effect_get_param_by_name(filter->effect, "color");
filter->contrast_param =
gs_effect_get_param_by_name(filter->effect, "contrast");
filter->brightness_param = gs_effect_get_param_by_name(
filter->effect, "brightness");
filter->gamma_param = gs_effect_get_param_by_name(
filter->effect, "gamma");
filter->effect, "brightness");
filter->gamma_param =
gs_effect_get_param_by_name(filter->effect, "gamma");
filter->key_color_param = gs_effect_get_param_by_name(
filter->effect, "key_color");
filter->effect, "key_color");
filter->similarity_param = gs_effect_get_param_by_name(
filter->effect, "similarity");
filter->effect, "similarity");
filter->smoothness_param = gs_effect_get_param_by_name(
filter->effect, "smoothness");
filter->effect, "smoothness");
}
obs_leave_graphics();
@ -167,7 +171,7 @@ static void color_key_render(void *data, gs_effect_t *effect)
struct color_key_filter_data *filter = data;
if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
OBS_ALLOW_DIRECT_RENDERING))
OBS_ALLOW_DIRECT_RENDERING))
return;
gs_effect_set_vec4(filter->color_param, &filter->color);
@ -184,13 +188,13 @@ static void color_key_render(void *data, gs_effect_t *effect)
}
static bool key_type_changed(obs_properties_t *props, obs_property_t *p,
obs_data_t *settings)
obs_data_t *settings)
{
const char *type = obs_data_get_string(settings, SETTING_COLOR_TYPE);
bool custom = strcmp(type, "custom") == 0;
obs_property_set_visible(obs_properties_get(props, SETTING_KEY_COLOR),
custom);
custom);
UNUSED_PARAMETER(p);
return true;
@ -200,32 +204,33 @@ static obs_properties_t *color_key_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
obs_property_t *p = obs_properties_add_list(props,
SETTING_COLOR_TYPE, TEXT_COLOR_TYPE,
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
obs_property_t *p = obs_properties_add_list(props, SETTING_COLOR_TYPE,
TEXT_COLOR_TYPE,
OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(p, obs_module_text("Green"), "green");
obs_property_list_add_string(p, obs_module_text("Blue"), "blue");
obs_property_list_add_string(p, obs_module_text("Red"), "red");
obs_property_list_add_string(p, obs_module_text("Magenta"), "magenta");
obs_property_list_add_string(p, obs_module_text("CustomColor"),
"custom");
"custom");
obs_property_set_modified_callback(p, key_type_changed);
obs_properties_add_color(props, SETTING_KEY_COLOR, TEXT_KEY_COLOR);
obs_properties_add_int_slider(props, SETTING_SIMILARITY,
TEXT_SIMILARITY, 1, 1000, 1);
TEXT_SIMILARITY, 1, 1000, 1);
obs_properties_add_int_slider(props, SETTING_SMOOTHNESS,
TEXT_SMOOTHNESS, 1, 1000, 1);
TEXT_SMOOTHNESS, 1, 1000, 1);
obs_properties_add_int_slider(props, SETTING_OPACITY, TEXT_OPACITY,
0, 100, 1);
obs_properties_add_float_slider(props, SETTING_CONTRAST,
TEXT_CONTRAST, -1.0, 1.0, 0.01);
obs_properties_add_int_slider(props, SETTING_OPACITY, TEXT_OPACITY, 0,
100, 1);
obs_properties_add_float_slider(props, SETTING_CONTRAST, TEXT_CONTRAST,
-1.0, 1.0, 0.01);
obs_properties_add_float_slider(props, SETTING_BRIGHTNESS,
TEXT_BRIGHTNESS, -1.0, 1.0, 0.01);
obs_properties_add_float_slider(props, SETTING_GAMMA,
TEXT_GAMMA, -1.0, 1.0, 0.01);
TEXT_BRIGHTNESS, -1.0, 1.0, 0.01);
obs_properties_add_float_slider(props, SETTING_GAMMA, TEXT_GAMMA, -1.0,
1.0, 0.01);
UNUSED_PARAMETER(data);
return props;
@ -244,14 +249,14 @@ static void color_key_defaults(obs_data_t *settings)
}
struct obs_source_info color_key_filter = {
.id = "color_key_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = color_key_name,
.create = color_key_create,
.destroy = color_key_destroy,
.video_render = color_key_render,
.update = color_key_update,
.get_properties = color_key_properties,
.get_defaults = color_key_defaults
.id = "color_key_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = color_key_name,
.create = color_key_create,
.destroy = color_key_destroy,
.video_render = color_key_render,
.update = color_key_update,
.get_properties = color_key_properties,
.get_defaults = color_key_defaults,
};

View file

@ -10,21 +10,23 @@
/* -------------------------------------------------------- */
#define do_log(level, format, ...) \
#define do_log(level, format, ...) \
blog(level, "[compressor: '%s'] " format, \
obs_source_get_name(cd->context), ##__VA_ARGS__)
obs_source_get_name(cd->context), ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
#ifdef _DEBUG
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
#else
#define debug(format, ...)
#endif
/* -------------------------------------------------------- */
/* clang-format off */
#define S_RATIO "ratio"
#define S_THRESHOLD "threshold"
#define S_ATTACK_TIME "attack_time"
@ -54,6 +56,8 @@
#define MS_IN_S 1000
#define MS_IN_S_F ((float)MS_IN_S)
/* clang-format on */
/* -------------------------------------------------------- */
struct compressor_data {
@ -93,7 +97,7 @@ static inline obs_source_t *get_sidechain(struct compressor_data *cd)
}
static inline void get_sidechain_data(struct compressor_data *cd,
const uint32_t num_samples)
const uint32_t num_samples)
{
size_t data_size = cd->envelope_buf_len * sizeof(float);
if (!data_size)
@ -110,7 +114,7 @@ static inline void get_sidechain_data(struct compressor_data *cd,
for (size_t i = 0; i < cd->num_channels; i++)
circlebuf_pop_front(&cd->sidechain_data[i],
cd->sidechain_buf[i], data_size);
cd->sidechain_buf[i], data_size);
pthread_mutex_unlock(&cd->sidechain_mutex);
return;
@ -126,8 +130,8 @@ static void resize_env_buffer(struct compressor_data *cd, size_t len)
cd->envelope_buf = brealloc(cd->envelope_buf, len * sizeof(float));
for (size_t i = 0; i < cd->num_channels; i++)
cd->sidechain_buf[i] = brealloc(cd->sidechain_buf[i],
len * sizeof(float));
cd->sidechain_buf[i] =
brealloc(cd->sidechain_buf[i], len * sizeof(float));
}
static inline float gain_coefficient(uint32_t sample_rate, float time)
@ -142,7 +146,7 @@ static const char *compressor_name(void *unused)
}
static void sidechain_capture(void *param, obs_source_t *source,
const struct audio_data *audio_data, bool muted)
const struct audio_data *audio_data, bool muted)
{
struct compressor_data *cd = param;
@ -161,20 +165,21 @@ static void sidechain_capture(void *param, obs_source_t *source,
if (cd->sidechain_data[0].size > expected_size * 2) {
for (size_t i = 0; i < cd->num_channels; i++) {
circlebuf_pop_front(&cd->sidechain_data[i], NULL,
expected_size);
expected_size);
}
}
if (muted) {
for (size_t i = 0; i < cd->num_channels; i++) {
circlebuf_push_back_zero(&cd->sidechain_data[i],
audio_data->frames * sizeof(float));
audio_data->frames *
sizeof(float));
}
} else {
for (size_t i = 0; i < cd->num_channels; i++) {
circlebuf_push_back(&cd->sidechain_data[i],
audio_data->data[i],
audio_data->frames * sizeof(float));
audio_data->data[i],
audio_data->frames * sizeof(float));
}
}
@ -188,30 +193,27 @@ static void compressor_update(void *data, obs_data_t *s)
const uint32_t sample_rate =
audio_output_get_sample_rate(obs_get_audio());
const size_t num_channels =
audio_output_get_channels(obs_get_audio());
const float attack_time_ms =
(float)obs_data_get_int(s, S_ATTACK_TIME);
const size_t num_channels = audio_output_get_channels(obs_get_audio());
const float attack_time_ms = (float)obs_data_get_int(s, S_ATTACK_TIME);
const float release_time_ms =
(float)obs_data_get_int(s, S_RELEASE_TIME);
const float output_gain_db =
(float)obs_data_get_double(s, S_OUTPUT_GAIN);
const char *sidechain_name =
obs_data_get_string(s, S_SIDECHAIN_SOURCE);
const char *sidechain_name = obs_data_get_string(s, S_SIDECHAIN_SOURCE);
cd->ratio = (float)obs_data_get_double(s, S_RATIO);
cd->threshold = (float)obs_data_get_double(s, S_THRESHOLD);
cd->attack_gain = gain_coefficient(sample_rate,
attack_time_ms / MS_IN_S_F);
cd->release_gain = gain_coefficient(sample_rate,
release_time_ms / MS_IN_S_F);
cd->attack_gain =
gain_coefficient(sample_rate, attack_time_ms / MS_IN_S_F);
cd->release_gain =
gain_coefficient(sample_rate, release_time_ms / MS_IN_S_F);
cd->output_gain = db_to_mul(output_gain_db);
cd->num_channels = num_channels;
cd->sample_rate = sample_rate;
cd->slope = 1.0f - (1.0f / cd->ratio);
bool valid_sidechain =
*sidechain_name && strcmp(sidechain_name, "none") != 0;
bool valid_sidechain = *sidechain_name &&
strcmp(sidechain_name, "none") != 0;
obs_weak_source_t *old_weak_sidechain = NULL;
pthread_mutex_lock(&cd->sidechain_update_mutex);
@ -246,8 +248,8 @@ static void compressor_update(void *data, obs_data_t *s)
obs_weak_source_get_source(old_weak_sidechain);
if (old_sidechain) {
obs_source_remove_audio_capture_callback(old_sidechain,
sidechain_capture, cd);
obs_source_remove_audio_capture_callback(
old_sidechain, sidechain_capture, cd);
obs_source_release(old_sidechain);
}
@ -288,8 +290,8 @@ static void compressor_destroy(void *data)
if (cd->weak_sidechain) {
obs_source_t *sidechain = get_sidechain(cd);
if (sidechain) {
obs_source_remove_audio_capture_callback(sidechain,
sidechain_capture, cd);
obs_source_remove_audio_capture_callback(
sidechain, sidechain_capture, cd);
obs_source_release(sidechain);
}
@ -308,8 +310,8 @@ static void compressor_destroy(void *data)
bfree(cd);
}
static void analyze_envelope(struct compressor_data *cd,
float **samples, const uint32_t num_samples)
static void analyze_envelope(struct compressor_data *cd, float **samples,
const uint32_t num_samples)
{
if (cd->envelope_buf_len < num_samples) {
resize_env_buffer(cd, num_samples);
@ -339,7 +341,7 @@ static void analyze_envelope(struct compressor_data *cd,
}
static void analyze_sidechain(struct compressor_data *cd,
const uint32_t num_samples)
const uint32_t num_samples)
{
if (cd->envelope_buf_len < num_samples) {
resize_env_buffer(cd, num_samples);
@ -359,7 +361,7 @@ static void analyze_sidechain(struct compressor_data *cd,
float *envelope_buf = cd->envelope_buf;
float env = cd->envelope;
for (uint32_t i = 0; i < num_samples; ++i) {
const float env_in = fabsf(sidechain_buf[chan][i]);
const float env_in = fabsf(sidechain_buf[chan][i]);
if (env < env_in) {
env = env_in + attack_gain * (env - env_in);
@ -373,7 +375,7 @@ static void analyze_sidechain(struct compressor_data *cd,
}
static inline void process_compression(const struct compressor_data *cd,
float **samples, uint32_t num_samples)
float **samples, uint32_t num_samples)
{
for (size_t i = 0; i < num_samples; ++i) {
const float env_db = mul_to_db(cd->envelope_buf[i]);
@ -407,10 +409,12 @@ static void compressor_tick(void *data, float seconds)
pthread_mutex_unlock(&cd->sidechain_update_mutex);
if (new_name) {
obs_source_t *sidechain = new_name && *new_name ?
obs_get_source_by_name(new_name) : NULL;
obs_weak_source_t *weak_sidechain = sidechain ?
obs_source_get_weak_source(sidechain) : NULL;
obs_source_t *sidechain =
new_name && *new_name ? obs_get_source_by_name(new_name)
: NULL;
obs_weak_source_t *weak_sidechain =
sidechain ? obs_source_get_weak_source(sidechain)
: NULL;
pthread_mutex_lock(&cd->sidechain_update_mutex);
@ -423,8 +427,8 @@ static void compressor_tick(void *data, float seconds)
pthread_mutex_unlock(&cd->sidechain_update_mutex);
if (sidechain) {
obs_source_add_audio_capture_callback(sidechain,
sidechain_capture, cd);
obs_source_add_audio_capture_callback(
sidechain, sidechain_capture, cd);
obs_weak_source_release(weak_sidechain);
obs_source_release(sidechain);
@ -436,8 +440,8 @@ static void compressor_tick(void *data, float seconds)
UNUSED_PARAMETER(seconds);
}
static struct obs_audio_data *compressor_filter_audio(void *data,
struct obs_audio_data *audio)
static struct obs_audio_data *
compressor_filter_audio(void *data, struct obs_audio_data *audio)
{
struct compressor_data *cd = data;
@ -445,7 +449,7 @@ static struct obs_audio_data *compressor_filter_audio(void *data,
if (num_samples == 0)
return audio;
float **samples = (float**)audio->data;
float **samples = (float **)audio->data;
pthread_mutex_lock(&cd->sidechain_update_mutex);
obs_weak_source_t *weak_sidechain = cd->weak_sidechain;
@ -495,24 +499,35 @@ static obs_properties_t *compressor_properties(void *data)
struct compressor_data *cd = data;
obs_properties_t *props = obs_properties_create();
obs_source_t *parent = NULL;
obs_property_t *p;
if (cd)
parent = obs_filter_get_parent(cd->context);
obs_properties_add_float_slider(props, S_RATIO,
TEXT_RATIO, MIN_RATIO, MAX_RATIO, 0.5);
obs_properties_add_float_slider(props, S_THRESHOLD,
TEXT_THRESHOLD, MIN_THRESHOLD_DB, MAX_THRESHOLD_DB, 0.1);
obs_properties_add_int_slider(props, S_ATTACK_TIME,
TEXT_ATTACK_TIME, MIN_ATK_RLS_MS, MAX_ATK_MS, 1);
obs_properties_add_int_slider(props, S_RELEASE_TIME,
TEXT_RELEASE_TIME, MIN_ATK_RLS_MS, MAX_RLS_MS, 1);
obs_properties_add_float_slider(props, S_OUTPUT_GAIN,
TEXT_OUTPUT_GAIN, MIN_OUTPUT_GAIN_DB, MAX_OUTPUT_GAIN_DB, 0.1);
p = obs_properties_add_float_slider(props, S_RATIO, TEXT_RATIO,
MIN_RATIO, MAX_RATIO, 0.5);
obs_property_float_set_suffix(p, ":1");
p = obs_properties_add_float_slider(props, S_THRESHOLD, TEXT_THRESHOLD,
MIN_THRESHOLD_DB, MAX_THRESHOLD_DB,
0.1);
obs_property_float_set_suffix(p, " dB");
p = obs_properties_add_int_slider(props, S_ATTACK_TIME,
TEXT_ATTACK_TIME, MIN_ATK_RLS_MS,
MAX_ATK_MS, 1);
obs_property_int_set_suffix(p, " ms");
p = obs_properties_add_int_slider(props, S_RELEASE_TIME,
TEXT_RELEASE_TIME, MIN_ATK_RLS_MS,
MAX_RLS_MS, 1);
obs_property_int_set_suffix(p, " ms");
p = obs_properties_add_float_slider(props, S_OUTPUT_GAIN,
TEXT_OUTPUT_GAIN,
MIN_OUTPUT_GAIN_DB,
MAX_OUTPUT_GAIN_DB, 0.1);
obs_property_float_set_suffix(p, " dB");
obs_property_t *sources = obs_properties_add_list(props,
S_SIDECHAIN_SOURCE, TEXT_SIDECHAIN_SOURCE,
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
obs_property_t *sources = obs_properties_add_list(
props, S_SIDECHAIN_SOURCE, TEXT_SIDECHAIN_SOURCE,
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(sources, obs_module_text("None"), "none");

View file

@ -2,24 +2,24 @@
#include <graphics/vec2.h>
struct crop_filter_data {
obs_source_t *context;
obs_source_t *context;
gs_effect_t *effect;
gs_eparam_t *param_mul;
gs_eparam_t *param_add;
gs_effect_t *effect;
gs_eparam_t *param_mul;
gs_eparam_t *param_add;
int left;
int right;
int top;
int bottom;
int abs_cx;
int abs_cy;
int width;
int height;
bool absolute;
int left;
int right;
int top;
int bottom;
int abs_cx;
int abs_cy;
int width;
int height;
bool absolute;
struct vec2 mul_val;
struct vec2 add_val;
struct vec2 mul_val;
struct vec2 add_val;
};
static const char *crop_filter_get_name(void *unused)
@ -46,10 +46,10 @@ static void *crop_filter_create(obs_data_t *settings, obs_source_t *context)
return NULL;
}
filter->param_mul = gs_effect_get_param_by_name(filter->effect,
"mul_val");
filter->param_add = gs_effect_get_param_by_name(filter->effect,
"add_val");
filter->param_mul =
gs_effect_get_param_by_name(filter->effect, "mul_val");
filter->param_add =
gs_effect_get_param_by_name(filter->effect, "add_val");
obs_source_update(context, settings);
return filter;
@ -80,14 +80,16 @@ static void crop_filter_update(void *data, obs_data_t *settings)
}
static bool relative_clicked(obs_properties_t *props, obs_property_t *p,
obs_data_t *settings)
obs_data_t *settings)
{
bool relative = obs_data_get_bool(settings, "relative");
obs_property_set_description(obs_properties_get(props, "left"),
relative ? obs_module_text("Crop.Left") : "X");
relative ? obs_module_text("Crop.Left")
: "X");
obs_property_set_description(obs_properties_get(props, "top"),
relative ? obs_module_text("Crop.Top") : "Y");
relative ? obs_module_text("Crop.Top")
: "Y");
obs_property_set_visible(obs_properties_get(props, "right"), relative);
obs_property_set_visible(obs_properties_get(props, "bottom"), relative);
@ -102,23 +104,23 @@ static obs_properties_t *crop_filter_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
obs_property_t *p = obs_properties_add_bool(props, "relative",
obs_module_text("Crop.Relative"));
obs_property_t *p = obs_properties_add_bool(
props, "relative", obs_module_text("Crop.Relative"));
obs_property_set_modified_callback(p, relative_clicked);
obs_properties_add_int(props, "left", obs_module_text("Crop.Left"),
-8192, 8192, 1);
obs_properties_add_int(props, "top", obs_module_text("Crop.Top"),
-8192, 8192, 1);
-8192, 8192, 1);
obs_properties_add_int(props, "top", obs_module_text("Crop.Top"), -8192,
8192, 1);
obs_properties_add_int(props, "right", obs_module_text("Crop.Right"),
-8192, 8192, 1);
-8192, 8192, 1);
obs_properties_add_int(props, "bottom", obs_module_text("Crop.Bottom"),
-8192, 8192, 1);
obs_properties_add_int(props, "cx", obs_module_text("Crop.Width"),
0, 8192, 1);
obs_properties_add_int(props, "cy", obs_module_text("Crop.Height"),
0, 8192, 1);
-8192, 8192, 1);
obs_properties_add_int(props, "cx", obs_module_text("Crop.Width"), 0,
8192, 1);
obs_properties_add_int(props, "cy", obs_module_text("Crop.Height"), 0,
8192, 1);
UNUSED_PARAMETER(data);
return props;
@ -130,7 +132,7 @@ static void crop_filter_defaults(obs_data_t *settings)
}
static void calc_crop_dimensions(struct crop_filter_data *filter,
struct vec2 *mul_val, struct vec2 *add_val)
struct vec2 *mul_val, struct vec2 *add_val)
{
obs_source_t *target = obs_filter_get_target(filter->context);
uint32_t width;
@ -146,15 +148,17 @@ static void calc_crop_dimensions(struct crop_filter_data *filter,
}
if (filter->absolute) {
filter->width = filter->abs_cx;
filter->width = filter->abs_cx;
filter->height = filter->abs_cy;
} else {
filter->width = (int)width - filter->left - filter->right;
filter->width = (int)width - filter->left - filter->right;
filter->height = (int)height - filter->top - filter->bottom;
}
if (filter->width < 1) filter->width = 1;
if (filter->height < 1) filter->height = 1;
if (filter->width < 1)
filter->width = 1;
if (filter->height < 1)
filter->height = 1;
if (width && filter->width) {
mul_val->x = (float)filter->width / (float)width;
@ -183,14 +187,14 @@ static void crop_filter_render(void *data, gs_effect_t *effect)
struct crop_filter_data *filter = data;
if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
OBS_NO_DIRECT_RENDERING))
OBS_NO_DIRECT_RENDERING))
return;
gs_effect_set_vec2(filter->param_mul, &filter->mul_val);
gs_effect_set_vec2(filter->param_add, &filter->add_val);
obs_source_process_filter_end(filter->context, filter->effect,
filter->width, filter->height);
filter->width, filter->height);
UNUSED_PARAMETER(effect);
}
@ -208,17 +212,17 @@ static uint32_t crop_filter_height(void *data)
}
struct obs_source_info crop_filter = {
.id = "crop_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = crop_filter_get_name,
.create = crop_filter_create,
.destroy = crop_filter_destroy,
.update = crop_filter_update,
.get_properties = crop_filter_properties,
.get_defaults = crop_filter_defaults,
.video_tick = crop_filter_tick,
.video_render = crop_filter_render,
.get_width = crop_filter_width,
.get_height = crop_filter_height
.id = "crop_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = crop_filter_get_name,
.create = crop_filter_create,
.destroy = crop_filter_destroy,
.update = crop_filter_update,
.get_properties = crop_filter_properties,
.get_defaults = crop_filter_defaults,
.video_tick = crop_filter_tick,
.video_render = crop_filter_render,
.get_width = crop_filter_width,
.get_height = crop_filter_height,
};

View file

@ -1,4 +1,36 @@
ColorFilter="Корекция на цвета"
AsyncDelayFilter="Забавяне на видеото (асинхронно)"
InvertPolarity="Преобръщане на полярността"
DelayMs="Забавяне (в милисекунди)"
Type="Вид"
Path="Път"
Color="Цвят"
Opacity="Прозиране"
Contrast="Контраст"
Brightness="Яркост"
Gamma="Гама"
BrowsePath.Images="Всички файлове с изображения"
BrowsePath.AllFiles="Всички файлове"
KeyColor="Цвят на ключа"
Similarity="Подобност (1-1000)"
Smoothness="Гладкост (1-1000)"
ScrollFilter.SpeedX="Водоравна бързина"
ScrollFilter.SpeedY="Отвесна бързина"
CustomColor="Подбиране на цвят"
Resolution="Разд. способност"
ScaleFiltering.Point="Точково"
ScaleFiltering.Bilinear="Двулинейно"
ScaleFiltering.Bicubic="Бикубично"
ScaleFiltering.Lanczos="Ланцош"
ScaleFiltering.Area="Област"
Saturation="Наситеност"
Compressor="Компресор"
Compressor.Ratio="Съотношение (X:1)"
Limiter="Ограничител"
Limiter.Threshold="Праг на отсичане (dB)"
Limiter.ReleaseTime="Време за отговор (мс)"
Expander.Ratio="Съотношение (X:1)"
Expander.Presets="Образци"
Expander.Presets.Expander="Експандър"
Expander.Presets.Gate="Порта"

View file

@ -1,6 +1,6 @@
ColorFilter="Farbkorrektur"
ColorGradeFilter="LUT anwenden"
MaskFilter="Bildmaske/-Vermischung"
MaskFilter="Bildmaske/Vermischung"
AsyncDelayFilter="Videoverzögerung (Asynchron)"
CropFilter="Zuschneiden/Pad"
ScrollFilter="Bewegung"
@ -29,11 +29,11 @@ Brightness="Helligkeit"
Gamma="Gamma"
BrowsePath.Images="Alle Bilddateien"
BrowsePath.AllFiles="Alle Dateien"
KeyColorType="Key-Farbtyp"
KeyColor="Key-Farbe"
Similarity="Ähnlichkeit (11000)"
Smoothness="Glätte (11000)"
ColorSpillReduction="Key-Farbe-Spill-Reduzierung (1 — 1000)"
KeyColorType="KeyFarbtyp"
KeyColor="KeyFarbe"
Similarity="Ähnlichkeit (11000)"
Smoothness="Glätte (11000)"
ColorSpillReduction="KeyFarbeSpillReduzierung (11000)"
Crop.Left="Links"
Crop.Right="Rechts"
Crop.Top="Oben"
@ -50,15 +50,15 @@ Red="Rot"
Green="Grün"
Blue="Blau"
Magenta="Magenta"
NoiseGate.OpenThreshold="Öffnen-Schwellenwert (dB)"
NoiseGate.CloseThreshold="Schließen-Schwellenwert (dB)"
NoiseGate.AttackTime="Attack-Zeit (Millisekunden)"
NoiseGate.HoldTime="Hold-Zeit (Millisekunden)"
NoiseGate.ReleaseTime="Release-Zeit (Millisekunden)"
NoiseGate.OpenThreshold="ÖffnungsSchwellwert (dB)"
NoiseGate.CloseThreshold="SchließungsSchwellwert (dB)"
NoiseGate.AttackTime="AttackZeit (Millisekunden)"
NoiseGate.HoldTime="HoldZeit (Millisekunden)"
NoiseGate.ReleaseTime="ReleaseZeit (Millisekunden)"
Gain.GainDB="Gain (dB)"
StretchImage="Bild strecken (Bildseitenverhältnis verwerfen)"
Resolution="Auflösung"
Base.Canvas="Basis-(Leinwand-)Auflösung"
Base.Canvas="Basis(Leinwand)Auflösung"
None="Keine"
ScaleFiltering="Skalierungsfilterung"
ScaleFiltering.Point="Point"
@ -72,30 +72,30 @@ HueShift="Farbtonverschiebung"
Amount="Betrag"
Compressor="Kompressor"
Compressor.Ratio="Verhältnis (X:1)"
Compressor.Threshold="Schwellenwert (dB)"
Compressor.AttackTime="Angriff (ms)"
Compressor.ReleaseTime="Abfallzeit (ms)"
Compressor.Threshold="Schwellwert (dB)"
Compressor.AttackTime="Attack (ms)"
Compressor.ReleaseTime="Release (ms)"
Compressor.OutputGain="Ausgangspegel (dB)"
Compressor.SidechainSource="Sidechain-/Ducking-Quelle"
Compressor.SidechainSource="Sidechain/DuckingQuelle"
Limiter="Begrenzer"
Limiter.Threshold="Schwellenwert (dB)"
Limiter.ReleaseTime="Abfallzeit (ms)"
Limiter.Threshold="Schwellwert (dB)"
Limiter.ReleaseTime="Release (ms)"
Expander="Expander"
Expander.Ratio="Verhältnis (X:1)"
Expander.Threshold="Schwellenwert (dB)"
Expander.AttackTime="Angriff (ms)"
Expander.ReleaseTime="Abfallzeit (ms)"
Expander.Threshold="Schwellwert (dB)"
Expander.AttackTime="Attack (ms)"
Expander.ReleaseTime="Release (ms)"
Expander.OutputGain="Ausgangspegel (dB)"
Expander.Detector="Erkennung"
Expander.RMS="RMS"
Expander.Peak="Spitze"
Expander.Peak="Peak"
Expander.None="Keine"
Expander.Presets="Voreinstellungen"
Expander.Presets.Expander="Expander"
Expander.Presets.Gate="Gate"
LumaKeyFilter="Luma-Key"
LumaKeyFilter="Luma Key"
Luma.LumaMax="Max. Luma"
Luma.LumaMin="Min. Luma"
Luma.LumaMaxSmooth="Max. Luma-Glätte"
Luma.LumaMinSmooth="Min. Luma-Glätte"
Luma.LumaMaxSmooth="Max. LumaGlätte"
Luma.LumaMinSmooth="Min. LumaGlätte"

View file

@ -14,7 +14,7 @@ NoiseGate="Noise Gate"
NoiseSuppress="Noise Suppression"
InvertPolarity="Invert Polarity"
Gain="Gain"
DelayMs="Delay (milliseconds)"
DelayMs="Delay"
Type="Type"
MaskBlendType.MaskColor="Alpha Mask (Color Channel)"
MaskBlendType.MaskAlpha="Alpha Mask (Alpha Channel)"
@ -50,12 +50,12 @@ Red="Red"
Green="Green"
Blue="Blue"
Magenta="Magenta"
NoiseGate.OpenThreshold="Open Threshold (dB)"
NoiseGate.CloseThreshold="Close Threshold (dB)"
NoiseGate.AttackTime="Attack Time (milliseconds)"
NoiseGate.HoldTime="Hold Time (milliseconds)"
NoiseGate.ReleaseTime="Release Time (milliseconds)"
Gain.GainDB="Gain (dB)"
NoiseGate.OpenThreshold="Open Threshold"
NoiseGate.CloseThreshold="Close Threshold"
NoiseGate.AttackTime="Attack Time"
NoiseGate.HoldTime="Hold Time"
NoiseGate.ReleaseTime="Release Time"
Gain.GainDB="Gain"
StretchImage="Stretch Image (discard image aspect ratio)"
Resolution="Resolution"
Base.Canvas="Base (Canvas) Resolution"
@ -66,26 +66,26 @@ ScaleFiltering.Bilinear="Bilinear"
ScaleFiltering.Bicubic="Bicubic"
ScaleFiltering.Lanczos="Lanczos"
ScaleFiltering.Area="Area"
NoiseSuppress.SuppressLevel="Suppression Level (dB)"
NoiseSuppress.SuppressLevel="Suppression Level"
Saturation="Saturation"
HueShift="Hue Shift"
Amount="Amount"
Compressor="Compressor"
Compressor.Ratio="Ratio (X:1)"
Compressor.Threshold="Threshold (dB)"
Compressor.AttackTime="Attack (ms)"
Compressor.ReleaseTime="Release (ms)"
Compressor.OutputGain="Output Gain (dB)"
Compressor.Ratio="Ratio"
Compressor.Threshold="Threshold"
Compressor.AttackTime="Attack"
Compressor.ReleaseTime="Release"
Compressor.OutputGain="Output Gain"
Compressor.SidechainSource="Sidechain/Ducking Source"
Limiter="Limiter"
Limiter.Threshold="Threshold (dB)"
Limiter.ReleaseTime="Release (ms)"
Limiter.Threshold="Threshold"
Limiter.ReleaseTime="Release"
Expander="Expander"
Expander.Ratio="Ratio (X:1)"
Expander.Threshold="Threshold (dB)"
Expander.AttackTime="Attack (ms)"
Expander.ReleaseTime="Release (ms)"
Expander.OutputGain="Output Gain (dB)"
Expander.Ratio="Ratio"
Expander.Threshold="Threshold"
Expander.AttackTime="Attack"
Expander.ReleaseTime="Release"
Expander.OutputGain="Output Gain"
Expander.Detector="Detection"
Expander.RMS="RMS"
Expander.Peak="Peak"

View file

@ -1,12 +1,27 @@
ColorFilter="Corrección da cor"
ColorGradeFilter="Aplicar LUT"
MaskFilter="Máscara/mestura de imaxes"
AsyncDelayFilter="Atraso do vídeo (asíncrono)"
CropFilter="Recorte/Recheo"
ScrollFilter="Desprazamento"
ChromaKeyFilter="Chroma Key"
ColorKeyFilter="Clave de cor"
SharpnessFilter="Nídio"
ScaleFilter="Escala/relación de aspecto"
GPUDelayFilter="Demora na xeración"
UndistortCenter="Non distorsionar o centro da imaxe cando se escala dende ultralarga"
NoiseGate="Porta de ruído"
NoiseSuppress="Supresión do ruído"
InvertPolarity="Inverter a polaridade"
Gain="Ganancia"
DelayMs="Atraso (milisegundos)"
Type="Tipo"
MaskBlendType.MaskColor="Máscara alfa (canle de cor)"
MaskBlendType.MaskAlpha="Máscara alfa (canle alfa)"
Path="Camiño"
MaskBlendType.BlendMultiply="Mestura (multiplicar)"
MaskBlendType.BlendAddition="Mestura (adición)"
MaskBlendType.BlendSubtraction="Mestura (substracción)"
Path="Ruta"
Color="Cor"
Opacity="Opacidade"
Contrast="Contraste"
@ -14,17 +29,73 @@ Brightness="Brillo"
Gamma="Gama"
BrowsePath.Images="Todo os ficheiros de imaxe"
BrowsePath.AllFiles="Todos os ficheiros"
KeyColorType="Tipo de cor da clave"
KeyColor="Cor da clave"
Similarity="Similitude (1-1000)"
Crop.Left="Á esquerda"
Crop.Right="Á dereita"
Smoothness="Suavidade (1-1000)"
ColorSpillReduction="Redución da vertedura da cor clave (1-1000)"
Crop.Left="Esquerda"
Crop.Right="Dereita"
Crop.Top="Arriba"
Crop.Bottom="Abaixo"
Crop.Width="Largura"
Crop.Height="Altura"
Crop.Width="Largo"
Crop.Height="Alto"
Crop.Relative="Relativo"
CustomColor="Personalizar cor"
ScrollFilter.SpeedX="Velocidade horizontal"
ScrollFilter.SpeedY="Velocidade vertical"
ScrollFilter.LimitWidth="Limitar o largo"
ScrollFilter.LimitHeight="Limitar o alto"
CustomColor="Cor personalizada"
Red="Vermello"
Green="Verde"
Blue="Azul"
Magenta="Maxenta"
NoiseGate.OpenThreshold="Limiar de apertura (dB)"
NoiseGate.CloseThreshold="Limiar de peche (dB)"
NoiseGate.AttackTime="Tempo de ataque (milisegundos)"
NoiseGate.HoldTime="Tempo de espera (milisegundos)"
NoiseGate.ReleaseTime="Tempo de liberación (milisegundos)"
Gain.GainDB="Ganancia (dB)"
StretchImage="Estricar a imaxe (desbotar a relación de aspecto da imaxe)"
Resolution="Resolución"
Base.Canvas="Resolución da base (lenzo)"
None="Ningunha"
ScaleFiltering="Filtrado da escala"
ScaleFiltering.Point="Punto"
ScaleFiltering.Bilinear="Bilineal"
ScaleFiltering.Bicubic="Bicúbico"
ScaleFiltering.Lanczos="Lanczos"
ScaleFiltering.Area="Área"
NoiseSuppress.SuppressLevel="Nivel de supresión (dB)"
Saturation="Saturación"
HueShift="Cambio de tonalidade"
Amount="Cantidade"
Compressor="Compresor"
Compressor.Ratio="Razón (X:1)"
Compressor.Threshold="Limiar (dB)"
Compressor.AttackTime="Ataque (ms)"
Compressor.ReleaseTime="Liberación (ms)"
Compressor.OutputGain="Ganancia da saída (dB)"
Compressor.SidechainSource="Fonte de atenuación/redución"
Limiter="Limitador"
Limiter.Threshold="Limiar (dB)"
Limiter.ReleaseTime="Liberación (ms)"
Expander="Expansor"
Expander.Ratio="Razón (X:1)"
Expander.Threshold="Limiar (dB)"
Expander.AttackTime="Ataque (ms)"
Expander.ReleaseTime="Liberación (ms)"
Expander.OutputGain="Ganancia da saída (dB)"
Expander.Detector="Detección"
Expander.RMS="RMS"
Expander.Peak="Pico"
Expander.None="Ningún"
Expander.Presets="Valores predefinidos"
Expander.Presets.Expander="Expansor"
Expander.Presets.Gate="Porta"
LumaKeyFilter="Clave Luma"
Luma.LumaMax="Máximo Luma"
Luma.LumaMin="Mínimo Luma"
Luma.LumaMaxSmooth="Suavizado máximo Luma"
Luma.LumaMinSmooth="Suavizado mínimo Luma"

View file

@ -96,6 +96,6 @@ Expander.Presets.Gate="ゲート"
LumaKeyFilter="ルマキー"
Luma.LumaMax="最大輝度"
Luma.LumaMin="最小輝度"
Luma.LumaMaxSmooth="ルマ最大スムーズ"
Luma.LumaMinSmooth="ルマ最小スムーズ"
Luma.LumaMaxSmooth="最大輝度グラデーション"
Luma.LumaMinSmooth="最小輝度グラデーション"

View file

@ -65,7 +65,7 @@ ScaleFiltering.Point="წერტილოვანი"
ScaleFiltering.Bilinear="ორხაზოვანი"
ScaleFiltering.Bicubic="ბიკუბური"
ScaleFiltering.Lanczos="Lanczos"
ScaleFiltering.Area="სივრც"
ScaleFiltering.Area="სივრცითი"
NoiseSuppress.SuppressLevel="დახშობის ხარისხი (dB)"
Saturation="გაჯერებულობა"
HueShift="შეფერილობის შეცვლა"

View file

@ -93,4 +93,9 @@ Expander.None="Geen"
Expander.Presets="Vooraf ingestelde instellingen"
Expander.Presets.Expander="Uitbreiding"
Expander.Presets.Gate="Hek"
LumaKeyFilter="Luma Key"
Luma.LumaMax="Luma Max"
Luma.LumaMin="Luma Min"
Luma.LumaMaxSmooth="Luma Max Smooth"
Luma.LumaMinSmooth="Luma Min Smooth"

View file

@ -5,7 +5,7 @@ ScrollFilter="Derulare"
ChromaKeyFilter="Cheie chroma"
ColorKeyFilter="Culoare cheie"
SharpnessFilter="Accentuare"
ScaleFilter="Scalare/Rație Aspect"
ScaleFilter="Raport de scalare/aspect"
NoiseGate="Poartă de zgomot"
InvertPolarity="Inversează polaritatea"
Gain="Amplificare"
@ -54,10 +54,13 @@ Gain.GainDB="Amplificare (dB)"
StretchImage="Întinde imaginea (renunță la raportul de aspect al imaginii)"
Resolution="Rezoluție"
Base.Canvas="Rezoluție (planșă) de bază"
None="Fără"
ScaleFiltering.Bilinear="Biliniar"
ScaleFiltering.Bicubic="Bicubic"
None="Niciuna"
ScaleFiltering="Filtrare scalară"
ScaleFiltering.Point="Punct"
ScaleFiltering.Bilinear="Bilineară"
ScaleFiltering.Bicubic="Bicubică"
ScaleFiltering.Lanczos="Lanczos"
ScaleFiltering.Area="Zonă"
Saturation="Saturație"
Compressor="Compresor"
Compressor.Ratio="Raport (X:1)"

View file

@ -1,2 +1,99 @@
ColorFilter="Popravljanje barv"
ColorGradeFilter="Uporabi LUT"
MaskFilter="Maskiranje/Mešanje slike"
AsyncDelayFilter="Zakasnitev slike (asinh.)"
CropFilter="Obreži/Zapolni"
ScrollFilter="Pomikanje"
ChromaKeyFilter="Kromatsko prekrivanje"
ColorKeyFilter="Barvno prekrivanje"
SharpnessFilter="Izostri"
ScaleFilter="Spr. velikosti/Razmerje"
GPUDelayFilter="Zakasnitev izrisa"
UndistortCenter="Odpravi popačenje sredine slike med spremembo velikost iz ultraširoke"
NoiseGate="Vrata šuma"
NoiseSuppress="Dušenje šuma"
InvertPolarity="Obrni polarnost"
Gain="Ojačitev"
DelayMs="Zakasnitev (ms)"
Type="Vrsta"
MaskBlendType.MaskColor="Maska alfa (barvni kanal)"
MaskBlendType.MaskAlpha="Maska alfa (kanal alfa)"
MaskBlendType.BlendMultiply="Premešaj (zmnoži)"
MaskBlendType.BlendAddition="Premešaj (seštej)"
MaskBlendType.BlendSubtraction="Premešaj (odštej)"
Path="Pot"
Color="Barva"
Opacity="Motnost"
Contrast="Kontrast"
Brightness="Svetlost"
Gamma="Gama"
BrowsePath.Images="Vse slikovne datoteke"
BrowsePath.AllFiles="Vse datoteke"
KeyColorType="Vrsta ključne barve"
KeyColor="Ključna barva"
Similarity="Podobnost (1-1000)"
Smoothness="Gladkost (1-1000)"
ColorSpillReduction="Zmanjševanje razlivanja ključne barve (1-1000)"
Crop.Left="Levo"
Crop.Right="Desno"
Crop.Top="Zgoraj"
Crop.Bottom="Spodaj"
Crop.Width="Širina"
Crop.Height="Višina"
Crop.Relative="Relativno"
ScrollFilter.SpeedX="Vodoravna hitrost"
ScrollFilter.SpeedY="Navpična hitrost"
ScrollFilter.LimitWidth="Omeji širino"
ScrollFilter.LimitHeight="Omeji višino"
CustomColor="Barva po meri"
Red="Rdeča"
Green="Zelena"
Blue="Modra"
Magenta="Škrlatna"
NoiseGate.OpenThreshold="Odpri prag (dB)"
NoiseGate.CloseThreshold="Zapri prag (dB)"
NoiseGate.AttackTime="Čas napada (ms)"
NoiseGate.HoldTime="Čas držanja (ms)"
NoiseGate.ReleaseTime="Čas sprostitve (ms)"
Gain.GainDB="Ojačitev (dB)"
StretchImage="Raztegni sliko (zavrzi razmerje slike)"
Resolution="Ločljivost"
Base.Canvas="Osnovna ločljivost"
None="Brez"
ScaleFiltering="Filtriranje sprem. velikosti"
ScaleFiltering.Point="Točkovno"
ScaleFiltering.Bilinear="Dvovrstno"
ScaleFiltering.Bicubic="Dvoprostor."
ScaleFiltering.Lanczos="Lanczos"
ScaleFiltering.Area="Območje"
NoiseSuppress.SuppressLevel="Raven dušenja (dB)"
Saturation="Nasičenost"
HueShift="Zamik odtenka"
Amount="Količina"
Compressor="Stiskalnik"
Compressor.Ratio="Razmerje (x:1)"
Compressor.Threshold="Prag (dB)"
Compressor.AttackTime="Napad (ms)"
Compressor.ReleaseTime="Sprostitev (ms)"
Compressor.OutputGain="Izhodna ojačitev (dB)"
Compressor.SidechainSource="Vir reference/zmanjšanja glasnosti"
Limiter="Omejevalnik"
Limiter.Threshold="Prag (dB)"
Limiter.ReleaseTime="Sprostitev (ms)"
Expander="Razširjevalec"
Expander.Ratio="Razmerje (x:1)"
Expander.Threshold="Prag (dB)"
Expander.AttackTime="Napad (ms)"
Expander.ReleaseTime="Sprostitev (ms)"
Expander.OutputGain="Izhodna ojačitev (dB)"
Expander.Detector="Zaznavanje"
Expander.RMS="Nazivna vrednost"
Expander.Peak="Najvišja točka"
Expander.None="Brez"
Expander.Presets="Prednastavitve"
Expander.Presets.Expander="Razširjevalec"
Expander.Presets.Gate="Vrata"
LumaKeyFilter="Svetlobno prekrivanje"
Luma.LumaMax="Največja svetilnost"
Luma.LumaMin="Najmanjša svetilnost"

View file

@ -28,7 +28,7 @@ Contrast="Kontrast"
Brightness="Ljusstyrka"
Gamma="Gamma"
BrowsePath.Images="Alla bildfiler"
BrowsePath.AllFiles="Alla Filer"
BrowsePath.AllFiles="Alla filer"
KeyColorType="Huvudfärg typ"
KeyColor="Huvudfärg"
Similarity="Likhet (1-1000)"

View file

@ -10,21 +10,23 @@
/* -------------------------------------------------------- */
#define do_log(level, format, ...) \
#define do_log(level, format, ...) \
blog(level, "[expander: '%s'] " format, \
obs_source_get_name(cd->context), ##__VA_ARGS__)
obs_source_get_name(cd->context), ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
#ifdef _DEBUG
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
#else
#define debug(format, ...)
#endif
/* -------------------------------------------------------- */
/* clang-format off */
#define S_RATIO "ratio"
#define S_THRESHOLD "threshold"
#define S_ATTACK_TIME "attack_time"
@ -61,6 +63,8 @@
#define MS_IN_S 1000
#define MS_IN_S_F ((float)MS_IN_S)
/* clang-format on */
/* -------------------------------------------------------- */
struct expander_data {
@ -78,7 +82,7 @@ struct expander_data {
size_t sample_rate;
float envelope[MAX_AUDIO_CHANNELS];
float slope;
int detector;
int detector;
float runave[MAX_AUDIO_CHANNELS];
bool is_gate;
float *runaverage[MAX_AUDIO_CHANNELS];
@ -90,11 +94,10 @@ struct expander_data {
size_t env_in_len;
};
enum {
RMS_DETECT,
RMS_STILLWELL_DETECT,
PEAK_DETECT,
NO_DETECT,
enum { RMS_DETECT,
RMS_STILLWELL_DETECT,
PEAK_DETECT,
NO_DETECT,
};
/* -------------------------------------------------------- */
@ -102,16 +105,17 @@ static void resize_env_buffer(struct expander_data *cd, size_t len)
{
cd->envelope_buf_len = len;
for (int i = 0; i < MAX_AUDIO_CHANNELS; i++)
cd->envelope_buf[i] = brealloc(cd->envelope_buf[i],
cd->envelope_buf_len * sizeof(float));
cd->envelope_buf[i] =
brealloc(cd->envelope_buf[i],
cd->envelope_buf_len * sizeof(float));
}
static void resize_runaverage_buffer(struct expander_data *cd, size_t len)
{
cd->runaverage_len = len;
for (int i = 0; i < MAX_AUDIO_CHANNELS; i++)
cd->runaverage[i] = brealloc(cd->runaverage[i],
cd->runaverage_len * sizeof(float));
cd->runaverage[i] = brealloc(
cd->runaverage[i], cd->runaverage_len * sizeof(float));
}
static void resize_env_in_buffer(struct expander_data *cd, size_t len)
@ -124,8 +128,8 @@ static void resize_gaindB_buffer(struct expander_data *cd, size_t len)
{
cd->gaindB_len = len;
for (int i = 0; i < MAX_AUDIO_CHANNELS; i++)
cd->gaindB[i] = brealloc(cd->gaindB[i],
cd->gaindB_len * sizeof(float));
cd->gaindB[i] =
brealloc(cd->gaindB[i], cd->gaindB_len * sizeof(float));
}
static inline float gain_coefficient(uint32_t sample_rate, float time)
@ -145,14 +149,14 @@ static void expander_defaults(obs_data_t *s)
bool is_expander_preset = true;
if (strcmp(presets, "gate") == 0)
is_expander_preset = false;
obs_data_set_default_string(s, S_PRESETS, is_expander_preset ?
"expander" : "gate");
obs_data_set_default_double(s, S_RATIO, is_expander_preset ?
2.0 : 10.0);
obs_data_set_default_string(s, S_PRESETS,
is_expander_preset ? "expander" : "gate");
obs_data_set_default_double(s, S_RATIO,
is_expander_preset ? 2.0 : 10.0);
obs_data_set_default_double(s, S_THRESHOLD, -40.0f);
obs_data_set_default_int(s, S_ATTACK_TIME, 10);
obs_data_set_default_int(s, S_RELEASE_TIME, is_expander_preset ?
50 : 125);
obs_data_set_default_int(s, S_RELEASE_TIME,
is_expander_preset ? 50 : 125);
obs_data_set_default_double(s, S_OUTPUT_GAIN, 0.0);
obs_data_set_default_string(s, S_DETECTOR, "RMS");
}
@ -175,23 +179,21 @@ static void expander_update(void *data, obs_data_t *s)
}
const uint32_t sample_rate =
audio_output_get_sample_rate(obs_get_audio());
const size_t num_channels =
audio_output_get_channels(obs_get_audio());
const float attack_time_ms =
(float)obs_data_get_int(s, S_ATTACK_TIME);
audio_output_get_sample_rate(obs_get_audio());
const size_t num_channels = audio_output_get_channels(obs_get_audio());
const float attack_time_ms = (float)obs_data_get_int(s, S_ATTACK_TIME);
const float release_time_ms =
(float)obs_data_get_int(s, S_RELEASE_TIME);
(float)obs_data_get_int(s, S_RELEASE_TIME);
const float output_gain_db =
(float)obs_data_get_double(s, S_OUTPUT_GAIN);
(float)obs_data_get_double(s, S_OUTPUT_GAIN);
cd->ratio = (float)obs_data_get_double(s, S_RATIO);
cd->threshold = (float)obs_data_get_double(s, S_THRESHOLD);
cd->attack_gain = gain_coefficient(sample_rate,
attack_time_ms / MS_IN_S_F);
cd->release_gain = gain_coefficient(sample_rate,
release_time_ms / MS_IN_S_F);
cd->attack_gain =
gain_coefficient(sample_rate, attack_time_ms / MS_IN_S_F);
cd->release_gain =
gain_coefficient(sample_rate, release_time_ms / MS_IN_S_F);
cd->output_gain = db_to_mul(output_gain_db);
cd->num_channels = num_channels;
cd->sample_rate = sample_rate;
@ -246,8 +248,8 @@ static void expander_destroy(void *data)
}
// detection stage
static void analyze_envelope(struct expander_data *cd,
float **samples, const uint32_t num_samples)
static void analyze_envelope(struct expander_data *cd, float **samples,
const uint32_t num_samples)
{
if (cd->envelope_buf_len < num_samples)
resize_env_buffer(cd, num_samples);
@ -261,9 +263,9 @@ static void analyze_envelope(struct expander_data *cd,
for (int i = 0; i < MAX_AUDIO_CHANNELS; i++) {
memset(cd->envelope_buf[i], 0,
num_samples * sizeof(cd->envelope_buf[i][0]));
num_samples * sizeof(cd->envelope_buf[i][0]));
memset(cd->runaverage[i], 0,
num_samples * sizeof(cd->runaverage[i][0]));
num_samples * sizeof(cd->runaverage[i][0]));
}
memset(cd->env_in, 0, num_samples * sizeof(cd->env_in[0]));
@ -276,13 +278,15 @@ static void analyze_envelope(struct expander_data *cd,
float *env_in = cd->env_in;
if (cd->detector == RMS_DETECT) {
runave[0] = rmscoef * cd->runave[chan] +
runave[0] =
rmscoef * cd->runave[chan] +
(1 - rmscoef) * powf(samples[chan][0], 2.0f);
env_in[0] = sqrtf(fmaxf(runave[0], 0));
for (uint32_t i = 1; i < num_samples; ++i) {
runave[i] = rmscoef * runave[i - 1] +
runave[i] =
rmscoef * runave[i - 1] +
(1 - rmscoef) *
powf(samples[chan][i], 2.0f);
powf(samples[chan][i], 2.0f);
env_in[i] = sqrtf(runave[i]);
}
} else if (cd->detector == PEAK_DETECT) {
@ -292,7 +296,7 @@ static void analyze_envelope(struct expander_data *cd,
}
}
cd->runave[chan] = runave[num_samples-1];
cd->runave[chan] = runave[num_samples - 1];
for (uint32_t i = 0; i < num_samples; ++i)
envelope_buf[i] = fmaxf(envelope_buf[i], env_in[i]);
cd->envelope[chan] = cd->envelope_buf[chan][num_samples - 1];
@ -300,8 +304,8 @@ static void analyze_envelope(struct expander_data *cd,
}
// gain stage and ballistics in dB domain
static inline void process_expansion(struct expander_data *cd,
float **samples, uint32_t num_samples)
static inline void process_expansion(struct expander_data *cd, float **samples,
uint32_t num_samples)
{
const float attack_gain = cd->attack_gain;
const float release_gain = cd->release_gain;
@ -309,35 +313,42 @@ static inline void process_expansion(struct expander_data *cd,
if (cd->gaindB_len < num_samples)
resize_gaindB_buffer(cd, num_samples);
for (int i = 0; i < MAX_AUDIO_CHANNELS; i++)
memset(cd->gaindB[i], 0, num_samples * sizeof(cd->gaindB[i][0]));
memset(cd->gaindB[i], 0,
num_samples * sizeof(cd->gaindB[i][0]));
for (size_t chan = 0; chan < cd->num_channels; chan++) {
for (size_t i = 0; i < num_samples; ++i) {
// gain stage of expansion
float env_db = mul_to_db(cd->envelope_buf[chan][i]);
float gain = cd->threshold - env_db > 0.0f ?
fmaxf(cd->slope *
(cd->threshold - env_db), -60.0f) :
0.0f;
float gain =
cd->threshold - env_db > 0.0f
? fmaxf(cd->slope * (cd->threshold -
env_db),
-60.0f)
: 0.0f;
// ballistics (attack/release)
if (i > 0) {
if (gain > cd->gaindB[chan][i - 1])
cd->gaindB[chan][i] = attack_gain *
cd->gaindB[chan][i - 1] +
(1.0f - attack_gain) * gain;
cd->gaindB[chan][i] =
attack_gain *
cd->gaindB[chan][i - 1] +
(1.0f - attack_gain) * gain;
else
cd->gaindB[chan][i] = release_gain *
cd->gaindB[chan][i - 1] +
(1.0f - release_gain) * gain;
cd->gaindB[chan][i] =
release_gain *
cd->gaindB[chan][i - 1] +
(1.0f - release_gain) * gain;
} else {
if (gain > cd->gaindB_buf[chan])
cd->gaindB[chan][i] = attack_gain *
cd->gaindB_buf[chan] +
(1.0f - attack_gain) * gain;
cd->gaindB[chan][i] =
attack_gain *
cd->gaindB_buf[chan] +
(1.0f - attack_gain) * gain;
else
cd->gaindB[chan][i] = release_gain *
cd->gaindB_buf[chan] +
(1.0f - release_gain) * gain;
cd->gaindB[chan][i] =
release_gain *
cd->gaindB_buf[chan] +
(1.0f - release_gain) * gain;
}
gain = db_to_mul(fminf(0, cd->gaindB[chan][i]));
@ -348,8 +359,8 @@ static inline void process_expansion(struct expander_data *cd,
}
}
static struct obs_audio_data *expander_filter_audio(void *data,
struct obs_audio_data *audio)
static struct obs_audio_data *
expander_filter_audio(void *data, struct obs_audio_data *audio)
{
struct expander_data *cd = data;
@ -357,7 +368,7 @@ static struct obs_audio_data *expander_filter_audio(void *data,
if (num_samples == 0)
return audio;
float **samples = (float**)audio->data;
float **samples = (float **)audio->data;
analyze_envelope(cd, samples, num_samples);
process_expansion(cd, samples, num_samples);
@ -365,7 +376,7 @@ static struct obs_audio_data *expander_filter_audio(void *data,
}
static bool presets_changed(obs_properties_t *props, obs_property_t *prop,
obs_data_t *settings)
obs_data_t *settings)
{
UNUSED_PARAMETER(props);
UNUSED_PARAMETER(prop);
@ -376,28 +387,37 @@ static bool presets_changed(obs_properties_t *props, obs_property_t *prop,
static obs_properties_t *expander_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
obs_property_t *p;
obs_property_t *presets = obs_properties_add_list(props, S_PRESETS,
TEXT_PRESETS, OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_property_t *presets = obs_properties_add_list(
props, S_PRESETS, TEXT_PRESETS, OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(presets, TEXT_PRESETS_EXP, "expander");
obs_property_list_add_string(presets, TEXT_PRESETS_GATE, "gate");
obs_property_set_modified_callback(presets, presets_changed);
obs_properties_add_float_slider(props, S_RATIO,
TEXT_RATIO, MIN_RATIO, MAX_RATIO, 0.1);
obs_properties_add_float_slider(props, S_THRESHOLD,
TEXT_THRESHOLD, MIN_THRESHOLD_DB, MAX_THRESHOLD_DB,
0.1);
obs_properties_add_int_slider(props, S_ATTACK_TIME,
TEXT_ATTACK_TIME, MIN_ATK_RLS_MS, MAX_ATK_MS, 1);
obs_properties_add_int_slider(props, S_RELEASE_TIME,
TEXT_RELEASE_TIME, MIN_ATK_RLS_MS, MAX_RLS_MS, 1);
obs_properties_add_float_slider(props, S_OUTPUT_GAIN,
TEXT_OUTPUT_GAIN, MIN_OUTPUT_GAIN_DB,
MAX_OUTPUT_GAIN_DB, 0.1);
obs_property_t *detect = obs_properties_add_list(props, S_DETECTOR,
TEXT_DETECTOR, OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
p = obs_properties_add_float_slider(props, S_RATIO, TEXT_RATIO,
MIN_RATIO, MAX_RATIO, 0.1);
obs_property_float_set_suffix(p, ":1");
p = obs_properties_add_float_slider(props, S_THRESHOLD, TEXT_THRESHOLD,
MIN_THRESHOLD_DB, MAX_THRESHOLD_DB,
0.1);
obs_property_float_set_suffix(p, " dB");
p = obs_properties_add_int_slider(props, S_ATTACK_TIME,
TEXT_ATTACK_TIME, MIN_ATK_RLS_MS,
MAX_ATK_MS, 1);
obs_property_int_set_suffix(p, " ms");
p = obs_properties_add_int_slider(props, S_RELEASE_TIME,
TEXT_RELEASE_TIME, MIN_ATK_RLS_MS,
MAX_RLS_MS, 1);
obs_property_int_set_suffix(p, " ms");
p = obs_properties_add_float_slider(props, S_OUTPUT_GAIN,
TEXT_OUTPUT_GAIN,
MIN_OUTPUT_GAIN_DB,
MAX_OUTPUT_GAIN_DB, 0.1);
obs_property_float_set_suffix(p, " dB");
obs_property_t *detect = obs_properties_add_list(
props, S_DETECTOR, TEXT_DETECTOR, OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(detect, TEXT_RMS, "RMS");
obs_property_list_add_string(detect, TEXT_PEAK, "peak");

View file

@ -2,17 +2,17 @@
#include <media-io/audio-math.h>
#include <math.h>
#define do_log(level, format, ...) \
#define do_log(level, format, ...) \
blog(level, "[gain filter: '%s'] " format, \
obs_source_get_name(gf->context), ##__VA_ARGS__)
obs_source_get_name(gf->context), ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
#define S_GAIN_DB "db"
#define S_GAIN_DB "db"
#define MT_ obs_module_text
#define TEXT_GAIN_DB MT_("Gain.GainDB")
#define TEXT_GAIN_DB MT_("Gain.GainDB")
struct gain_data {
obs_source_t *context;
@ -49,11 +49,11 @@ static void *gain_create(obs_data_t *settings, obs_source_t *filter)
}
static struct obs_audio_data *gain_filter_audio(void *data,
struct obs_audio_data *audio)
struct obs_audio_data *audio)
{
struct gain_data *gf = data;
const size_t channels = gf->channels;
float **adata = (float**)audio->data;
float **adata = (float **)audio->data;
const float multiple = gf->multiple;
for (size_t c = 0; c < channels; c++) {
@ -76,8 +76,9 @@ static obs_properties_t *gain_properties(void *data)
{
obs_properties_t *ppts = obs_properties_create();
obs_properties_add_float_slider(ppts, S_GAIN_DB, TEXT_GAIN_DB,
-30.0, 30.0, 0.1);
obs_property_t *p = obs_properties_add_float_slider(
ppts, S_GAIN_DB, TEXT_GAIN_DB, -30.0, 30.0, 0.1);
obs_property_float_set_suffix(p, " dB");
UNUSED_PARAMETER(data);
return ppts;

View file

@ -1,8 +1,8 @@
#include <obs-module.h>
#include <util/circlebuf.h>
#define S_DELAY_MS "delay_ms"
#define T_DELAY_MS obs_module_text("DelayMs")
#define S_DELAY_MS "delay_ms"
#define T_DELAY_MS obs_module_text("DelayMs")
struct frame {
gs_texrender_t *render;
@ -10,14 +10,14 @@ struct frame {
};
struct gpu_delay_filter_data {
obs_source_t *context;
struct circlebuf frames;
uint64_t delay_ns;
uint64_t interval_ns;
uint32_t cx;
uint32_t cy;
bool target_valid;
bool processed_frame;
obs_source_t *context;
struct circlebuf frames;
uint64_t delay_ns;
uint64_t interval_ns;
uint32_t cx;
uint32_t cy;
bool target_valid;
bool processed_frame;
};
static const char *gpu_delay_filter_get_name(void *unused)
@ -44,7 +44,7 @@ static size_t num_frames(struct circlebuf *buf)
}
static void update_interval(struct gpu_delay_filter_data *f,
uint64_t new_interval_ns)
uint64_t new_interval_ns)
{
if (!f->target_valid) {
free_textures(f);
@ -62,9 +62,10 @@ static void update_interval(struct gpu_delay_filter_data *f,
circlebuf_upsize(&f->frames, num * sizeof(struct frame));
for (size_t i = prev_num; i < num; i++) {
struct frame *frame = circlebuf_data(&f->frames,
i * sizeof(*frame));
frame->render = gs_texrender_create(GS_RGBA, GS_ZS_NONE);
struct frame *frame =
circlebuf_data(&f->frames, i * sizeof(*frame));
frame->render =
gs_texrender_create(GS_RGBA, GS_ZS_NONE);
}
obs_leave_graphics();
@ -89,8 +90,8 @@ static inline void check_interval(struct gpu_delay_filter_data *f)
obs_get_video_info(&ovi);
interval_ns = (uint64_t)ovi.fps_den * 1000000000ULL /
(uint64_t)ovi.fps_num;
interval_ns =
(uint64_t)ovi.fps_den * 1000000000ULL / (uint64_t)ovi.fps_num;
if (interval_ns != f->interval_ns)
update_interval(f, interval_ns);
@ -147,13 +148,16 @@ static obs_properties_t *gpu_delay_filter_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
obs_properties_add_int(props, S_DELAY_MS, T_DELAY_MS, 0, 500, 1);
obs_property_t *p = obs_properties_add_int(props, S_DELAY_MS,
T_DELAY_MS, 0, 500, 1);
obs_property_int_set_suffix(p, " ms");
UNUSED_PARAMETER(data);
return props;
}
static void *gpu_delay_filter_create(obs_data_t *settings, obs_source_t *context)
static void *gpu_delay_filter_create(obs_data_t *settings,
obs_source_t *context)
{
struct gpu_delay_filter_data *f = bzalloc(sizeof(*f));
f->context = context;
@ -232,8 +236,8 @@ static void gpu_delay_filter_render(void *data, gs_effect_t *effect)
vec4_zero(&clear_color);
gs_clear(GS_CLEAR_COLOR, &clear_color, 0.0f, 0);
gs_ortho(0.0f, (float)f->cx, 0.0f, (float)f->cy,
-100.0f, 100.0f);
gs_ortho(0.0f, (float)f->cx, 0.0f, (float)f->cy, -100.0f,
100.0f);
if (target == parent && !custom_draw && !async)
obs_source_default_render(target);
@ -253,14 +257,14 @@ static void gpu_delay_filter_render(void *data, gs_effect_t *effect)
}
struct obs_source_info gpu_delay_filter = {
.id = "gpu_delay",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = gpu_delay_filter_get_name,
.create = gpu_delay_filter_create,
.destroy = gpu_delay_filter_destroy,
.update = gpu_delay_filter_update,
.get_properties = gpu_delay_filter_properties,
.video_tick = gpu_delay_filter_tick,
.video_render = gpu_delay_filter_render
.id = "gpu_delay",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = gpu_delay_filter_get_name,
.create = gpu_delay_filter_create,
.destroy = gpu_delay_filter_destroy,
.update = gpu_delay_filter_update,
.get_properties = gpu_delay_filter_properties,
.video_tick = gpu_delay_filter_tick,
.video_render = gpu_delay_filter_render,
};

View file

@ -17,10 +17,10 @@ static void *invert_polarity_create(obs_data_t *settings, obs_source_t *filter)
return filter;
}
static struct obs_audio_data *invert_polarity_filter_audio(void *unused,
struct obs_audio_data *audio)
static struct obs_audio_data *
invert_polarity_filter_audio(void *unused, struct obs_audio_data *audio)
{
float **adata = (float**)audio->data;
float **adata = (float **)audio->data;
for (size_t c = 0; c < MAX_AV_PLANES; c++) {
register float *channel_data = adata[c];

View file

@ -8,21 +8,23 @@
/* -------------------------------------------------------- */
#define do_log(level, format, ...) \
#define do_log(level, format, ...) \
blog(level, "[limiter: '%s'] " format, \
obs_source_get_name(cd->context), ##__VA_ARGS__)
obs_source_get_name(cd->context), ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
#ifdef _DEBUG
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
#else
#define debug(format, ...)
#endif
/* -------------------------------------------------------- */
/* clang-format off */
#define S_THRESHOLD "threshold"
#define S_RELEASE_TIME "release_time"
@ -39,6 +41,8 @@
#define MS_IN_S 1000
#define MS_IN_S_F ((float)MS_IN_S)
/* clang-format on */
/* -------------------------------------------------------- */
struct limiter_data {
@ -82,20 +86,19 @@ static void limiter_update(void *data, obs_data_t *s)
const uint32_t sample_rate =
audio_output_get_sample_rate(obs_get_audio());
const size_t num_channels =
audio_output_get_channels(obs_get_audio());
const size_t num_channels = audio_output_get_channels(obs_get_audio());
float attack_time_ms = ATK_TIME;
const float release_time_ms =
(float)obs_data_get_int(s, S_RELEASE_TIME);
const float output_gain_db = 0;
const float output_gain_db = 0;
cd->threshold = (float)obs_data_get_double(s, S_THRESHOLD);
cd->attack_gain = gain_coefficient(sample_rate,
attack_time_ms / MS_IN_S_F);
cd->release_gain = gain_coefficient(sample_rate,
release_time_ms / MS_IN_S_F);
cd->attack_gain =
gain_coefficient(sample_rate, attack_time_ms / MS_IN_S_F);
cd->release_gain =
gain_coefficient(sample_rate, release_time_ms / MS_IN_S_F);
cd->output_gain = db_to_mul(output_gain_db);
cd->num_channels = num_channels;
cd->sample_rate = sample_rate;
@ -109,7 +112,7 @@ static void limiter_update(void *data, obs_data_t *s)
static void *limiter_create(obs_data_t *settings, obs_source_t *filter)
{
struct limiter_data *cd = bzalloc(sizeof(struct limiter_data));
cd->context = filter;
cd->context = filter;
limiter_update(cd, settings);
return cd;
@ -123,8 +126,8 @@ static void limiter_destroy(void *data)
bfree(cd);
}
static void analyze_envelope(struct limiter_data *cd,
float **samples, const uint32_t num_samples)
static void analyze_envelope(struct limiter_data *cd, float **samples,
const uint32_t num_samples)
{
if (cd->envelope_buf_len < num_samples) {
resize_env_buffer(cd, num_samples);
@ -154,7 +157,7 @@ static void analyze_envelope(struct limiter_data *cd,
}
static inline void process_compression(const struct limiter_data *cd,
float **samples, uint32_t num_samples)
float **samples, uint32_t num_samples)
{
for (size_t i = 0; i < num_samples; ++i) {
const float env_db = mul_to_db(cd->envelope_buf[i]);
@ -170,7 +173,7 @@ static inline void process_compression(const struct limiter_data *cd,
}
static struct obs_audio_data *limiter_filter_audio(void *data,
struct obs_audio_data *audio)
struct obs_audio_data *audio)
{
struct limiter_data *cd = data;
@ -178,7 +181,7 @@ static struct obs_audio_data *limiter_filter_audio(void *data,
if (num_samples == 0)
return audio;
float **samples = (float**)audio->data;
float **samples = (float **)audio->data;
analyze_envelope(cd, samples, num_samples);
process_compression(cd, samples, num_samples);
return audio;
@ -193,23 +196,30 @@ static void limiter_defaults(obs_data_t *s)
static obs_properties_t *limiter_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
obs_property_t *p;
obs_properties_add_float_slider(props, S_THRESHOLD, TEXT_THRESHOLD, MIN_THRESHOLD_DB, MAX_THRESHOLD_DB, 0.1);
obs_properties_add_int_slider(props, S_RELEASE_TIME, TEXT_RELEASE_TIME, MIN_ATK_RLS_MS, MAX_RLS_MS, 1);
p = obs_properties_add_float_slider(props, S_THRESHOLD, TEXT_THRESHOLD,
MIN_THRESHOLD_DB, MAX_THRESHOLD_DB,
0.1);
obs_property_float_set_suffix(p, " dB");
p = obs_properties_add_int_slider(props, S_RELEASE_TIME,
TEXT_RELEASE_TIME, MIN_ATK_RLS_MS,
MAX_RLS_MS, 1);
obs_property_int_set_suffix(p, " ms");
UNUSED_PARAMETER(data);
return props;
}
struct obs_source_info limiter_filter = {
.id = "limiter_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_AUDIO,
.get_name = limiter_name,
.create = limiter_create,
.destroy = limiter_destroy,
.update = limiter_update,
.filter_audio = limiter_filter_audio,
.get_defaults = limiter_defaults,
.get_properties = limiter_properties,
.id = "limiter_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_AUDIO,
.get_name = limiter_name,
.create = limiter_create,
.destroy = limiter_destroy,
.update = limiter_update,
.filter_audio = limiter_filter_audio,
.get_defaults = limiter_defaults,
.get_properties = limiter_properties,
};

View file

@ -1,5 +1,7 @@
#include <obs-module.h>
/* clang-format off */
#define SETTING_LUMA_MAX "luma_max"
#define SETTING_LUMA_MIN "luma_min"
#define SETTING_LUMA_MAX_SMOOTH "luma_max_smooth"
@ -10,20 +12,22 @@
#define TEXT_LUMA_MAX_SMOOTH obs_module_text("Luma.LumaMaxSmooth")
#define TEXT_LUMA_MIN_SMOOTH obs_module_text("Luma.LumaMinSmooth")
/* clang-format on */
struct luma_key_filter_data {
obs_source_t *context;
obs_source_t *context;
gs_effect_t *effect;
gs_effect_t *effect;
gs_eparam_t *luma_max_param;
gs_eparam_t *luma_min_param;
gs_eparam_t *luma_max_smooth_param;
gs_eparam_t *luma_min_smooth_param;
gs_eparam_t *luma_max_param;
gs_eparam_t *luma_min_param;
gs_eparam_t *luma_max_smooth_param;
gs_eparam_t *luma_min_smooth_param;
float luma_max;
float luma_min;
float luma_max_smooth;
float luma_min_smooth;
float luma_max;
float luma_min;
float luma_max_smooth;
float luma_min_smooth;
};
static const char *luma_key_name(void *unused)
@ -38,8 +42,10 @@ static void luma_key_update(void *data, obs_data_t *settings)
double lumaMax = obs_data_get_double(settings, SETTING_LUMA_MAX);
double lumaMin = obs_data_get_double(settings, SETTING_LUMA_MIN);
double lumaMaxSmooth = obs_data_get_double(settings, SETTING_LUMA_MAX_SMOOTH);
double lumaMinSmooth = obs_data_get_double(settings, SETTING_LUMA_MIN_SMOOTH);
double lumaMaxSmooth =
obs_data_get_double(settings, SETTING_LUMA_MAX_SMOOTH);
double lumaMinSmooth =
obs_data_get_double(settings, SETTING_LUMA_MIN_SMOOTH);
filter->luma_max = (float)lumaMax;
filter->luma_min = (float)lumaMin;
@ -63,7 +69,7 @@ static void luma_key_destroy(void *data)
static void *luma_key_create(obs_data_t *settings, obs_source_t *context)
{
struct luma_key_filter_data *filter =
bzalloc(sizeof(struct luma_key_filter_data));
bzalloc(sizeof(struct luma_key_filter_data));
char *effect_path = obs_module_file("luma_key_filter.effect");
filter->context = context;
@ -72,14 +78,14 @@ static void *luma_key_create(obs_data_t *settings, obs_source_t *context)
filter->effect = gs_effect_create_from_file(effect_path, NULL);
if (filter->effect) {
filter->luma_max_param = gs_effect_get_param_by_name(
filter->effect, "lumaMax");
filter->luma_min_param = gs_effect_get_param_by_name(
filter->effect, "lumaMin");
filter->luma_max_param =
gs_effect_get_param_by_name(filter->effect, "lumaMax");
filter->luma_min_param =
gs_effect_get_param_by_name(filter->effect, "lumaMin");
filter->luma_max_smooth_param = gs_effect_get_param_by_name(
filter->effect, "lumaMaxSmooth");
filter->effect, "lumaMaxSmooth");
filter->luma_min_smooth_param = gs_effect_get_param_by_name(
filter->effect, "lumaMinSmooth");
filter->effect, "lumaMinSmooth");
}
obs_leave_graphics();
@ -100,13 +106,15 @@ static void luma_key_render(void *data, gs_effect_t *effect)
struct luma_key_filter_data *filter = data;
if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
OBS_ALLOW_DIRECT_RENDERING))
OBS_ALLOW_DIRECT_RENDERING))
return;
gs_effect_set_float(filter->luma_max_param, filter->luma_max);
gs_effect_set_float(filter->luma_min_param, filter->luma_min);
gs_effect_set_float(filter->luma_max_smooth_param, filter->luma_max_smooth);
gs_effect_set_float(filter->luma_min_smooth_param, filter->luma_min_smooth);
gs_effect_set_float(filter->luma_max_smooth_param,
filter->luma_max_smooth);
gs_effect_set_float(filter->luma_min_smooth_param,
filter->luma_min_smooth);
obs_source_process_filter_end(filter->context, filter->effect, 0, 0);
@ -117,14 +125,14 @@ static obs_properties_t *luma_key_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
obs_properties_add_float_slider(props, SETTING_LUMA_MAX,
TEXT_LUMA_MAX, 0, 1, 0.01);
obs_properties_add_float_slider(props, SETTING_LUMA_MAX, TEXT_LUMA_MAX,
0, 1, 0.01);
obs_properties_add_float_slider(props, SETTING_LUMA_MAX_SMOOTH,
TEXT_LUMA_MAX_SMOOTH, 0, 1, 0.01);
obs_properties_add_float_slider(props, SETTING_LUMA_MIN,
TEXT_LUMA_MIN, 0, 1, 0.01);
TEXT_LUMA_MAX_SMOOTH, 0, 1, 0.01);
obs_properties_add_float_slider(props, SETTING_LUMA_MIN, TEXT_LUMA_MIN,
0, 1, 0.01);
obs_properties_add_float_slider(props, SETTING_LUMA_MIN_SMOOTH,
TEXT_LUMA_MIN_SMOOTH, 0, 1, 0.01);
TEXT_LUMA_MIN_SMOOTH, 0, 1, 0.01);
UNUSED_PARAMETER(data);
return props;
@ -138,16 +146,15 @@ static void luma_key_defaults(obs_data_t *settings)
obs_data_set_default_double(settings, SETTING_LUMA_MIN_SMOOTH, 0.0);
}
struct obs_source_info luma_key_filter = {
.id = "luma_key_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = luma_key_name,
.create = luma_key_create,
.destroy = luma_key_destroy,
.video_render = luma_key_render,
.update = luma_key_update,
.get_properties = luma_key_properties,
.get_defaults = luma_key_defaults
.id = "luma_key_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = luma_key_name,
.create = luma_key_create,
.destroy = luma_key_destroy,
.video_render = luma_key_render,
.update = luma_key_update,
.get_properties = luma_key_properties,
.get_defaults = luma_key_defaults,
};

View file

@ -4,6 +4,8 @@
#include <graphics/image-file.h>
#include <util/dstr.h>
/* clang-format off */
#define SETTING_TYPE "type"
#define SETTING_IMAGE_PATH "image_path"
#define SETTING_COLOR "color"
@ -18,16 +20,18 @@
#define TEXT_PATH_IMAGES obs_module_text("BrowsePath.Images")
#define TEXT_PATH_ALL_FILES obs_module_text("BrowsePath.AllFiles")
/* clang-format on */
struct mask_filter_data {
uint64_t last_time;
uint64_t last_time;
obs_source_t *context;
gs_effect_t *effect;
obs_source_t *context;
gs_effect_t *effect;
gs_texture_t *target;
gs_image_file_t image;
struct vec4 color;
bool lock_aspect;
gs_texture_t *target;
gs_image_file_t image;
struct vec4 color;
bool lock_aspect;
};
static const char *mask_filter_get_name(void *unused)
@ -75,13 +79,12 @@ static void mask_filter_update(void *data, obs_data_t *settings)
static void mask_filter_defaults(obs_data_t *settings)
{
obs_data_set_default_string(settings, SETTING_TYPE,
"mask_color_filter.effect");
"mask_color_filter.effect");
obs_data_set_default_int(settings, SETTING_COLOR, 0xFFFFFF);
obs_data_set_default_int(settings, SETTING_OPACITY, 100);
}
#define IMAGE_FILTER_EXTENSIONS \
" (*.bmp *.jpg *.jpeg *.tga *.gif *.png)"
#define IMAGE_FILTER_EXTENSIONS " (*.bmp *.jpg *.jpeg *.tga *.gif *.png)"
static obs_properties_t *mask_filter_properties(void *data)
{
@ -95,29 +98,30 @@ static obs_properties_t *mask_filter_properties(void *data)
dstr_cat(&filter_str, " (*.*)");
p = obs_properties_add_list(props, SETTING_TYPE, TEXT_TYPE,
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(p,
obs_module_text("MaskBlendType.MaskColor"),
"mask_color_filter.effect");
obs_module_text("MaskBlendType.MaskColor"),
"mask_color_filter.effect");
obs_property_list_add_string(p,
obs_module_text("MaskBlendType.MaskAlpha"),
"mask_alpha_filter.effect");
obs_property_list_add_string(p,
obs_module_text("MaskBlendType.BlendMultiply"),
"blend_mul_filter.effect");
obs_property_list_add_string(p,
obs_module_text("MaskBlendType.BlendAddition"),
"blend_add_filter.effect");
obs_property_list_add_string(p,
obs_module_text("MaskBlendType.BlendSubtraction"),
"blend_sub_filter.effect");
obs_module_text("MaskBlendType.MaskAlpha"),
"mask_alpha_filter.effect");
obs_property_list_add_string(
p, obs_module_text("MaskBlendType.BlendMultiply"),
"blend_mul_filter.effect");
obs_property_list_add_string(
p, obs_module_text("MaskBlendType.BlendAddition"),
"blend_add_filter.effect");
obs_property_list_add_string(
p, obs_module_text("MaskBlendType.BlendSubtraction"),
"blend_sub_filter.effect");
obs_properties_add_path(props, SETTING_IMAGE_PATH, TEXT_IMAGE_PATH,
OBS_PATH_FILE, filter_str.array, NULL);
OBS_PATH_FILE, filter_str.array, NULL);
obs_properties_add_color(props, SETTING_COLOR, TEXT_COLOR);
obs_properties_add_int_slider(props, SETTING_OPACITY, TEXT_OPACITY,
0, 100, 1);
obs_properties_add_int_slider(props, SETTING_OPACITY, TEXT_OPACITY, 0,
100, 1);
obs_properties_add_bool(props, SETTING_STRETCH, TEXT_STRETCH);
dstr_free(&filter_str);
@ -159,7 +163,8 @@ static void mask_filter_tick(void *data, float t)
if (!filter->last_time)
filter->last_time = cur_time;
gs_image_file_tick(&filter->image, cur_time - filter->last_time);
gs_image_file_tick(&filter->image,
cur_time - filter->last_time);
obs_enter_graphics();
gs_image_file_update_texture(&filter->image);
obs_leave_graphics();
@ -199,9 +204,8 @@ static void mask_filter_render(void *data, gs_effect_t *effect)
mask_aspect = mask_size.x / mask_size.y;
size_to_x = (source_aspect < mask_aspect);
fix = size_to_x ?
(source_size.x / mask_size.x) :
(source_size.y / mask_size.y);
fix = size_to_x ? (source_size.x / mask_size.x)
: (source_size.y / mask_size.y);
vec2_mulf(&mask_size, &mask_size, fix);
vec2_div(&mul_val, &source_size, &mask_size);
@ -213,7 +217,7 @@ static void mask_filter_render(void *data, gs_effect_t *effect)
}
if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
OBS_ALLOW_DIRECT_RENDERING))
OBS_ALLOW_DIRECT_RENDERING))
return;
param = gs_effect_get_param_by_name(filter->effect, "target");
@ -234,15 +238,15 @@ static void mask_filter_render(void *data, gs_effect_t *effect)
}
struct obs_source_info mask_filter = {
.id = "mask_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = mask_filter_get_name,
.create = mask_filter_create,
.destroy = mask_filter_destroy,
.update = mask_filter_update,
.get_defaults = mask_filter_defaults,
.get_properties = mask_filter_properties,
.video_tick = mask_filter_tick,
.video_render = mask_filter_render
.id = "mask_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = mask_filter_get_name,
.create = mask_filter_create,
.destroy = mask_filter_destroy,
.update = mask_filter_update,
.get_defaults = mask_filter_defaults,
.get_properties = mask_filter_properties,
.video_tick = mask_filter_tick,
.video_render = mask_filter_render,
};

View file

@ -2,12 +2,14 @@
#include <obs-module.h>
#include <math.h>
#define do_log(level, format, ...) \
#define do_log(level, format, ...) \
blog(level, "[noise gate: '%s'] " format, \
obs_source_get_name(ng->context), ##__VA_ARGS__)
obs_source_get_name(ng->context), ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
/* clang-format off */
#define S_OPEN_THRESHOLD "open_threshold"
#define S_CLOSE_THRESHOLD "close_threshold"
@ -22,6 +24,8 @@
#define TEXT_HOLD_TIME MT_("NoiseGate.HoldTime")
#define TEXT_RELEASE_TIME MT_("NoiseGate.ReleaseTime")
/* clang-format on */
struct noise_gate_data {
obs_source_t *context;
@ -104,12 +108,12 @@ static void *noise_gate_create(obs_data_t *settings, obs_source_t *filter)
return ng;
}
static struct obs_audio_data *noise_gate_filter_audio(void *data,
struct obs_audio_data *audio)
static struct obs_audio_data *
noise_gate_filter_audio(void *data, struct obs_audio_data *audio)
{
struct noise_gate_data *ng = data;
float **adata = (float**)audio->data;
float **adata = (float **)audio->data;
const float close_threshold = ng->close_threshold;
const float open_threshold = ng->open_threshold;
const float sample_rate_i = ng->sample_rate_i;
@ -136,13 +140,13 @@ static struct obs_audio_data *noise_gate_filter_audio(void *data,
ng->level = fmaxf(ng->level, cur_level) - decay_rate;
if (ng->is_open) {
ng->attenuation = fminf(1.0f,
ng->attenuation + attack_rate);
ng->attenuation =
fminf(1.0f, ng->attenuation + attack_rate);
} else {
ng->held_time += sample_rate_i;
if (ng->held_time > hold_time) {
ng->attenuation = fmaxf(0.0f,
ng->attenuation - release_rate);
ng->attenuation = fmaxf(
0.0f, ng->attenuation - release_rate);
}
}
@ -157,25 +161,33 @@ static void noise_gate_defaults(obs_data_t *s)
{
obs_data_set_default_double(s, S_OPEN_THRESHOLD, -26.0);
obs_data_set_default_double(s, S_CLOSE_THRESHOLD, -32.0);
obs_data_set_default_int (s, S_ATTACK_TIME, 25);
obs_data_set_default_int (s, S_HOLD_TIME, 200);
obs_data_set_default_int (s, S_RELEASE_TIME, 150);
obs_data_set_default_int(s, S_ATTACK_TIME, 25);
obs_data_set_default_int(s, S_HOLD_TIME, 200);
obs_data_set_default_int(s, S_RELEASE_TIME, 150);
}
static obs_properties_t *noise_gate_properties(void *data)
{
obs_properties_t *ppts = obs_properties_create();
obs_property_t *p;
obs_properties_add_float_slider(ppts, S_CLOSE_THRESHOLD,
TEXT_CLOSE_THRESHOLD, VOL_MIN, VOL_MAX, 1.0);
obs_properties_add_float_slider(ppts, S_OPEN_THRESHOLD,
TEXT_OPEN_THRESHOLD, VOL_MIN, VOL_MAX, 1.0);
obs_properties_add_int(ppts, S_ATTACK_TIME, TEXT_ATTACK_TIME,
0, 10000, 1);
obs_properties_add_int(ppts, S_HOLD_TIME, TEXT_HOLD_TIME,
0, 10000, 1);
obs_properties_add_int(ppts, S_RELEASE_TIME, TEXT_RELEASE_TIME,
0, 10000, 1);
p = obs_properties_add_float_slider(ppts, S_CLOSE_THRESHOLD,
TEXT_CLOSE_THRESHOLD, VOL_MIN,
VOL_MAX, 1.0);
obs_property_float_set_suffix(p, " dB");
p = obs_properties_add_float_slider(ppts, S_OPEN_THRESHOLD,
TEXT_OPEN_THRESHOLD, VOL_MIN,
VOL_MAX, 1.0);
obs_property_float_set_suffix(p, " dB");
p = obs_properties_add_int(ppts, S_ATTACK_TIME, TEXT_ATTACK_TIME, 0,
10000, 1);
obs_property_int_set_suffix(p, " ms");
p = obs_properties_add_int(ppts, S_HOLD_TIME, TEXT_HOLD_TIME, 0, 10000,
1);
obs_property_int_set_suffix(p, " ms");
p = obs_properties_add_int(ppts, S_RELEASE_TIME, TEXT_RELEASE_TIME, 0,
10000, 1);
obs_property_int_set_suffix(p, " ms");
UNUSED_PARAMETER(data);
return ppts;

View file

@ -7,27 +7,27 @@
/* -------------------------------------------------------- */
#define do_log(level, format, ...) \
#define do_log(level, format, ...) \
blog(level, "[noise suppress: '%s'] " format, \
obs_source_get_name(ng->context), ##__VA_ARGS__)
obs_source_get_name(ng->context), ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
#ifdef _DEBUG
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
#else
#define debug(format, ...)
#endif
/* -------------------------------------------------------- */
#define S_SUPPRESS_LEVEL "suppress_level"
#define S_SUPPRESS_LEVEL "suppress_level"
#define MT_ obs_module_text
#define TEXT_SUPPRESS_LEVEL MT_("NoiseSuppress.SuppressLevel")
#define TEXT_SUPPRESS_LEVEL MT_("NoiseSuppress.SuppressLevel")
#define MAX_PREPROC_CHANNELS 8
#define MAX_PREPROC_CHANNELS 8
/* -------------------------------------------------------- */
@ -90,12 +90,13 @@ static void noise_suppress_destroy(void *data)
}
static inline void alloc_channel(struct noise_suppress_data *ng,
uint32_t sample_rate, size_t channel, size_t frames)
uint32_t sample_rate, size_t channel,
size_t frames)
{
ng->states[channel] = speex_preprocess_state_init((int)frames,
sample_rate);
ng->states[channel] =
speex_preprocess_state_init((int)frames, sample_rate);
circlebuf_reserve(&ng->input_buffers[channel], frames * sizeof(float));
circlebuf_reserve(&ng->input_buffers[channel], frames * sizeof(float));
circlebuf_reserve(&ng->output_buffers[channel], frames * sizeof(float));
}
@ -119,13 +120,13 @@ static void noise_suppress_update(void *data, obs_data_t *s)
/* One speex state for each channel (limit 2) */
ng->copy_buffers[0] = bmalloc(frames * channels * sizeof(float));
ng->segment_buffers[0] = bmalloc(frames * channels * sizeof(spx_int16_t));
ng->segment_buffers[0] =
bmalloc(frames * channels * sizeof(spx_int16_t));
for (size_t c = 1; c < channels; ++c) {
ng->copy_buffers[c] = ng->copy_buffers[c-1] + frames;
ng->segment_buffers[c] = ng->segment_buffers[c-1] + frames;
ng->copy_buffers[c] = ng->copy_buffers[c - 1] + frames;
ng->segment_buffers[c] = ng->segment_buffers[c - 1] + frames;
}
for (size_t i = 0; i < channels; i++)
alloc_channel(ng, sample_rate, i, frames);
}
@ -145,22 +146,24 @@ static inline void process(struct noise_suppress_data *ng)
/* Pop from input circlebuf */
for (size_t i = 0; i < ng->channels; i++)
circlebuf_pop_front(&ng->input_buffers[i], ng->copy_buffers[i],
ng->frames * sizeof(float));
ng->frames * sizeof(float));
/* Set args */
for (size_t i = 0; i < ng->channels; i++)
speex_preprocess_ctl(ng->states[i],
SPEEX_PREPROCESS_SET_NOISE_SUPPRESS,
&ng->suppress_level);
SPEEX_PREPROCESS_SET_NOISE_SUPPRESS,
&ng->suppress_level);
/* Convert to 16bit */
for (size_t i = 0; i < ng->channels; i++)
for (size_t j = 0; j < ng->frames; j++) {
float s = ng->copy_buffers[i][j];
if (s > 1.0f) s = 1.0f;
else if (s < -1.0f) s = -1.0f;
ng->segment_buffers[i][j] = (spx_int16_t)
(s * c_32_to_16);
if (s > 1.0f)
s = 1.0f;
else if (s < -1.0f)
s = -1.0f;
ng->segment_buffers[i][j] =
(spx_int16_t)(s * c_32_to_16);
}
/* Execute */
@ -176,7 +179,7 @@ static inline void process(struct noise_suppress_data *ng)
/* Push to output circlebuf */
for (size_t i = 0; i < ng->channels; i++)
circlebuf_push_back(&ng->output_buffers[i], ng->copy_buffers[i],
ng->frames * sizeof(float));
ng->frames * sizeof(float));
}
struct ng_audio_info {
@ -199,8 +202,8 @@ static void reset_data(struct noise_suppress_data *ng)
clear_circlebuf(&ng->info_buffer);
}
static struct obs_audio_data *noise_suppress_filter_audio(void *data,
struct obs_audio_data *audio)
static struct obs_audio_data *
noise_suppress_filter_audio(void *data, struct obs_audio_data *audio)
{
struct noise_suppress_data *ng = data;
struct ng_audio_info info;
@ -216,7 +219,7 @@ static struct obs_audio_data *noise_suppress_filter_audio(void *data,
* from being processed as part of the new data. */
if (ng->last_timestamp) {
int64_t diff = llabs((int64_t)ng->last_timestamp -
(int64_t)audio->timestamp);
(int64_t)audio->timestamp);
if (diff > 1000000000LL)
reset_data(ng);
@ -234,7 +237,7 @@ static struct obs_audio_data *noise_suppress_filter_audio(void *data,
* push back current audio data to input circlebuf */
for (size_t i = 0; i < ng->channels; i++)
circlebuf_push_back(&ng->input_buffers[i], audio->data[i],
audio->frames * sizeof(float));
audio->frames * sizeof(float));
/* -----------------------------------------------
* pop/process each 10ms segments, push back to output circlebuf */
@ -259,11 +262,10 @@ static struct obs_audio_data *noise_suppress_filter_audio(void *data,
for (size_t i = 0; i < ng->channels; i++) {
ng->output_audio.data[i] =
(uint8_t*)&ng->output_data.array[i * out_size];
(uint8_t *)&ng->output_data.array[i * out_size];
circlebuf_pop_front(&ng->output_buffers[i],
ng->output_audio.data[i],
out_size);
ng->output_audio.data[i], out_size);
}
ng->output_audio.frames = info.frames;
@ -280,8 +282,11 @@ static obs_properties_t *noise_suppress_properties(void *data)
{
obs_properties_t *ppts = obs_properties_create();
obs_properties_add_int_slider(ppts, S_SUPPRESS_LEVEL,
TEXT_SUPPRESS_LEVEL, SUP_MIN, SUP_MAX, 1);
obs_property_t *p = obs_properties_add_int_slider(ppts,
S_SUPPRESS_LEVEL,
TEXT_SUPPRESS_LEVEL,
SUP_MIN, SUP_MAX, 1);
obs_property_int_set_suffix(p, " dB");
UNUSED_PARAMETER(data);
return ppts;

View file

@ -6,6 +6,8 @@
#include <graphics/vec2.h>
#include <graphics/math-defs.h>
/* clang-format off */
#define S_RESOLUTION "resolution"
#define S_SAMPLING "sampling"
#define S_UNDISTORT "undistort"
@ -27,25 +29,30 @@
#define S_SAMPLING_LANCZOS "lanczos"
#define S_SAMPLING_AREA "area"
/* clang-format on */
struct scale_filter_data {
obs_source_t *context;
gs_effect_t *effect;
gs_eparam_t *image_param;
gs_eparam_t *dimension_param;
gs_eparam_t *undistort_factor_param;
struct vec2 dimension_i;
double undistort_factor;
int cx_in;
int cy_in;
int cx_out;
int cy_out;
enum obs_scale_type sampling;
gs_samplerstate_t *point_sampler;
bool aspect_ratio_only;
bool target_valid;
bool valid;
bool undistort;
bool base_canvas_resolution;
obs_source_t *context;
gs_effect_t *effect;
gs_eparam_t *image_param;
gs_eparam_t *dimension_param;
gs_eparam_t *dimension_i_param;
gs_eparam_t *undistort_factor_param;
struct vec2 dimension;
struct vec2 dimension_i;
double undistort_factor;
int cx_in;
int cy_in;
int cx_out;
int cy_out;
enum obs_scale_type sampling;
gs_samplerstate_t *point_sampler;
bool aspect_ratio_only;
bool target_valid;
bool valid;
bool undistort;
bool upscale;
bool base_canvas_resolution;
};
static const char *scale_filter_name(void *unused)
@ -78,7 +85,7 @@ static void scale_filter_update(void *data, obs_data_t *settings)
filter->aspect_ratio_only = false;
} else {
ret = sscanf(res_str, "%d:%d", &filter->cx_in,
&filter->cy_in);
&filter->cy_in);
if (ret != 2) {
filter->valid = false;
return;
@ -179,8 +186,7 @@ static void scale_filter_tick(void *data, float seconds)
cy_f = (double)cy;
double old_aspect = cx_f / cy_f;
double new_aspect =
(double)filter->cx_in / (double)filter->cy_in;
double new_aspect = (double)filter->cx_in / (double)filter->cy_in;
if (filter->aspect_ratio_only) {
if (fabs(old_aspect - new_aspect) <= EPSILON) {
@ -200,9 +206,8 @@ static void scale_filter_tick(void *data, float seconds)
filter->cy_out = filter->cy_in;
}
vec2_set(&filter->dimension_i,
1.0f / (float)cx,
1.0f / (float)cy);
vec2_set(&filter->dimension, (float)cx, (float)cy);
vec2_set(&filter->dimension_i, 1.0f / (float)cx, 1.0f / (float)cy);
if (filter->undistort) {
filter->undistort_factor = new_aspect / old_aspect;
@ -210,6 +215,8 @@ static void scale_filter_tick(void *data, float seconds)
filter->undistort_factor = 1.0;
}
filter->upscale = false;
/* ------------------------- */
lower_than_2x = filter->cx_out < cx / 2 || filter->cy_out < cy / 2;
@ -220,29 +227,41 @@ static void scale_filter_tick(void *data, float seconds)
switch (filter->sampling) {
default:
case OBS_SCALE_POINT:
case OBS_SCALE_BILINEAR: type = OBS_EFFECT_DEFAULT; break;
case OBS_SCALE_BICUBIC: type = OBS_EFFECT_BICUBIC; break;
case OBS_SCALE_LANCZOS: type = OBS_EFFECT_LANCZOS; break;
case OBS_SCALE_AREA: type = OBS_EFFECT_AREA; break;
case OBS_SCALE_BILINEAR:
type = OBS_EFFECT_DEFAULT;
break;
case OBS_SCALE_BICUBIC:
type = OBS_EFFECT_BICUBIC;
break;
case OBS_SCALE_LANCZOS:
type = OBS_EFFECT_LANCZOS;
break;
case OBS_SCALE_AREA:
type = OBS_EFFECT_AREA;
if ((filter->cx_out >= cx) && (filter->cy_out >= cy))
filter->upscale = true;
break;
}
}
filter->effect = obs_get_base_effect(type);
filter->image_param = gs_effect_get_param_by_name(filter->effect,
"image");
filter->image_param =
gs_effect_get_param_by_name(filter->effect, "image");
if (type != OBS_EFFECT_DEFAULT) {
filter->dimension_param = gs_effect_get_param_by_name(
filter->effect, "base_dimension_i");
filter->effect, "base_dimension");
filter->dimension_i_param = gs_effect_get_param_by_name(
filter->effect, "base_dimension_i");
} else {
filter->dimension_param = NULL;
filter->dimension_i_param = NULL;
}
if (type == OBS_EFFECT_BICUBIC || type == OBS_EFFECT_LANCZOS) {
filter->undistort_factor_param = gs_effect_get_param_by_name(
filter->effect, "undistort_factor");
}
else {
} else {
filter->undistort_factor_param = NULL;
}
@ -252,8 +271,9 @@ static void scale_filter_tick(void *data, float seconds)
static void scale_filter_render(void *data, gs_effect_t *effect)
{
struct scale_filter_data *filter = data;
const char *technique = filter->undistort ?
"DrawUndistort" : "Draw";
const char *technique =
filter->undistort ? "DrawUndistort"
: (filter->upscale ? "DrawUpscale" : "Draw");
if (!filter->valid || !filter->target_valid) {
obs_source_skip_video_filter(filter->context);
@ -261,75 +281,61 @@ static void scale_filter_render(void *data, gs_effect_t *effect)
}
if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
OBS_NO_DIRECT_RENDERING))
OBS_NO_DIRECT_RENDERING))
return;
if (filter->dimension_param)
gs_effect_set_vec2(filter->dimension_param,
&filter->dimension_i);
gs_effect_set_vec2(filter->dimension_param, &filter->dimension);
if (filter->dimension_i_param)
gs_effect_set_vec2(filter->dimension_i_param,
&filter->dimension_i);
if (filter->undistort_factor_param)
gs_effect_set_float(filter->undistort_factor_param,
(float)filter->undistort_factor);
(float)filter->undistort_factor);
if (filter->sampling == OBS_SCALE_POINT)
gs_effect_set_next_sampler(filter->image_param,
filter->point_sampler);
filter->point_sampler);
obs_source_process_filter_tech_end(filter->context, filter->effect,
filter->cx_out, filter->cy_out, technique);
filter->cx_out, filter->cy_out,
technique);
UNUSED_PARAMETER(effect);
}
static const double downscale_vals[] = {
1.0,
1.25,
(1.0/0.75),
1.5,
(1.0/0.6),
1.75,
2.0,
2.25,
2.5,
2.75,
3.0
};
static const double downscale_vals[] = {1.0, 1.25, (1.0 / 0.75), 1.5,
(1.0 / 0.6), 1.75, 2.0, 2.25,
2.5, 2.75, 3.0};
#define NUM_DOWNSCALES (sizeof(downscale_vals) / sizeof(double))
static const char *aspects[] = {
"16:9",
"16:10",
"4:3",
"1:1"
};
static const char *aspects[] = {"16:9", "16:10", "4:3", "1:1"};
#define NUM_ASPECTS (sizeof(aspects) / sizeof(const char *))
static bool sampling_modified(obs_properties_t *props, obs_property_t *p,
obs_data_t *settings)
obs_data_t *settings)
{
const char *sampling = obs_data_get_string(settings, S_SAMPLING);
bool has_undistort;
if (astrcmpi(sampling, S_SAMPLING_POINT) == 0) {
has_undistort = false;
}
else if (astrcmpi(sampling, S_SAMPLING_BILINEAR) == 0) {
} else if (astrcmpi(sampling, S_SAMPLING_BILINEAR) == 0) {
has_undistort = false;
}
else if (astrcmpi(sampling, S_SAMPLING_LANCZOS) == 0) {
} else if (astrcmpi(sampling, S_SAMPLING_LANCZOS) == 0) {
has_undistort = true;
}
else if (astrcmpi(sampling, S_SAMPLING_AREA) == 0) {
} else if (astrcmpi(sampling, S_SAMPLING_AREA) == 0) {
has_undistort = false;
}
else { /* S_SAMPLING_BICUBIC */
} else { /* S_SAMPLING_BICUBIC */
has_undistort = true;
}
obs_property_set_visible(obs_properties_get(props, S_UNDISTORT), has_undistort);
obs_property_set_visible(obs_properties_get(props, S_UNDISTORT),
has_undistort);
UNUSED_PARAMETER(p);
return true;
@ -360,18 +366,21 @@ static obs_properties_t *scale_filter_properties(void *data)
}
p = obs_properties_add_list(props, S_SAMPLING, T_SAMPLING,
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
obs_property_set_modified_callback(p, sampling_modified);
obs_property_list_add_string(p, T_SAMPLING_POINT, S_SAMPLING_POINT);
obs_property_list_add_string(p, T_SAMPLING_BILINEAR, S_SAMPLING_BILINEAR);
obs_property_list_add_string(p, T_SAMPLING_BICUBIC, S_SAMPLING_BICUBIC);
obs_property_list_add_string(p, T_SAMPLING_LANCZOS, S_SAMPLING_LANCZOS);
obs_property_list_add_string(p, T_SAMPLING_AREA, S_SAMPLING_AREA);
obs_property_list_add_string(p, T_SAMPLING_POINT, S_SAMPLING_POINT);
obs_property_list_add_string(p, T_SAMPLING_BILINEAR,
S_SAMPLING_BILINEAR);
obs_property_list_add_string(p, T_SAMPLING_BICUBIC, S_SAMPLING_BICUBIC);
obs_property_list_add_string(p, T_SAMPLING_LANCZOS, S_SAMPLING_LANCZOS);
obs_property_list_add_string(p, T_SAMPLING_AREA, S_SAMPLING_AREA);
/* ----------------- */
p = obs_properties_add_list(props, S_RESOLUTION, T_RESOLUTION,
OBS_COMBO_TYPE_EDITABLE, OBS_COMBO_FORMAT_STRING);
OBS_COMBO_TYPE_EDITABLE,
OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(p, T_NONE, T_NONE);
obs_property_list_add_string(p, T_BASE, T_BASE);
@ -413,17 +422,17 @@ static uint32_t scale_filter_height(void *data)
}
struct obs_source_info scale_filter = {
.id = "scale_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = scale_filter_name,
.create = scale_filter_create,
.destroy = scale_filter_destroy,
.video_tick = scale_filter_tick,
.video_render = scale_filter_render,
.update = scale_filter_update,
.get_properties = scale_filter_properties,
.get_defaults = scale_filter_defaults,
.get_width = scale_filter_width,
.get_height = scale_filter_height
.id = "scale_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = scale_filter_name,
.create = scale_filter_create,
.destroy = scale_filter_destroy,
.video_tick = scale_filter_tick,
.video_render = scale_filter_render,
.update = scale_filter_update,
.get_properties = scale_filter_properties,
.get_defaults = scale_filter_defaults,
.get_width = scale_filter_width,
.get_height = scale_filter_height,
};

View file

@ -2,22 +2,22 @@
#include <graphics/vec2.h>
struct scroll_filter_data {
obs_source_t *context;
obs_source_t *context;
gs_effect_t *effect;
gs_eparam_t *param_add;
gs_eparam_t *param_mul;
gs_eparam_t *param_image;
gs_effect_t *effect;
gs_eparam_t *param_add;
gs_eparam_t *param_mul;
gs_eparam_t *param_image;
struct vec2 scroll_speed;
gs_samplerstate_t *sampler;
bool limit_cx;
bool limit_cy;
uint32_t cx;
uint32_t cy;
struct vec2 scroll_speed;
gs_samplerstate_t *sampler;
bool limit_cx;
bool limit_cy;
uint32_t cx;
uint32_t cy;
struct vec2 size_i;
struct vec2 offset;
struct vec2 size_i;
struct vec2 offset;
};
static const char *scroll_filter_get_name(void *unused)
@ -31,11 +31,9 @@ static void *scroll_filter_create(obs_data_t *settings, obs_source_t *context)
struct scroll_filter_data *filter = bzalloc(sizeof(*filter));
char *effect_path = obs_module_file("crop_filter.effect");
struct gs_sampler_info sampler_info = {
.filter = GS_FILTER_LINEAR,
.address_u = GS_ADDRESS_WRAP,
.address_v = GS_ADDRESS_WRAP
};
struct gs_sampler_info sampler_info = {.filter = GS_FILTER_LINEAR,
.address_u = GS_ADDRESS_WRAP,
.address_v = GS_ADDRESS_WRAP};
filter->context = context;
@ -51,12 +49,12 @@ static void *scroll_filter_create(obs_data_t *settings, obs_source_t *context)
return NULL;
}
filter->param_add = gs_effect_get_param_by_name(filter->effect,
"add_val");
filter->param_mul = gs_effect_get_param_by_name(filter->effect,
"mul_val");
filter->param_image = gs_effect_get_param_by_name(filter->effect,
"image");
filter->param_add =
gs_effect_get_param_by_name(filter->effect, "add_val");
filter->param_mul =
gs_effect_get_param_by_name(filter->effect, "mul_val");
filter->param_image =
gs_effect_get_param_by_name(filter->effect, "image");
obs_source_update(context, settings);
return filter;
@ -83,10 +81,10 @@ static void scroll_filter_update(void *data, obs_data_t *settings)
filter->cx = (uint32_t)obs_data_get_int(settings, "cx");
filter->cy = (uint32_t)obs_data_get_int(settings, "cy");
filter->scroll_speed.x = (float)obs_data_get_double(settings,
"speed_x");
filter->scroll_speed.y = (float)obs_data_get_double(settings,
"speed_y");
filter->scroll_speed.x =
(float)obs_data_get_double(settings, "speed_x");
filter->scroll_speed.y =
(float)obs_data_get_double(settings, "speed_y");
if (filter->scroll_speed.x == 0.0f)
filter->offset.x = 0.0f;
@ -95,7 +93,7 @@ static void scroll_filter_update(void *data, obs_data_t *settings)
}
static bool limit_cx_clicked(obs_properties_t *props, obs_property_t *p,
obs_data_t *settings)
obs_data_t *settings)
{
bool limit_size = obs_data_get_bool(settings, "limit_cx");
obs_property_set_visible(obs_properties_get(props, "cx"), limit_size);
@ -105,7 +103,7 @@ static bool limit_cx_clicked(obs_properties_t *props, obs_property_t *p,
}
static bool limit_cy_clicked(obs_properties_t *props, obs_property_t *p,
obs_data_t *settings)
obs_data_t *settings)
{
bool limit_size = obs_data_get_bool(settings, "limit_cy");
obs_property_set_visible(obs_properties_get(props, "cy"), limit_size);
@ -120,23 +118,23 @@ static obs_properties_t *scroll_filter_properties(void *data)
obs_property_t *p;
obs_properties_add_float_slider(props, "speed_x",
obs_module_text("ScrollFilter.SpeedX"),
-500.0, 500.0, 1.0);
obs_module_text("ScrollFilter.SpeedX"),
-500.0, 500.0, 1.0);
obs_properties_add_float_slider(props, "speed_y",
obs_module_text("ScrollFilter.SpeedY"),
-500.0, 500.0, 1.0);
obs_module_text("ScrollFilter.SpeedY"),
-500.0, 500.0, 1.0);
p = obs_properties_add_bool(props, "limit_cx",
obs_module_text("ScrollFilter.LimitWidth"));
obs_module_text("ScrollFilter.LimitWidth"));
obs_property_set_modified_callback(p, limit_cx_clicked);
obs_properties_add_int(props, "cx",
obs_module_text("Crop.Width"), 1, 8192, 1);
obs_properties_add_int(props, "cx", obs_module_text("Crop.Width"), 1,
8192, 1);
p = obs_properties_add_bool(props, "limit_cy",
obs_module_text("ScrollFilter.LimitHeight"));
p = obs_properties_add_bool(
props, "limit_cy", obs_module_text("ScrollFilter.LimitHeight"));
obs_property_set_modified_callback(p, limit_cy_clicked);
obs_properties_add_int(props, "cy",
obs_module_text("Crop.Height"), 1, 8192, 1);
obs_properties_add_int(props, "cy", obs_module_text("Crop.Height"), 1,
8192, 1);
UNUSED_PARAMETER(data);
return props;
@ -179,21 +177,19 @@ static void scroll_filter_render(void *data, gs_effect_t *effect)
cy = filter->limit_cy ? filter->cy : base_cy;
if (base_cx && base_cy) {
vec2_set(&filter->size_i,
1.0f / (float)base_cx,
1.0f / (float)base_cy);
vec2_set(&filter->size_i, 1.0f / (float)base_cx,
1.0f / (float)base_cy);
} else {
vec2_zero(&filter->size_i);
obs_source_skip_video_filter(filter->context);
return;
}
vec2_set(&mul_val,
(float)cx / (float)base_cx,
(float)cy / (float)base_cy);
vec2_set(&mul_val, (float)cx / (float)base_cx,
(float)cy / (float)base_cy);
if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
OBS_NO_DIRECT_RENDERING))
OBS_NO_DIRECT_RENDERING))
return;
gs_effect_set_vec2(filter->param_add, &filter->offset);
@ -211,8 +207,8 @@ static uint32_t scroll_filter_width(void *data)
struct scroll_filter_data *filter = data;
obs_source_t *target = obs_filter_get_target(filter->context);
return filter->limit_cx ?
filter->cx : obs_source_get_base_width(target);
return filter->limit_cx ? filter->cx
: obs_source_get_base_width(target);
}
static uint32_t scroll_filter_height(void *data)
@ -220,22 +216,22 @@ static uint32_t scroll_filter_height(void *data)
struct scroll_filter_data *filter = data;
obs_source_t *target = obs_filter_get_target(filter->context);
return filter->limit_cy ?
filter->cy : obs_source_get_base_height(target);
return filter->limit_cy ? filter->cy
: obs_source_get_base_height(target);
}
struct obs_source_info scroll_filter = {
.id = "scroll_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = scroll_filter_get_name,
.create = scroll_filter_create,
.destroy = scroll_filter_destroy,
.update = scroll_filter_update,
.get_properties = scroll_filter_properties,
.get_defaults = scroll_filter_defaults,
.video_tick = scroll_filter_tick,
.video_render = scroll_filter_render,
.get_width = scroll_filter_width,
.get_height = scroll_filter_height
.id = "scroll_filter",
.type = OBS_SOURCE_TYPE_FILTER,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = scroll_filter_get_name,
.create = scroll_filter_create,
.destroy = scroll_filter_destroy,
.update = scroll_filter_update,
.get_properties = scroll_filter_properties,
.get_defaults = scroll_filter_defaults,
.video_tick = scroll_filter_tick,
.video_render = scroll_filter_render,
.get_width = scroll_filter_width,
.get_height = scroll_filter_height,
};

View file

@ -4,14 +4,14 @@
#include <util/platform.h>
struct sharpness_data {
obs_source_t *context;
obs_source_t *context;
gs_effect_t *effect;
gs_eparam_t *sharpness_param;
gs_eparam_t *texture_width, *texture_height;
gs_effect_t *effect;
gs_eparam_t *sharpness_param;
gs_eparam_t *texture_width, *texture_height;
float sharpness;
float texwidth, texheight;
float sharpness;
float texwidth, texheight;
};
static const char *sharpness_getname(void *unused)
@ -43,8 +43,7 @@ static void sharpness_destroy(void *data)
static void *sharpness_create(obs_data_t *settings, obs_source_t *context)
{
struct sharpness_data *filter =
bzalloc(sizeof(struct sharpness_data));
struct sharpness_data *filter = bzalloc(sizeof(struct sharpness_data));
char *effect_path = obs_module_file("sharpness.effect");
filter->context = context;
@ -79,13 +78,13 @@ static void sharpness_render(void *data, gs_effect_t *effect)
struct sharpness_data *filter = data;
if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
OBS_ALLOW_DIRECT_RENDERING))
OBS_ALLOW_DIRECT_RENDERING))
return;
filter->texwidth =(float)obs_source_get_width(
obs_filter_get_target(filter->context));
filter->texwidth = (float)obs_source_get_width(
obs_filter_get_target(filter->context));
filter->texheight = (float)obs_source_get_height(
obs_filter_get_target(filter->context));
obs_filter_get_target(filter->context));
gs_effect_set_float(filter->sharpness_param, filter->sharpness);
gs_effect_set_float(filter->texture_width, filter->texwidth);
@ -100,8 +99,8 @@ static obs_properties_t *sharpness_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
obs_properties_add_float_slider(props, "sharpness",
"Sharpness", 0.0, 1.0, 0.01);
obs_properties_add_float_slider(props, "sharpness", "Sharpness", 0.0,
1.0, 0.01);
UNUSED_PARAMETER(data);
return props;
@ -122,5 +121,5 @@ struct obs_source_info sharpness_filter = {
.update = sharpness_update,
.video_render = sharpness_render,
.get_properties = sharpness_properties,
.get_defaults = sharpness_defaults
.get_defaults = sharpness_defaults,
};