OpenShot Library | libopenshot  0.4.0
Echo.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 "Echo.h"
14 #include "Exceptions.h"
15 #include "Frame.h"
16 
17 using namespace openshot;
18 
19 Echo::Echo() : Echo::Echo(0.1, 0.5, 0.5) { }
20 
21 Echo::Echo(Keyframe echo_time, Keyframe feedback, Keyframe mix) :
22  echo_time(echo_time), feedback(feedback), mix(mix)
23 {
24  // Init effect properties
25  init_effect_details();
26 }
27 
28 // Init effect settings
29 void Echo::init_effect_details()
30 {
33 
35  info.class_name = "Echo";
36  info.name = "Echo";
37  info.description = "Reflection of sound with a delay after the direct sound.";
38  info.has_audio = true;
39  info.has_video = false;
40  initialized = false;
41 }
42 
43 void Echo::setup(std::shared_ptr<openshot::Frame> frame)
44 {
45  if (!initialized)
46  {
47  const float max_echo_time = 5;
48  echo_buffer_samples = (int)(max_echo_time * (float)frame->SampleRate()) + 1;
49 
50  if (echo_buffer_samples < 1)
52 
53  echo_buffer_channels = frame->audio->getNumChannels();
55  echo_buffer.clear();
57  initialized = true;
58  }
59 }
60 
61 // This method is required for all derived classes of EffectBase, and returns a
62 // modified openshot::Frame object
63 std::shared_ptr<openshot::Frame> Echo::GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number)
64 {
65  const float echo_time_value = (float)echo_time.GetValue(frame_number)*(float)frame->SampleRate();
66  const float feedback_value = feedback.GetValue(frame_number);
67  const float mix_value = mix.GetValue(frame_number);
68  int local_write_position;
69 
70  setup(frame);
71 
72  for (int channel = 0; channel < frame->audio->getNumChannels(); channel++)
73  {
74  float *channel_data = frame->audio->getWritePointer(channel);
75  float *echo_data = echo_buffer.getWritePointer(channel);
76  local_write_position = echo_write_position;
77 
78  for (auto sample = 0; sample < frame->audio->getNumSamples(); ++sample)
79  {
80  const float in = (float)(channel_data[sample]);
81  float out = 0.0f;
82 
83  float read_position = fmodf((float)local_write_position - echo_time_value + (float)echo_buffer_samples, echo_buffer_samples);
84  int local_read_position = floorf(read_position);
85 
86  if (local_read_position != local_write_position)
87  {
88  float fraction = read_position - (float)local_read_position;
89  float echoed1 = echo_data[(local_read_position + 0)];
90  float echoed2 = echo_data[(local_read_position + 1) % echo_buffer_samples];
91  out = (float)(echoed1 + fraction * (echoed2 - echoed1));
92  channel_data[sample] = in + mix_value*(out - in);
93  echo_data[local_write_position] = in + out*feedback_value;
94  }
95 
96  if (++local_write_position >= echo_buffer_samples)
97  local_write_position -= echo_buffer_samples;
98  }
99  }
100 
101  echo_write_position = local_write_position;
102 
103  // return the modified frame
104  return frame;
105 }
106 
107 // Generate JSON string of this object
108 std::string Echo::Json() const {
109 
110  // Return formatted string
111  return JsonValue().toStyledString();
112 }
113 
114 // Generate Json::Value for this object
115 Json::Value Echo::JsonValue() const {
116 
117  // Create root json object
118  Json::Value root = EffectBase::JsonValue(); // get parent properties
119  root["type"] = info.class_name;
120  root["echo_time"] = echo_time.JsonValue();
121  root["feedback"] = feedback.JsonValue();
122  root["mix"] = mix.JsonValue();
123 
124  // return JsonValue
125  return root;
126 }
127 
128 // Load JSON string into this object
129 void Echo::SetJson(const std::string value) {
130 
131  // Parse JSON string into JSON objects
132  try
133  {
134  const Json::Value root = openshot::stringToJson(value);
135  // Set all values that match
136  SetJsonValue(root);
137  }
138  catch (const std::exception& e)
139  {
140  // Error parsing JSON (or missing keys)
141  throw InvalidJSON("JSON is invalid (missing keys or invalid data types)");
142  }
143 }
144 
145 // Load Json::Value into this object
146 void Echo::SetJsonValue(const Json::Value root) {
147 
148  // Set parent data
150 
151  // Set data from Json (if key is found)
152  if (!root["echo_time"].isNull())
153  echo_time.SetJsonValue(root["echo_time"]);
154  if (!root["feedback"].isNull())
155  feedback.SetJsonValue(root["feedback"]);
156  if (!root["mix"].isNull())
157  mix.SetJsonValue(root["mix"]);
158 }
159 
160 // Get all properties for a specific frame
161 std::string Echo::PropertiesJSON(int64_t requested_frame) const {
162 
163  // Generate JSON properties list
164  Json::Value root = BasePropertiesJSON(requested_frame);
165 
166  // Keyframes
167  root["echo_time"] = add_property_json("Time", echo_time.GetValue(requested_frame), "float", "", &echo_time, 0, 5, false, requested_frame);
168  root["feedback"] = add_property_json("Feedback", feedback.GetValue(requested_frame), "float", "", &feedback, 0, 1, false, requested_frame);
169  root["mix"] = add_property_json("Mix", mix.GetValue(requested_frame), "float", "", &mix, 0, 1, false, requested_frame);
170 
171  // Return formatted string
172  return root.toStyledString();
173 }
openshot::ClipBase::add_property_json
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
openshot::stringToJson
const Json::Value stringToJson(const std::string value)
Definition: Json.cpp:16
openshot::EffectBase::info
EffectInfoStruct info
Information about the current effect.
Definition: EffectBase.h:69
openshot::Echo::GetFrame
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: Echo.h:58
openshot::Echo::echo_time
Keyframe echo_time
Definition: Echo.h:42
openshot::Echo::feedback
Keyframe feedback
Definition: Echo.h:43
openshot::Echo::mix
Keyframe mix
Definition: Echo.h:44
openshot::Echo::echo_buffer_samples
int echo_buffer_samples
Definition: Echo.h:47
openshot
This namespace is the default namespace for all code in the openshot library.
Definition: Compressor.h:28
openshot::EffectBase::JsonValue
virtual Json::Value JsonValue() const
Generate Json::Value for this object.
Definition: EffectBase.cpp:79
openshot::Keyframe::SetJsonValue
void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
Definition: KeyFrame.cpp:372
openshot::Echo::SetJsonValue
void SetJsonValue(const Json::Value root) override
Load Json::Value into this object.
Definition: Echo.cpp:146
openshot::Echo::setup
void setup(std::shared_ptr< openshot::Frame > frame)
Definition: Echo.cpp:43
openshot::Keyframe::JsonValue
Json::Value JsonValue() const
Generate Json::Value for this object.
Definition: KeyFrame.cpp:339
openshot::Echo::Echo
Echo()
Default constructor.
Definition: Echo.cpp:19
openshot::EffectBase::BasePropertiesJSON
Json::Value BasePropertiesJSON(int64_t requested_frame) const
Generate JSON object of base properties (recommended to be used by all effects)
Definition: EffectBase.cpp:179
openshot::Echo::JsonValue
Json::Value JsonValue() const override
Generate Json::Value for this object.
Definition: Echo.cpp:115
openshot::Keyframe
A Keyframe is a collection of Point instances, which is used to vary a number or property over time.
Definition: KeyFrame.h:53
openshot::InvalidJSON
Exception for invalid JSON.
Definition: Exceptions.h:217
openshot::Echo::SetJson
void SetJson(const std::string value) override
Load JSON string into this object.
Definition: Echo.cpp:129
Echo.h
Header file for Echo audio effect class.
openshot::EffectBase::InitEffectInfo
void InitEffectInfo()
Definition: EffectBase.cpp:24
openshot::EffectInfoStruct::has_audio
bool has_audio
Determines if this effect manipulates the audio of a frame.
Definition: EffectBase.h:41
openshot::Echo::initialized
bool initialized
Definition: Echo.h:50
Frame.h
Header file for Frame class.
openshot::Echo::echo_buffer_channels
int echo_buffer_channels
Definition: Echo.h:48
openshot::EffectInfoStruct::class_name
std::string class_name
The class name of the effect.
Definition: EffectBase.h:36
openshot::EffectInfoStruct::description
std::string description
The description of this effect and what it does.
Definition: EffectBase.h:38
openshot::Echo::Json
std::string Json() const override
Generate JSON string of this object.
Definition: Echo.cpp:108
openshot::EffectInfoStruct::has_video
bool has_video
Determines if this effect manipulates the image of a frame.
Definition: EffectBase.h:40
openshot::EffectInfoStruct::name
std::string name
The name of the effect.
Definition: EffectBase.h:37
openshot::Echo
This class adds a echo into the audio.
Definition: Echo.h:35
openshot::Echo::echo_write_position
int echo_write_position
Definition: Echo.h:49
openshot::Echo::echo_buffer
juce::AudioBuffer< float > echo_buffer
Definition: Echo.h:46
Exceptions.h
Header file for all Exception classes.
openshot::EffectBase::SetJsonValue
virtual void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
Definition: EffectBase.cpp:115
openshot::Keyframe::GetValue
double GetValue(int64_t index) const
Get the value at a specific index.
Definition: KeyFrame.cpp:258
openshot::Echo::PropertiesJSON
std::string PropertiesJSON(int64_t requested_frame) const override
Definition: Echo.cpp:161