OpenShot Library | libopenshot 0.3.3
Loading...
Searching...
No Matches
Distortion.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 "Distortion.h"
14#include "Exceptions.h"
15
16using namespace openshot;
17
19
21 Keyframe input_gain, Keyframe output_gain,
22 Keyframe tone):
23 distortion_type(distortion_type), input_gain(input_gain),
24 output_gain(output_gain), tone(tone)
25{
26 // Init effect properties
27 init_effect_details();
28}
29
30// Init effect settings
31void Distortion::init_effect_details()
32{
35
37 info.class_name = "Distortion";
38 info.name = "Distortion";
39 info.description = "Alter the audio by clipping the signal.";
40 info.has_audio = true;
41 info.has_video = false;
42}
43
44
45// This method is required for all derived classes of EffectBase, and returns a
46// modified openshot::Frame object
47std::shared_ptr<openshot::Frame> Distortion::GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number)
48{
49 filters.clear();
50
51 for (int i = 0; i < frame->audio->getNumChannels(); ++i) {
52 Filter* filter;
53 filters.add (filter = new Filter());
54 }
55
56 updateFilters(frame_number);
57
58 // Add distortion
59 for (int channel = 0; channel < frame->audio->getNumChannels(); channel++)
60 {
61 auto *channel_data = frame->audio->getWritePointer(channel);
62 float out;
63
64 for (auto sample = 0; sample < frame->audio->getNumSamples(); ++sample)
65 {
66
67 const int input_gain_value = (int)input_gain.GetValue(frame_number);
68 const int output_gain_value = (int)output_gain.GetValue(frame_number);
69 const float in = channel_data[sample]*powf(10.0f, input_gain_value * 0.05f);
70
71 // Use the current distortion type
72 switch (distortion_type) {
73
74 case HARD_CLIPPING: {
75 float threshold = 0.5f;
76 if (in > threshold)
77 out = threshold;
78 else if (in < -threshold)
79 out = -threshold;
80 else
81 out = in;
82 break;
83 }
84
85 case SOFT_CLIPPING: {
86 float threshold1 = 1.0f / 3.0f;
87 float threshold2 = 2.0f / 3.0f;
88 if (in > threshold2)
89 out = 1.0f;
90 else if (in > threshold1)
91 out = 1.0f - powf (2.0f - 3.0f * in, 2.0f) / 3.0f;
92 else if (in < -threshold2)
93 out = -1.0f;
94 else if (in < -threshold1)
95 out = -1.0f + powf (2.0f + 3.0f * in, 2.0f) / 3.0f;
96 else
97 out = 2.0f * in;
98 out *= 0.5f;
99 break;
100 }
101
102 case EXPONENTIAL: {
103 if (in > 0.0f)
104 out = 1.0f - expf (-in);
105 else
106 out = -1.0f + expf (in);
107 break;
108 }
109
110 case FULL_WAVE_RECTIFIER: {
111 out = fabsf (in);
112 break;
113 }
114
115 case HALF_WAVE_RECTIFIER: {
116 if (in > 0.0f)
117 out = in;
118 else
119 out = 0.0f;
120 break;
121 }
122 }
123
124 float filtered = filters[channel]->processSingleSampleRaw(out);
125 channel_data[sample] = filtered*powf(10.0f, output_gain_value * 0.05f);
126 }
127 }
128
129 // return the modified frame
130 return frame;
131}
132
133void Distortion::updateFilters(int64_t frame_number)
134{
135 double discrete_frequency = M_PI * 0.01;
136 double gain = pow(10.0, (float)tone.GetValue(frame_number) * 0.05);
137
138 for (int i = 0; i < filters.size(); ++i)
139 filters[i]->updateCoefficients(discrete_frequency, gain);
140}
141
142// Generate JSON string of this object
143std::string Distortion::Json() const {
144
145 // Return formatted string
146 return JsonValue().toStyledString();
147}
148
149void Distortion::Filter::updateCoefficients(const double discrete_frequency, const double gain)
150{
151 double tan_half_wc = tan(discrete_frequency / 2.0);
152 double sqrt_gain = sqrt(gain);
153
154 coefficients = juce::IIRCoefficients(/* b0 */ sqrt_gain * tan_half_wc + gain,
155 /* b1 */ sqrt_gain * tan_half_wc - gain,
156 /* b2 */ 0.0,
157 /* a0 */ sqrt_gain * tan_half_wc + 1.0,
158 /* a1 */ sqrt_gain * tan_half_wc - 1.0,
159 /* a2 */ 0.0);
160 setCoefficients(coefficients);
161}
162
163// Generate Json::Value for this object
164Json::Value Distortion::JsonValue() const {
165
166 // Create root json object
167 Json::Value root = EffectBase::JsonValue(); // get parent properties
168 root["type"] = info.class_name;
169 root["distortion_type"] = distortion_type;
170 root["input_gain"] = input_gain.JsonValue();
171 root["output_gain"] = output_gain.JsonValue();
172 root["tone"] = tone.JsonValue();
173
174 // return JsonValue
175 return root;
176}
177
178// Load JSON string into this object
179void Distortion::SetJson(const std::string value) {
180
181 // Parse JSON string into JSON objects
182 try
183 {
184 const Json::Value root = openshot::stringToJson(value);
185 // Set all values that match
186 SetJsonValue(root);
187 }
188 catch (const std::exception& e)
189 {
190 // Error parsing JSON (or missing keys)
191 throw InvalidJSON("JSON is invalid (missing keys or invalid data types)");
192 }
193}
194
195// Load Json::Value into this object
196void Distortion::SetJsonValue(const Json::Value root) {
197
198 // Set parent data
200
201 // Set data from Json (if key is found)
202 if (!root["distortion_type"].isNull())
203 distortion_type = (DistortionType)root["distortion_type"].asInt();
204
205 if (!root["input_gain"].isNull())
206 input_gain.SetJsonValue(root["input_gain"]);
207
208 if (!root["output_gain"].isNull())
209 output_gain.SetJsonValue(root["output_gain"]);
210
211 if (!root["tone"].isNull())
212 tone.SetJsonValue(root["tone"]);
213}
214
215// Get all properties for a specific frame
216std::string Distortion::PropertiesJSON(int64_t requested_frame) const {
217
218 // Generate JSON properties list
219 Json::Value root = BasePropertiesJSON(requested_frame);
220
221 // Keyframes
222 root["distortion_type"] = add_property_json("Distortion Type", distortion_type, "int", "", NULL, 0, 3, false, requested_frame);
223 root["input_gain"] = add_property_json("Input Gain (dB)", input_gain.GetValue(requested_frame), "int", "", &input_gain, -24, 24, false, requested_frame);
224 root["output_gain"] = add_property_json("Output Gain (dB)", output_gain.GetValue(requested_frame), "int", "", &output_gain, -24, 24, false, requested_frame);
225 root["tone"] = add_property_json("Tone (dB)", tone.GetValue(requested_frame), "int", "", &tone, -24, 24, false, requested_frame);
226
227 // Add distortion_type choices (dropdown style)
228 root["distortion_type"]["choices"].append(add_property_choice_json("Hard Clipping", HARD_CLIPPING, distortion_type));
229 root["distortion_type"]["choices"].append(add_property_choice_json("Soft Clipping", SOFT_CLIPPING, distortion_type));
230 root["distortion_type"]["choices"].append(add_property_choice_json("Exponential", EXPONENTIAL, distortion_type));
231 root["distortion_type"]["choices"].append(add_property_choice_json("Full Wave Rectifier", FULL_WAVE_RECTIFIER, distortion_type));
232 root["distortion_type"]["choices"].append(add_property_choice_json("Half Wave Rectifier", HALF_WAVE_RECTIFIER, distortion_type));
233
234 // Return formatted string
235 return root.toStyledString();
236}
Header file for Distortion audio effect class.
Header file for all Exception classes.
Json::Value add_property_choice_json(std::string name, int value, int selected_value) const
Generate JSON choice for a property (dropdown properties)
Definition ClipBase.cpp:132
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
void updateCoefficients(const double discrete_frequency, const double gain)
This class adds a distortion into the audio.
Definition Distortion.h:38
openshot::DistortionType distortion_type
Definition Distortion.h:44
std::string PropertiesJSON(int64_t requested_frame) const override
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 Distortion.h:56
juce::OwnedArray< Filter > filters
Definition Distortion.h:76
void updateFilters(int64_t frame_number)
Json::Value JsonValue() const override
Generate Json::Value for this object.
void SetJson(const std::string value) override
Load JSON string into this object.
void SetJsonValue(const Json::Value root) override
Load Json::Value into this object.
Distortion()
Default constructor.
std::string Json() const override
Generate JSON string of this object.
virtual Json::Value JsonValue() const
Generate Json::Value for this object.
Json::Value BasePropertiesJSON(int64_t requested_frame) const
Generate JSON object of base properties (recommended to be used by all effects)
virtual void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
EffectInfoStruct info
Information about the current effect.
Definition EffectBase.h:69
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
DistortionType
This enumeration determines the distortion type of Distortion Effect.
Definition Enums.h:70
@ HALF_WAVE_RECTIFIER
Definition Enums.h:75
@ FULL_WAVE_RECTIFIER
Definition Enums.h:74
@ EXPONENTIAL
Definition Enums.h:73
@ SOFT_CLIPPING
Definition Enums.h:72
@ HARD_CLIPPING
Definition Enums.h:71
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