#iced #audio #lv2 #vst

iced_audio

Iced GUI库的扩展,为音频应用程序提供了有用的控件

39个版本 (12个重大变更)

0.12.0 2023年8月3日
0.11.0 2023年2月25日
0.10.0 2023年1月31日
0.9.0 2022年12月22日
0.4.0 2020年7月29日

#157 in GUI

Download history 34/week @ 2024-04-22 25/week @ 2024-04-29 16/week @ 2024-05-06 18/week @ 2024-05-13 17/week @ 2024-05-20 10/week @ 2024-05-27 14/week @ 2024-06-03 15/week @ 2024-06-10 26/week @ 2024-06-17 30/week @ 2024-06-24 16/week @ 2024-07-01 10/week @ 2024-07-08 17/week @ 2024-07-15 3/week @ 2024-07-22 72/week @ 2024-07-29 13/week @ 2024-08-05

每月105次下载
用于 6 个crate(2个直接使用)

MIT 协议

410KB
9K SLoC

Iced Audio

Documentation Crates.io License project chat

Iced GUI库的扩展,为VST / LV2插件等音频应用程序提供了有用的控件。

更多截图

实现的控件

输入

  • HSlider - 水平滑块
  • VSlider - 垂直滑块
  • Knob - 经典的旋钮控件。(暂无纹理样式)
  • Ramp - 用于控制两个时间点之间缓动的斜坡
  • XYPad- XY垫,用于同时控制两个参数
  • ModRangeInput - 用于控制参数调制范围的点。为 HSliderVSliderKnob 控件存在添加视觉反馈的样式。

查看路线图以获取计划中的控件列表。

每个参数都可以映射到四个范围之一

  • FloatRange - f32值的线性范围
  • IntRange - i32值的离散范围。这将导致控件在移动时“步进”。
  • LogDBRange - 分贝值的对数范围。围绕0 dB的值将比远离0 dB的值增加得更慢。
  • FreqRange - 频率值的对数范围。10个八度音阶频谱(从20 Hz到20480 Hz)均匀分布。

使用以下方式运行示例

cargo run --package inputs_tour --release
cargo run --package simple --release

安装

在您的 Cargo.toml 中将 iced_audio 添加为依赖项

iced_audio = "0.8"

或者如果您想使用GitHub上的iced版本

iced_audio = { git = "https://github.com/iced-rs/iced_audio", branch = "iced_git" }

Both Iced Audio和Iced发展迅速,mainiced_git分支可能包含重大更改!如果您想了解特定版本的信息,请查看版本列表

简单使用示例

本crate假设您已了解如何使用Iced。如果您还没有,请在此查看

// Import iced modules.
use iced::widget::{column, container, text};
use iced::{Alignment, Element, Length, Sandbox, Settings};
// Import iced_audio modules.
use iced_audio::{
    tick_marks, FloatRange, FreqRange, HSlider, IntRange, Knob, LogDBRange,
    Normal, NormalParam, VSlider, XYPad,
};

// The message when a parameter widget is moved by the user
#[derive(Debug, Clone)]
pub enum Message {
    HSliderInt(Normal),
    VSliderDB(Normal),
    KnobFreq(Normal),
    XYPadFloat(Normal, Normal),
}

pub fn main() {
    App::run(Settings::default()).unwrap();
}

pub struct App {
    // The ranges handle converting the input/output of a parameter to and from
    // a usable value.
    //
    // There are 4 built-in options available for a range:
    //
    // * FloatRange - a linear range of f32 values
    // * IntRange - a discrete range of i32 values. This will cause the widget
    // to "step" when moved.
    // * LogDBRange - a logarithmic range of decibel values. Values around 0 dB
    // will increment slower than values farther away from 0 dB.
    // * FreqRange - a logarithmic range of frequency values. Each octave in
    // the 10 octave spectrum (from 20 Hz to 20480 Hz) is spaced evenly.
    //
    float_range: FloatRange,
    int_range: IntRange,
    db_range: LogDBRange,
    freq_range: FreqRange,

    // The states of the widgets that will control the parameters.
    h_slider_param: NormalParam,
    v_slider_param: NormalParam,
    knob_param: NormalParam,
    xy_pad_x_param: NormalParam,
    xy_pad_y_param: NormalParam,

    // A group of tick marks with their size and position.
    center_tick_mark: tick_marks::Group,

    output_text: String,
}

impl Sandbox for App {
    type Message = Message;

    fn new() -> App {
        // Initalize each range:
        let float_range = FloatRange::default_bipolar();
        let int_range = IntRange::new(0, 10);
        let db_range = LogDBRange::new(-12.0, 12.0, 0.5.into());
        let freq_range = FreqRange::default();

        App {
            // Add the ranges.
            float_range,
            int_range,
            db_range,
            freq_range,

            // Initialize the state of the widgets with a normalized parameter
            // that has a value and a default value.
            h_slider_param: int_range.normal_param(5, 5),
            v_slider_param: db_range.default_normal_param(),
            knob_param: freq_range.normal_param(1000.0, 1000.0),
            xy_pad_x_param: float_range.default_normal_param(),
            xy_pad_y_param: float_range.default_normal_param(),

            // Add a tick mark at the center position with the tier 2 size
            center_tick_mark: tick_marks::Group::center(tick_marks::Tier::Two),

            output_text: "Move a widget!".into(),
        }
    }

    fn title(&self) -> String {
        format!("Simple Example - Iced Audio")
    }

    fn update(&mut self, event: Message) {
        match event {
            // Retrieve the value by mapping the normalized value of the parameter
            // to the corresponding range.
            //
            // Now do something useful with that value!
            Message::HSliderInt(normal) => {
                // Integer parameters must be snapped to make the widget "step" when moved.
                self.h_slider_param.update(self.int_range.snapped(normal));

                let value = self.int_range.unmap_to_value(normal);
                self.output_text = format!("HSliderInt: {}", value);
            }
            Message::VSliderDB(normal) => {
                self.v_slider_param.update(normal);

                let value = self.db_range.unmap_to_value(normal);
                self.output_text = format!("VSliderDB: {:.3}", value);
            }
            Message::KnobFreq(normal) => {
                self.knob_param.update(normal);

                let value = self.freq_range.unmap_to_value(normal);
                self.output_text = format!("KnobFreq: {:.2}", value);
            }
            Message::XYPadFloat(normal_x, normal_y) => {
                self.xy_pad_x_param.update(normal_x);
                self.xy_pad_y_param.update(normal_y);

                let value_x = self.float_range.unmap_to_value(normal_x);
                let value_y = self.float_range.unmap_to_value(normal_y);
                self.output_text =
                    format!("XYPadFloat: x: {:.2}, y: {:.2}", value_x, value_y);
            }
        }
    }

    fn view(&self) -> Element<Message> {
        // Create each parameter widget, passing in the current state of the widget.
        let h_slider_widget =
            HSlider::new(self.h_slider_param, Message::HSliderInt)
                // Add the tick mark group to this widget.
                .tick_marks(&self.center_tick_mark);

        let v_slider_widget =
            VSlider::new(self.v_slider_param, Message::VSliderDB)
                .tick_marks(&self.center_tick_mark);

        let knob_widget =
            Knob::new(self.knob_param, Message::KnobFreq, || None, || None);

        let xy_pad_widget = XYPad::new(
            self.xy_pad_x_param,
            self.xy_pad_y_param,
            Message::XYPadFloat,
        );

        // Push the widgets into the iced DOM
        let content = column![
            h_slider_widget,
            v_slider_widget,
            knob_widget,
            xy_pad_widget,
            container(text(&self.output_text)).width(Length::Fill),
        ]
        .max_width(300)
        .spacing(20)
        .padding(20)
        .align_items(Alignment::Center);

        container(content)
            .max_height(500)
            .width(Length::Fill)
            .height(Length::Fill)
            .center_x()
            .center_y()
            .into()
    }
}

VST / LV2 / AU 插件

如果您希望使用iced_audio为音频插件,请查看我的其他仓库。

请注意,这些是实验性的,目前缺少许多功能。

贡献/反馈

非常感谢您的贡献!如果您想贡献,请阅读官方Iced 贡献指南以获取更多详细信息。

也欢迎反馈!您可以打开一个问题,或者如果您想交谈,来我们的Discord服务器聊天。此外,您可以在Rust社区Discord#gui-and-ui频道中找到我(以及一群很棒的伙伴)。我在那里的ID是BillyDM#3892

依赖项

~11–43MB
~750K SLoC