New upstream version 24.0.1+dfsg1
This commit is contained in:
parent
b14f9eae6d
commit
5a730d6ec3
842 changed files with 42245 additions and 33385 deletions
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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="Порта"
|
||||
|
||||
|
|
|
|||
|
|
@ -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 (1 — 1000)"
|
||||
Smoothness="Glätte (1 — 1000)"
|
||||
ColorSpillReduction="Key-Farbe-Spill-Reduzierung (1 — 1000)"
|
||||
KeyColorType="Key‐Farbtyp"
|
||||
KeyColor="Key‐Farbe"
|
||||
Similarity="Ähnlichkeit (1–1000)"
|
||||
Smoothness="Glätte (1–1000)"
|
||||
ColorSpillReduction="Key‐Farbe‐Spill‐Reduzierung (1–1000)"
|
||||
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="Öffnungs‐Schwellwert (dB)"
|
||||
NoiseGate.CloseThreshold="Schließungs‐Schwellwert (dB)"
|
||||
NoiseGate.AttackTime="Attack‐Zeit (Millisekunden)"
|
||||
NoiseGate.HoldTime="Hold‐Zeit (Millisekunden)"
|
||||
NoiseGate.ReleaseTime="Release‐Zeit (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‐/Ducking‐Quelle"
|
||||
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. Luma‐Glätte"
|
||||
Luma.LumaMinSmooth="Min. Luma‐Glätte"
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -96,6 +96,6 @@ Expander.Presets.Gate="ゲート"
|
|||
LumaKeyFilter="ルマキー"
|
||||
Luma.LumaMax="最大輝度"
|
||||
Luma.LumaMin="最小輝度"
|
||||
Luma.LumaMaxSmooth="ルマ最大スムーズ"
|
||||
Luma.LumaMinSmooth="ルマ最小スムーズ"
|
||||
Luma.LumaMaxSmooth="最大輝度グラデーション"
|
||||
Luma.LumaMinSmooth="最小輝度グラデーション"
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ ScaleFiltering.Point="წერტილოვანი"
|
|||
ScaleFiltering.Bilinear="ორხაზოვანი"
|
||||
ScaleFiltering.Bicubic="ბიკუბური"
|
||||
ScaleFiltering.Lanczos="Lanczos"
|
||||
ScaleFiltering.Area="სივრცე"
|
||||
ScaleFiltering.Area="სივრცითი"
|
||||
NoiseSuppress.SuppressLevel="დახშობის ხარისხი (dB)"
|
||||
Saturation="გაჯერებულობა"
|
||||
HueShift="შეფერილობის შეცვლა"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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)"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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)"
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue