OpenShot Library | libopenshot 0.3.2
Loading...
Searching...
No Matches
Expander.cpp
Go to the documentation of this file.
1
9// Copyright (c) 2008-2019 OpenShot Studios, LLC
10//
11// SPDX-License-Identifier: LGPL-3.0-or-later
12
13#include "Expander.h"
14#include "Exceptions.h"
15#include "Frame.h"
16
17using namespace openshot;
18
19Expander::Expander(): Expander::Expander(-10, 1, 1, 1, 1, false) { }
20
21// Default constructor
23 Keyframe release, Keyframe makeup_gain, Keyframe bypass) :
24 threshold(threshold), ratio(ratio), attack(attack),
25 release(release), makeup_gain(makeup_gain), bypass(bypass)
26{
27 // Init effect properties
28 init_effect_details();
29}
30
31// Init effect settings
32void Expander::init_effect_details()
33{
36
38 info.class_name = "Expander";
39 info.name = "Expander";
40 info.description = "Louder parts of audio becomes relatively louder and quieter parts becomes quieter.";
41 info.has_audio = true;
42 info.has_video = false;
43
44 input_level = 0.0f;
45 yl_prev = 0.0f;
46
47
48}
49
50// This method is required for all derived classes of EffectBase, and returns a
51// modified openshot::Frame object
52std::shared_ptr<openshot::Frame> Expander::GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number)
53{
54 // Adding Expander
55 const int num_input_channels = frame->audio->getNumChannels();
56 const int num_output_channels = frame->audio->getNumChannels();
57 const int num_samples = frame->audio->getNumSamples();
58
59 mixed_down_input.setSize(1, num_samples);
60 inverse_sample_rate = 1.0f / frame->SampleRate();
61 inverseE = 1.0f / M_E;
62
63 if ((bool)bypass.GetValue(frame_number))
64 return frame;
65
66 mixed_down_input.clear();
67
68 for (int channel = 0; channel < num_input_channels; ++channel)
69 mixed_down_input.addFrom(0, 0, *frame->audio, channel, 0, num_samples, 1.0f / num_input_channels);
70
71 for (int sample = 0; sample < num_samples; ++sample) {
72 float T = threshold.GetValue(frame_number);
73 float R = ratio.GetValue(frame_number);
74 float alphaA = calculateAttackOrRelease(attack.GetValue(frame_number));
75 float alphaR = calculateAttackOrRelease(release.GetValue(frame_number));
76 float gain = makeup_gain.GetValue(frame_number);
77 float input_squared = powf(mixed_down_input.getSample(0, sample), 2.0f);
78
79 const float average_factor = 0.9999f;
80 input_level = average_factor * input_level + (1.0f - average_factor) * input_squared;
81
82 xg = (input_level <= 1e-6f) ? -60.0f : 10.0f * log10f(input_level);
83
84 if (xg > T)
85 yg = xg;
86 else
87 yg = T + (xg - T) * R;
88
89 xl = xg - yg;
90
91 if (xl < yl_prev)
92 yl = alphaA * yl_prev + (1.0f - alphaA) * xl;
93 else
94 yl = alphaR * yl_prev + (1.0f - alphaR) * xl;
95
96
97 control = powf (10.0f, (gain - yl) * 0.05f);
98 yl_prev = yl;
99
100 for (int channel = 0; channel < num_input_channels; ++channel) {
101 float new_value = frame->audio->getSample(channel, sample)*control;
102 frame->audio->setSample(channel, sample, new_value);
103 }
104 }
105
106 for (int channel = num_input_channels; channel < num_output_channels; ++channel)
107 frame->audio->clear(channel, 0, num_samples);
108
109 // return the modified frame
110 return frame;
111}
112
114{
115 if (value == 0.0f)
116 return 0.0f;
117 else
118 return pow (inverseE, inverse_sample_rate / value);
119}
120
121// Generate JSON string of this object
122std::string Expander::Json() const {
123
124 // Return formatted string
125 return JsonValue().toStyledString();
126}
127
128// Generate Json::Value for this object
129Json::Value Expander::JsonValue() const {
130
131 // Create root json object
132 Json::Value root = EffectBase::JsonValue(); // get parent properties
133 root["type"] = info.class_name;
134 root["threshold"] = threshold.JsonValue();
135 root["ratio"] = ratio.JsonValue();
136 root["attack"] = attack.JsonValue();
137 root["release"] = release.JsonValue();
138 root["makeup_gain"] = makeup_gain.JsonValue();
139 root["bypass"] = bypass.JsonValue();
140
141 // return JsonValue
142 return root;
143}
144
145// Load JSON string into this object
146void Expander::SetJson(const std::string value) {
147
148 // Parse JSON string into JSON objects
149 try
150 {
151 const Json::Value root = openshot::stringToJson(value);
152 // Set all values that match
153 SetJsonValue(root);
154 }
155 catch (const std::exception& e)
156 {
157 // Error parsing JSON (or missing keys)
158 throw InvalidJSON("JSON is invalid (missing keys or invalid data types)");
159 }
160}
161
162// Load Json::Value into this object
163void Expander::SetJsonValue(const Json::Value root) {
164
165 // Set parent data
167
168 // Set data from Json (if key is found)
169 if (!root["threshold"].isNull())
170 threshold.SetJsonValue(root["threshold"]);
171
172 if (!root["ratio"].isNull())
173 ratio.SetJsonValue(root["ratio"]);
174
175 if (!root["attack"].isNull())
176 attack.SetJsonValue(root["attack"]);
177
178 if (!root["release"].isNull())
179 release.SetJsonValue(root["release"]);
180
181 if (!root["makeup_gain"].isNull())
182 makeup_gain.SetJsonValue(root["makeup_gain"]);
183
184 if (!root["bypass"].isNull())
185 bypass.SetJsonValue(root["bypass"]);
186}
187
188// Get all properties for a specific frame
189std::string Expander::PropertiesJSON(int64_t requested_frame) const {
190
191 // Generate JSON properties list
192 Json::Value root;
193 root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame);
194 root["layer"] = add_property_json("Track", Layer(), "int", "", NULL, 0, 20, false, requested_frame);
195 root["start"] = add_property_json("Start", Start(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame);
196 root["end"] = add_property_json("End", End(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame);
197 root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 1000 * 60 * 30, true, requested_frame);
198
199 // Keyframes
200 root["threshold"] = add_property_json("Threshold (dB)", threshold.GetValue(requested_frame), "float", "", &threshold, -60, 0, false, requested_frame);
201 root["ratio"] = add_property_json("Ratio", ratio.GetValue(requested_frame), "float", "", &ratio, 1, 100, false, requested_frame);
202 root["attack"] = add_property_json("Attack (ms)", attack.GetValue(requested_frame), "float", "", &attack, 0.1, 100, false, requested_frame);
203 root["release"] = add_property_json("Release (ms)", release.GetValue(requested_frame), "float", "", &release, 10, 1000, false, requested_frame);
204 root["makeup_gain"] = add_property_json("Makeup gain (dB)", makeup_gain.GetValue(requested_frame), "float", "", &makeup_gain, -12, 12, false, requested_frame);
205 root["bypass"] = add_property_json("Bypass", bypass.GetValue(requested_frame), "bool", "", &bypass, 0, 1, false, requested_frame);
206
207 // Return formatted string
208 return root.toStyledString();
209}
Header file for all Exception classes.
Header file for Expander audio effect class.
Header file for Frame class.
float Start() const
Get start position (in seconds) of clip (trim start of video)
Definition ClipBase.h:88
float Duration() const
Get the length of this clip (in seconds)
Definition ClipBase.h:90
virtual float End() const
Get end position (in seconds) of clip (trim end of video)
Definition ClipBase.h:89
std::string Id() const
Get the Id of this clip object.
Definition ClipBase.h:85
int Layer() const
Get layer of clip on timeline (lower number is covered by higher numbers)
Definition ClipBase.h:87
Json::Value add_property_json(std::string name, float value, std::string type, std::string memo, const Keyframe *keyframe, float min_value, float max_value, bool readonly, int64_t requested_frame) const
Generate JSON for a property.
Definition ClipBase.cpp:96
virtual Json::Value JsonValue() const
Generate Json::Value for this object.
virtual void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
EffectInfoStruct info
Information about the current effect.
Definition EffectBase.h:69
This class adds a expander (or noise gate) into the audio.
Definition Expander.h:37
Expander()
Default constructor.
Definition Expander.cpp:19
float inverse_sample_rate
Definition Expander.h:61
std::string PropertiesJSON(int64_t requested_frame) const override
Definition Expander.cpp:189
void SetJsonValue(const Json::Value root) override
Load Json::Value into this object.
Definition Expander.cpp:163
Keyframe makeup_gain
Definition Expander.h:48
Keyframe release
Definition Expander.h:47
float calculateAttackOrRelease(float value)
Definition Expander.cpp:113
void SetJson(const std::string value) override
Load JSON string into this object.
Definition Expander.cpp:146
Keyframe threshold
Definition Expander.h:44
Keyframe bypass
Definition Expander.h:49
Keyframe attack
Definition Expander.h:46
Json::Value JsonValue() const override
Generate Json::Value for this object.
Definition Expander.cpp:129
juce::AudioBuffer< float > mixed_down_input
Definition Expander.h:51
std::string Json() const override
Generate JSON string of this object.
Definition Expander.cpp:122
std::shared_ptr< openshot::Frame > GetFrame(int64_t frame_number) override
This method is required for all derived classes of ClipBase, and returns a new openshot::Frame object...
Definition Expander.h:73
Exception for invalid JSON.
Definition Exceptions.h:218
A Keyframe is a collection of Point instances, which is used to vary a number or property over time.
Definition KeyFrame.h:53
void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
Definition KeyFrame.cpp:372
double GetValue(int64_t index) const
Get the value at a specific index.
Definition KeyFrame.cpp:258
Json::Value JsonValue() const
Generate Json::Value for this object.
Definition KeyFrame.cpp:339
This namespace is the default namespace for all code in the openshot library.
Definition Compressor.h:29
const Json::Value stringToJson(const std::string value)
Definition Json.cpp:16
bool has_video
Determines if this effect manipulates the image of a frame.
Definition EffectBase.h:40
bool has_audio
Determines if this effect manipulates the audio of a frame.
Definition EffectBase.h:41
std::string class_name
The class name of the effect.
Definition EffectBase.h:36
std::string name
The name of the effect.
Definition EffectBase.h:37
std::string description
The description of this effect and what it does.
Definition EffectBase.h:38