Skip to content

Commit

Permalink
split effect from instrument
Browse files Browse the repository at this point in the history
fixed #129
  • Loading branch information
anokta committed May 24, 2024
1 parent 1663a36 commit 86caa68
Show file tree
Hide file tree
Showing 24 changed files with 330 additions and 659 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ instrument.SetNoteOn(a3_pitch, /*intensity=*/0.25);
// Check if the instrument note pitch is on.
const bool is_note_on = instrument.IsNoteOn(a3_pitch); // will return true.

// Add a low-pass effect to the instrument.
auto effect = instrument.CreateEffect<barely::LowPassEffect>();
// Create a low-pass effect.
auto effect = musician.CreateEffect<barely::LowPassEffect>(kFrameRate);

// Set the effect cutoff frequency to 1kHz.
effect.SetControl(barely::LowPassEffect::Control::kCutoffFrequency, /*value=*/1000.0);
Expand All @@ -82,6 +82,9 @@ const int frame_count = 1024;
std::vector<double> output_samples(channel_count * frame_count, 0.0);
instrument.Process(output_samples.data(), channel_count, frame_count, timestamp);

// Process the instrument output with the effect.
effect.Process(output_samples.data(), channel_count, frame_count, timestamp);

// Create a performer.
auto performer = musician.CreatePerformer();

Expand Down
63 changes: 26 additions & 37 deletions barelymusician/barelymusician.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,17 @@ using ::barely::internal::Task;

// Effect.
struct BarelyEffect : public Effect {
// Constructs `BarelyEffect` with `definition`, `instrument`, and `process_order`.
BarelyEffect(const Observable<Instrument>& instrument, BarelyEffectDefinition definition,
int process_order) noexcept
: Effect(definition, instrument.GetFrameRate(), process_order),
instrument_(instrument.Observe()) {
instrument_->AddEffect(*this);
// Constructs `BarelyEffect` with `musician`, `definition`, and `frame_rate`.
BarelyEffect(const Observable<Musician>& musician, BarelyEffectDefinition definition,
int frame_rate) noexcept
: Effect(definition, frame_rate, musician.GetTimestamp()), musician_(musician.Observe()) {
musician_->AddEffect(*this);
}

// Destroys `BarelyEffect`.
~BarelyEffect() noexcept {
if (instrument_) {
instrument_->RemoveEffect(*this);
if (musician_) {
musician_->RemoveEffect(*this);
}
}

Expand All @@ -41,12 +40,9 @@ struct BarelyEffect : public Effect {
BarelyEffect(BarelyEffect&& other) noexcept = delete;
BarelyEffect& operator=(BarelyEffect&& other) noexcept = delete;

// Returns the instrument.
[[nodiscard]] Instrument* instrument() const noexcept { return instrument_.get(); }

private:
// Internal instrument.
Observer<Instrument> instrument_;
// Internal musician.
Observer<Musician> musician_;
};

// Instrument.
Expand Down Expand Up @@ -149,11 +145,11 @@ struct BarelyTask : public Task {
Observer<Performer> performer_;
};

bool BarelyEffect_Create(BarelyInstrumentHandle instrument, BarelyEffectDefinition definition,
int32_t process_order, BarelyEffectHandle* out_effect) {
if (!instrument || !out_effect) return false;
bool BarelyEffect_Create(BarelyMusicianHandle musician, BarelyEffectDefinition definition,
int32_t frame_rate, BarelyEffectHandle* out_effect) {
if (!musician || !out_effect) return false;

*out_effect = new BarelyEffect(*instrument, definition, process_order);
*out_effect = new BarelyEffect(*musician, definition, frame_rate);
return true;
}

Expand Down Expand Up @@ -187,31 +183,31 @@ bool BarelyEffect_GetControlDefinition(BarelyEffectHandle effect, int32_t id,
return false;
}

bool BarelyEffect_GetProcessOrder(BarelyEffectHandle effect, int32_t* out_process_order) {
bool BarelyEffect_Process(BarelyEffectHandle effect, double* output_samples,
int32_t output_channel_count, int32_t output_frame_count,
double timestamp) {
if (!effect) return false;
if (!out_process_order) return false;

*out_process_order = effect->GetProcessOrder();
return true;
return effect->Process(output_samples, output_channel_count, output_frame_count, timestamp);
}

bool BarelyEffect_ResetAllControls(BarelyEffectHandle effect) {
if (!effect || !effect->instrument()) return false;
if (!effect) return false;

effect->instrument()->ResetAllEffectControls(*effect);
effect->ResetAllControls();
return true;
}

bool BarelyEffect_ResetControl(BarelyEffectHandle effect, int32_t id) {
if (!effect || !effect->instrument()) return false;
if (!effect) return false;

return effect->instrument()->ResetEffectControl(*effect, id);
return effect->ResetControl(id);
}

bool BarelyEffect_SetControl(BarelyEffectHandle effect, int32_t id, double value) {
if (!effect || !effect->instrument()) return false;
if (!effect) return false;

return effect->instrument()->SetEffectControl(*effect, id, value);
return effect->SetControl(id, value);
}

bool BarelyEffect_SetControlEvent(BarelyEffectHandle effect,
Expand All @@ -223,17 +219,10 @@ bool BarelyEffect_SetControlEvent(BarelyEffectHandle effect,
}

bool BarelyEffect_SetData(BarelyEffectHandle effect, const void* data, int32_t size) {
if (!effect || !effect->instrument()) return false;

effect->instrument()->SetEffectData(
*effect, {static_cast<const std::byte*>(data), static_cast<const std::byte*>(data) + size});
return true;
}

bool BarelyEffect_SetProcessOrder(BarelyEffectHandle effect, int32_t process_order) {
if (!effect || !effect->instrument()) return false;
if (!effect) return false;

effect->instrument()->SetEffectProcessOrder(*effect, process_order);
effect->SetData(
{static_cast<const std::byte*>(data), static_cast<const std::byte*>(data) + size});
return true;
}

Expand Down
146 changes: 80 additions & 66 deletions barelymusician/barelymusician.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,8 @@
/// - Instrument:
///
/// @code{.cpp}
/// #include "barelymusician/instruments/low_pass_effect.h"
/// #include "barelymusician/instruments/synth_instrument.h"
///
/// // Create.
/// auto instrument = musician.CreateInstrument<barely::SynthInstrument>(/*frame_rate=*/48000);
///
/// // Set a note on.
/// //
/// // Pitch values are normalized, where each `1.0` shifts one octave, and `0.0` represents the
Expand Down Expand Up @@ -72,6 +68,21 @@
/// timestamp);
/// @endcode
///
/// - Effect:
///
/// @code{.cpp}
/// #include "barelymusician/instruments/low_pass_effect.h"
///
/// // Create.
/// auto effect = musician.CreateEffect<barely::LowPassEffect>(/*frame_rate=*/48000);
///
/// // Set a control value.
/// effect.SetControl(barely::LowPassEffect::Control::kCutoffFrequency, /*value=*/1000.0);
///
/// // Process.
/// effect.Process(output_samples.data(), output_channel_count, output_frame_count, timestamp);
/// @endcode
///
/// - Performer:
///
/// @code{.cpp}
Expand Down Expand Up @@ -125,7 +136,6 @@
/// - Instrument:
///
/// @code{.cpp}
/// #include "barelymusician/effects/low_pass_effect.h"
/// #include "barelymusician/instruments/synth_instrument.h"
///
/// // Create.
Expand All @@ -147,14 +157,6 @@
/// // Set a control value.
/// BarelyInstrument_SetControl(instrument, /*id=*/0, /*value=*/0.5);
///
/// // Create a low-pass effect.
/// BarelyEffectHandle effect;
/// BarelyEffect_Create(instrument, BarelyLowPassEffect_GetDefinition(), /*process_order=*/0,
/// &effect);
///
/// // Set the low-pass cutoff frequency to 1kHz.
/// BarelyEffect_SetControl(effect, /*id=*/0, /*value=*/1000.0);
///
/// // Process.
/// //
/// // Instruments expect raw PCM audio buffers to be processed with a synchronous call.
Expand All @@ -167,13 +169,31 @@
/// BarelyInstrument_Process(instrument, output_samples, output_channel_count, output_frame_count,
/// timestamp);
///
/// // Destroy the effect.
/// BarelyEffect_Destroy(effect);
///
/// // Destroy.
/// BarelyInstrument_Destroy(instrument);
/// @endcode
///
/// - Effect:
///
/// @code{.cpp}
/// #include "barelymusician/effects/low_pass_effect.h"
///
/// // Create.
/// BarelyEffectHandle effect;
/// BarelyEffect_Create(musician, BarelyLowPassEffect_GetDefinition(), /*frame_rate=*/48000,
/// &effect);
///
/// // Set a control value.
/// BarelyEffect_SetControl(effect, /*id=*/0, /*value=*/1000.0);
///
/// // Process.
/// BarelyEffect_Process(effect, output_samples, output_channel_count, output_frame_count,
/// timestamp);
///
/// // Destroy the effect.
/// BarelyEffect_Destroy(effect);
/// @endcode
///
/// - Performer:
///
/// @code{.cpp}
Expand Down Expand Up @@ -579,13 +599,13 @@ typedef struct BarelyTask* BarelyTaskHandle;

/// Creates a new effect.
///
/// @param instrument Instrument handle.
/// @param musician Musician handle.
/// @param definition Effect definition.
/// @param process_order Effect process order.
/// @param frame_rate Frame rate in hertz.
/// @param out_effect Output effect handle.
/// @return True if successful, false otherwise.
BARELY_EXPORT bool BarelyEffect_Create(BarelyInstrumentHandle instrument,
BarelyEffectDefinition definition, int32_t process_order,
BARELY_EXPORT bool BarelyEffect_Create(BarelyMusicianHandle musician,
BarelyEffectDefinition definition, int32_t frame_rate,
BarelyEffectHandle* out_effect);

/// Destroys an effect.
Expand All @@ -612,13 +632,18 @@ BARELY_EXPORT bool BarelyEffect_GetControl(BarelyEffectHandle effect, int32_t id
BARELY_EXPORT bool BarelyEffect_GetControlDefinition(BarelyEffectHandle effect, int32_t id,
BarelyControlDefinition* out_value);

/// Gets the process order of an effect.
/// Processes instrument output samples at timestamp.
/// @note This function is *not* thread-safe during a corresponding `BarelyEffect_Destroy` call.
///
/// @param effect Effect handle.
/// @param out_process_order Output process order.
/// @param output_samples Array of interleaved output samples.
/// @param output_channel_count Number of output channels.
/// @param output_frame_count Number of output frames.
/// @param timestamp Timestamp in seconds.
/// @return True if successful, false otherwise.
BARELY_EXPORT bool BarelyEffect_GetProcessOrder(BarelyEffectHandle effect,
int32_t* out_process_order);
BARELY_EXPORT bool BarelyEffect_Process(BarelyEffectHandle instrument, double* output_samples,
int32_t output_channel_count, int32_t output_frame_count,
double timestamp);

/// Resets all effect control values.
///
Expand Down Expand Up @@ -659,13 +684,6 @@ BARELY_EXPORT bool BarelyEffect_SetControlEvent(BarelyEffectHandle effect,
/// @return True if successful, false otherwise.
BARELY_EXPORT bool BarelyEffect_SetData(BarelyEffectHandle effect, const void* data, int32_t size);

/// Sets the process order of an effect.
///
/// @param effect Effect handle.
/// @param process_order Process order.
/// @return True if successful, false otherwise.
BARELY_EXPORT bool BarelyEffect_SetProcessOrder(BarelyEffectHandle effect, int32_t process_order);

/// Creates a new instrument.
///
/// @param musician Musician handle.
Expand Down Expand Up @@ -1690,14 +1708,17 @@ class Effect : protected Wrapper<BarelyEffectHandle> {
return definition;
}

/// Returns the process order.
/// Processes output samples at timestamp.
///
/// @return Process order.
[[nodiscard]] int GetProcessOrder() const noexcept {
int32_t process_order = 0;
[[maybe_unused]] const bool success = BarelyEffect_GetProcessOrder(Get(), &process_order);
/// @param output_samples Interleaved array of output samples.
/// @param output_channel_count Number of output channels.
/// @param output_frame_count Number of output frames.
/// @param timestamp Timestamp in seconds.
void Process(double* output_samples, int output_channel_count, int output_frame_count,
double timestamp) noexcept {
[[maybe_unused]] const bool success = BarelyEffect_Process(
Get(), output_samples, output_channel_count, output_frame_count, timestamp);
assert(success);
return static_cast<int>(process_order);
}

/// Resets all control values.
Expand Down Expand Up @@ -1774,14 +1795,6 @@ class Effect : protected Wrapper<BarelyEffectHandle> {
[[maybe_unused]] const bool success = BarelyEffect_SetData(Get(), data, size);
assert(success);
}

/// Sets the process order.
///
/// @param process_order Process order.
void SetProcessOrder(int process_order) noexcept {
[[maybe_unused]] const bool success = BarelyEffect_SetProcessOrder(Get(), process_order);
assert(success);
}
};

/// Class that wraps an instrument.
Expand Down Expand Up @@ -1820,27 +1833,6 @@ class Instrument : protected Wrapper<BarelyInstrumentHandle> {
return *this;
}

/// Creates a new effect of type.
///
/// @return Effect.
template <class EffectType>
[[nodiscard]] Effect CreateEffect() noexcept {
return CreateEffect(EffectType::GetDefinition());
}

/// Creates a new effect.
///
/// @param definition Effect definition.
/// @param process_order Effect process order.
/// @return Effect.
[[nodiscard]] Effect CreateEffect(EffectDefinition definition, int process_order = 0) noexcept {
BarelyEffectHandle effect;
[[maybe_unused]] const bool success =
BarelyEffect_Create(Get(), definition, process_order, &effect);
assert(success);
return Effect(effect);
}

/// Returns a control value.
///
/// @param id Control identifier.
Expand Down Expand Up @@ -2426,6 +2418,28 @@ class Musician : protected Wrapper<BarelyMusicianHandle> {
return ComponentType(*this, args...);
}

/// Creates a new effect of type.
///
/// @param frame_rate Frame rate in hertz.
/// @return Effect.
template <class EffectType>
[[nodiscard]] Effect CreateEffect(int frame_rate) noexcept {
return CreateEffect(EffectType::GetDefinition(), frame_rate);
}

/// Creates a new effect.
///
/// @param definition Effect definition.
/// @param frame_rate Frame rate in hertz.
/// @return Effect.
[[nodiscard]] Effect CreateEffect(EffectDefinition definition, int frame_rate) noexcept {
BarelyEffectHandle effect;
[[maybe_unused]] const bool success =
BarelyEffect_Create(Get(), definition, frame_rate, &effect);
assert(success);
return Effect(effect);
}

/// Creates a new instrument of type.
///
/// @param frame_rate Frame rate in hertz.
Expand Down
Loading

0 comments on commit 86caa68

Please sign in to comment.