Skip to content

Commit

Permalink
implement simple lfo effect
Browse files Browse the repository at this point in the history
+ might need to support some sort of note start/reset in effect definition
  • Loading branch information
anokta committed Feb 18, 2024
1 parent 3f39d50 commit 9d938c0
Show file tree
Hide file tree
Showing 13 changed files with 247 additions and 9 deletions.
13 changes: 13 additions & 0 deletions barelymusician/effects/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ cc_library(
alwayslink = True,
)

cc_library(
name = "lfo_effect",
srcs = ["lfo_effect.cpp"],
hdrs = ["lfo_effect.h"],
defines = ["BARELYMUSICIAN_EXPORTS"],
deps = [
":custom_effect",
"//barelymusician",
"//barelymusician/dsp:oscillator",
],
alwayslink = True,
)

cc_library(
name = "low_pass_effect",
srcs = ["low_pass_effect.cpp"],
Expand Down
17 changes: 17 additions & 0 deletions barelymusician/effects/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@ target_link_libraries(
barely_one_pole_filter
)

add_library(
barely_lfo_effect
lfo_effect.cpp
lfo_effect.h
)
target_compile_definitions(
barely_lfo_effect
PUBLIC BARELYMUSICIAN_EXPORTS
)
target_link_libraries(
barely_lfo_effect
barely_custom_effect
barelymusician
barely_oscillator
)


add_library(
barely_low_pass_effect
low_pass_effect.cpp
Expand Down
8 changes: 4 additions & 4 deletions barelymusician/effects/high_pass_effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ void HighPassEffect::Process(double* output_samples, int output_channel_count,
int output_frame_count) noexcept {
assert(output_channel_count <= kMaxChannelCount);
for (int frame = 0; frame < output_frame_count; ++frame) {
for (int channel = 0; channel < output_channel_count; ++channel) {
auto& sample = output_samples[output_channel_count * frame + channel];
sample = filters_[channel].Next(sample);
}
if (cutoff_frequency_.second != 0.0) {
cutoff_frequency_.first += cutoff_frequency_.second;
for (auto& filter : filters_) {
filter.SetCoefficient(GetFilterCoefficient(frame_rate_, cutoff_frequency_.first));
}
}
for (int channel = 0; channel < output_channel_count; ++channel) {
auto& sample = output_samples[output_channel_count * frame + channel];
sample = filters_[channel].Next(sample);
}
}
}

Expand Down
75 changes: 75 additions & 0 deletions barelymusician/effects/lfo_effect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include "barelymusician/effects/lfo_effect.h"

#include <array>
#include <cassert>

#include "barelymusician/barelymusician.h"
#include "barelymusician/dsp/oscillator.h"
#include "barelymusician/effects/custom_effect.h"

BarelyEffectDefinition BarelyLfoEffect_GetDefinition() {
return barely::LfoEffect::GetDefinition();
}

namespace barely {

EffectDefinition LfoEffect::GetDefinition() noexcept {
static const std::array<ControlDefinition, static_cast<int>(Control::kCount)>
control_definitions = {
// Oscillator type.
ControlDefinition{static_cast<double>(OscillatorType::kSine), 0.0,
static_cast<double>(OscillatorType::kNoise)},
// Oscillator frequency.
ControlDefinition{1.0, 0.0, 32.0},
// Intensity.
ControlDefinition{1.0, 0.0, 1.0},
};
return CustomEffect::GetDefinition<LfoEffect>(control_definitions);
}

LfoEffect::LfoEffect(int frame_rate) noexcept : lfo_(frame_rate) { assert(frame_rate > 0); }

void LfoEffect::Process(double* output_samples, int output_channel_count,
int output_frame_count) noexcept {
for (int frame = 0; frame < output_frame_count; ++frame) {
const double gain = intensity_.first * lfo_.Next();
for (int channel = 0; channel < output_channel_count; ++channel) {
auto& sample = output_samples[output_channel_count * frame + channel];
sample *= gain;
}
if (frequency_.second != 0.0) {
frequency_.first += frequency_.second;
lfo_.SetFrequency(frequency_.first);
}
if (intensity_.second != 0.0) {
intensity_.first += intensity_.second;
}
}
}

void LfoEffect::SetControl(int index, double value, double slope_per_frame) noexcept {
switch (static_cast<Control>(index)) {
case Control::kOscillatorType:
lfo_.SetType(static_cast<OscillatorType>(static_cast<int>(value)));
break;
case Control::kOscillatorFrequency:
if (value != frequency_.first) {
frequency_.first = value;
lfo_.SetFrequency(value);
}
frequency_.second = slope_per_frame;
break;
case Control::kIntensity:
if (value != intensity_.first) {
intensity_.first = value;
lfo_.SetFrequency(value);
}
intensity_.second = slope_per_frame;
break;
default:
assert(false);
break;
}
}

} // namespace barely
72 changes: 72 additions & 0 deletions barelymusician/effects/lfo_effect.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#ifndef BARELYMUSICIAN_EFFECTS_LFO_EFFECT_H_
#define BARELYMUSICIAN_EFFECTS_LFO_EFFECT_H_

// NOLINTBEGIN
#include "barelymusician/barelymusician.h"

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

/// Returns the low-frequency oscillator effect definition.
///
/// @return Effect definition.
BARELY_EXPORT BarelyEffectDefinition BarelyLfoEffect_GetDefinition();

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
// NOLINTEND

#ifdef __cplusplus

#include "barelymusician/dsp/oscillator.h"
#include "barelymusician/effects/custom_effect.h"

namespace barely {

/// Simple amplitude low-frequency oscillator effect.
class LfoEffect : public CustomEffect {
public:
/// Control enum.
enum class Control : int {
/// Oscillator type.
kOscillatorType = 0,
/// Oscillator frequency.
kOscillatorFrequency = 1,
/// Intensity.
kIntensity = 2,
/// Number of controls.
kCount,
};

/// Returns the effect definition.
///
/// @return Effect definition.
static EffectDefinition GetDefinition() noexcept;

protected:
/// Constructs new `LfoEffect`.
explicit LfoEffect(int frame_rate) noexcept;

/// Implements `CustomEffect`.
void Process(double* output_samples, int output_channel_count,
int output_frame_count) noexcept final;
void SetControl(int index, double value, double slope_per_frame) noexcept final;
void SetData(const void* /*data*/, int /*size*/) noexcept final {}

private:
// Low-frequency oscillator.
Oscillator lfo_;

// Frequency-slope pair.
std::pair<double, double> frequency_ = {220.0, 0.0};

// Intensity-slope pair.
std::pair<double, double> intensity_ = {1.0, 0.0};
};

} // namespace barely
#endif // __cplusplus

#endif // BARELYMUSICIAN_EFFECTS_LFO_EFFECT_H_
8 changes: 4 additions & 4 deletions barelymusician/effects/low_pass_effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ void LowPassEffect::Process(double* output_samples, int output_channel_count,
int output_frame_count) noexcept {
assert(output_channel_count <= kMaxChannelCount);
for (int frame = 0; frame < output_frame_count; ++frame) {
for (int channel = 0; channel < output_channel_count; ++channel) {
auto& sample = output_samples[output_channel_count * frame + channel];
sample = filters_[channel].Next(sample);
}
if (cutoff_frequency_.second != 0.0) {
cutoff_frequency_.first += cutoff_frequency_.second;
for (auto& filter : filters_) {
filter.SetCoefficient(GetFilterCoefficient(frame_rate_, cutoff_frequency_.first));
}
}
for (int channel = 0; channel < output_channel_count; ++channel) {
auto& sample = output_samples[output_channel_count * frame + channel];
sample = filters_[channel].Next(sample);
}
}
}

Expand Down
40 changes: 40 additions & 0 deletions platforms/unity/Assets/BarelyMusician/Scripts/Effects/LfoEffect.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using UnityEngine;

namespace Barely {
/// A representation of a simple amplitude low-frequency oscillator effect.
public class LfoEffect : Effect {
/// Type.
public OscillatorType Type {
get { return (OscillatorType)GetControl(0); }
set { SetControl(0, (double)value, 0.0); }
}

/// Frequency.
public double Frequency {
get { return GetControl(1); }
set { SetControl(1, value, 0.0); }
}

/// Intensity.
public double Intensity {
get { return GetControl(2); }
set { SetControl(2, value, 0.0); }
}

/// Sets the oscillator frequency with a slope.
///
/// @param frequency Oscillator frequency.
/// @param slopePerBeat Slope in value change per beat.
public void SetFrequency(double frequency, double slopePerBeat) {
SetControl(0, frequency, slopePerBeat);
}

/// Sets the intensity with a slope.
///
/// @param intensity Intensity.
/// @param slopePerBeat Slope in value change per beat.
public void SetIntensity(double intensity, double slopePerBeat) {
SetControl(0, intensity, slopePerBeat);
}
}
} // namespace Barely

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions platforms/unity/Assets/BarelyMusician/Scripts/Musician.cs
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@ public static void Effect_Create(Instrument instrument, Effect effect,
case HighPassEffect highPass:
definition = BarelyHighPassEffect_GetDefinition();
break;
case LfoEffect lfoEffect:
definition = BarelyLfoEffect_GetDefinition();
break;
case LowPassEffect lowPass:
definition = BarelyLowPassEffect_GetDefinition();
break;
Expand Down Expand Up @@ -1875,6 +1878,9 @@ private static extern bool BarelyRepeater_Create(IntPtr musician, Int32 processO
[DllImport(pluginName, EntryPoint = "BarelyHighPassEffect_GetDefinition")]
private static extern EffectDefinition BarelyHighPassEffect_GetDefinition();

[DllImport(pluginName, EntryPoint = "BarelyLfoEffect_GetDefinition")]
private static extern EffectDefinition BarelyLfoEffect_GetDefinition();

[DllImport(pluginName, EntryPoint = "BarelyLowPassEffect_GetDefinition")]
private static extern EffectDefinition BarelyLowPassEffect_GetDefinition();

Expand Down
3 changes: 2 additions & 1 deletion platforms/unity/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ BARELYMUSICIAN_DEPS = [
"//barelymusician",
"//barelymusician/components:arpeggiator",
"//barelymusician/components:repeater",
"//barelymusician/effects:low_pass_effect",
"//barelymusician/effects:high_pass_effect",
"//barelymusician/effects:lfo_effect",
"//barelymusician/effects:low_pass_effect",
"//barelymusician/instruments:percussion_instrument",
"//barelymusician/instruments:sampler_instrument",
"//barelymusician/instruments:synth_instrument",
Expand Down
1 change: 1 addition & 0 deletions platforms/unity/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ target_link_libraries(
barelymusician
barely_arpeggiator
barely_high_pass_effect
barely_lfo_effect
barely_low_pass_effect
barely_percussion_instrument
barely_sampler_instrument
Expand Down
1 change: 1 addition & 0 deletions platforms/unity/unity_android.lds
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ VERS_1.0 {
BarelyRepeater_Stop;

BarelyHighPassEffect_GetDefinition;
BarelyLfoEffect_GetDefinition;
BarelyLowPassEffect_GetDefinition;

BarelyPercussionInstrument_GetDefinition;
Expand Down
1 change: 1 addition & 0 deletions platforms/unity/unity_windows.def
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ EXPORTS
BarelyRepeater_Stop

BarelyHighPassEffect_GetDefinition
BarelyLfoEffect_GetDefinition
BarelyLowPassEffect_GetDefinition

BarelyPercussionInstrument_GetDefinition
Expand Down

0 comments on commit 9d938c0

Please sign in to comment.