Skip to content

Commit

Permalink
Merge pull request #54 from magnetophon/histogram
Browse files Browse the repository at this point in the history
Histogram
  • Loading branch information
exa04 authored May 31, 2024
2 parents f6026be + 90e3357 commit 83568f0
Show file tree
Hide file tree
Showing 12 changed files with 635 additions and 1 deletion.
9 changes: 9 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description = "Composable views and associated data structures for nih-plug UIs
resolver = "2"
members = [
"xtask",
"examples/visualizers", "examples/peak_graph",
"examples/visualizers", "examples/peak_graph", "examples/histogram",
]

[lib]
Expand Down
22 changes: 22 additions & 0 deletions examples/histogram/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "histogram"
version = "0.1.0"
edition = "2021"
description = "A histogram built using Cyma"

[lib]
crate-type = ["cdylib", "lib"]

[dependencies]
nih_plug = { git = "https://github.com/robbert-vdh/nih-plug.git", features = ["assert_process_allocs", "standalone"] }
cyma = { path = "../../" }
nih_plug_vizia = { git = "https://github.com/robbert-vdh/nih-plug.git" }

[profile.release]
lto = "thin"
strip = "symbols"

[profile.profiling]
inherits = "release"
debug = true
strip = "none"
15 changes: 15 additions & 0 deletions examples/histogram/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Peak Graph

> [!NOTE]
> This code is taken from the *Composing a Peak Graph* chapter of the Cyma Book.
![A peak graph visualizer with a grid backdrop and a unit ruler to the side.](doc/peak_graph.png)

A peak analyzer plugin.

This example plug-in uses a peak buffer that stores incoming audio as peaks that
decay in amplitude. The buffer is behind an `Arc<Mutex>`. By cloning the Arc, a
reference is sent to the editor. The editor uses the buffer to draw a `PeakGraph`.

Behind it is a grid, and to the side of it is a unit ruler. These views are composed
using VIZIA's *Stack* views.
Binary file added examples/histogram/doc/peak_graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 71 additions & 0 deletions examples/histogram/src/editor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use cyma::prelude::*;
use cyma::{
utils::HistogramBuffer,
visualizers::{Grid, Histogram, UnitRuler},
};
use nih_plug::editor::Editor;
use nih_plug_vizia::{assets, create_vizia_editor, vizia::prelude::*, ViziaState, ViziaTheming};
use std::sync::{Arc, Mutex};

#[derive(Lens, Clone)]
pub(crate) struct Data {
histogram_buffer: Arc<Mutex<HistogramBuffer>>,
}

impl Data {
pub(crate) fn new(histogram_buffer: Arc<Mutex<HistogramBuffer>>) -> Self {
Self { histogram_buffer }
}
}

impl Model for Data {}

pub(crate) fn default_state() -> Arc<ViziaState> {
ViziaState::new(|| (800, 500))
}

pub(crate) fn create(editor_data: Data, editor_state: Arc<ViziaState>) -> Option<Box<dyn Editor>> {
create_vizia_editor(editor_state, ViziaTheming::default(), move |cx, _| {
assets::register_noto_sans_light(cx);
editor_data.clone().build(cx);

HStack::new(cx, |cx| {
ZStack::new(cx, |cx| {
Grid::new(
cx,
ValueScaling::Linear,
(-32., 8.),
vec![6.0, 0.0, -6.0, -12.0, -18.0, -24.0, -30.0],
Orientation::Horizontal,
)
.color(Color::rgb(60, 60, 60));

Histogram::new(cx, Data::histogram_buffer, (-32.0, 8.0))
.color(Color::rgba(255, 255, 255, 160))
.background_color(Color::rgba(255, 255, 255, 60));
})
.background_color(Color::rgb(16, 16, 16));

UnitRuler::new(
cx,
(-32.0, 8.0),
ValueScaling::Linear,
vec![
(6.0, "6db"),
(0.0, "0db"),
(-6.0, "-6db"),
(-12.0, "-12db"),
(-18.0, "-18db"),
(-24.0, "-24db"),
(-30.0, "-30db"),
],
Orientation::Vertical,
)
.font_size(12.)
.color(Color::rgb(160, 160, 160))
.width(Pixels(48.));
})
.col_between(Pixels(8.))
.background_color(Color::rgb(0, 0, 0));
})
}
123 changes: 123 additions & 0 deletions examples/histogram/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
use cyma::prelude::*;
use cyma::utils::HistogramBuffer;
use nih_plug::prelude::*;
use nih_plug_vizia::ViziaState;
use std::sync::{Arc, Mutex};

mod editor;

pub struct HistogramPlugin {
params: Arc<DemoParams>,
histogram_buffer: Arc<Mutex<HistogramBuffer>>,
}

#[derive(Params)]
struct DemoParams {
#[persist = "editor-state"]
editor_state: Arc<ViziaState>,
}

impl Default for HistogramPlugin {
fn default() -> Self {
Self {
params: Arc::new(DemoParams::default()),
histogram_buffer: Arc::new(Mutex::new(HistogramBuffer::new(256, 1.0))),
}
}
}

impl Default for DemoParams {
fn default() -> Self {
Self {
editor_state: editor::default_state(),
}
}
}

impl Plugin for HistogramPlugin {
const NAME: &'static str = "CymaHistogram";
const VENDOR: &'static str = "223230";
const URL: &'static str = env!("CARGO_PKG_HOMEPAGE");
const EMAIL: &'static str = "[email protected]";
const VERSION: &'static str = env!("CARGO_PKG_VERSION");

const AUDIO_IO_LAYOUTS: &'static [AudioIOLayout] = &[AudioIOLayout {
main_input_channels: NonZeroU32::new(2),
main_output_channels: NonZeroU32::new(2),

aux_input_ports: &[],
aux_output_ports: &[],

names: PortNames::const_default(),
}];

const MIDI_INPUT: MidiConfig = MidiConfig::None;
const MIDI_OUTPUT: MidiConfig = MidiConfig::None;

const SAMPLE_ACCURATE_AUTOMATION: bool = true;

type SysExMessage = ();
type BackgroundTask = ();

fn params(&self) -> Arc<dyn Params> {
self.params.clone()
}

fn editor(&mut self, _async_executor: AsyncExecutor<Self>) -> Option<Box<dyn Editor>> {
editor::create(
editor::Data::new(self.histogram_buffer.clone()),
self.params.editor_state.clone(),
)
}

fn initialize(
&mut self,
_audio_io_layout: &AudioIOLayout,
buffer_config: &BufferConfig,
_context: &mut impl InitContext<Self>,
) -> bool {
match self.histogram_buffer.lock() {
Ok(mut buffer) => {
buffer.set_sample_rate(buffer_config.sample_rate);
}
Err(_) => return false,
}

true
}

fn process(
&mut self,
buffer: &mut nih_plug::buffer::Buffer,
_: &mut AuxiliaryBuffers,
_: &mut impl ProcessContext<Self>,
) -> ProcessStatus {
// Append to the visualizers' respective buffers, only if the editor is currently open.
if self.params.editor_state.is_open() {
self.histogram_buffer
.lock()
.unwrap()
.enqueue_buffer(buffer, None);
}
ProcessStatus::Normal
}
}

impl ClapPlugin for HistogramPlugin {
const CLAP_ID: &'static str = "org.cyma.histogram";
const CLAP_DESCRIPTION: Option<&'static str> = Some("A histogram built using Cyma");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;

const CLAP_FEATURES: &'static [ClapFeature] =
&[ClapFeature::AudioEffect, ClapFeature::Analyzer];
}

impl Vst3Plugin for HistogramPlugin {
const VST3_CLASS_ID: [u8; 16] = *b"CYMA000HISTOGRAM";

const VST3_SUBCATEGORIES: &'static [Vst3SubCategory] = &[Vst3SubCategory::Analyzer];
}

nih_export_clap!(HistogramPlugin);
nih_export_vst3!(HistogramPlugin);
6 changes: 6 additions & 0 deletions examples/histogram/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use histogram::HistogramPlugin;
use nih_plug::prelude::*;

fn main() {
nih_export_standalone::<HistogramPlugin>();
}
Loading

0 comments on commit 83568f0

Please sign in to comment.