{"id":13603580,"url":"https://github.com/RustAudio/dasp","last_synced_at":"2025-04-11T22:31:36.262Z","repository":{"id":27269953,"uuid":"30742812","full_name":"RustAudio/dasp","owner":"RustAudio","description":"The fundamentals for Digital Audio Signal Processing. Formerly `sample`.","archived":false,"fork":false,"pushed_at":"2024-03-26T10:42:00.000Z","size":1789,"stargazers_count":883,"open_issues_count":56,"forks_count":64,"subscribers_count":22,"default_branch":"master","last_synced_at":"2024-10-29T21:32:11.543Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RustAudio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-02-13T06:01:52.000Z","updated_at":"2024-10-26T23:53:11.000Z","dependencies_parsed_at":"2024-03-24T00:31:30.234Z","dependency_job_id":"7078e29a-6355-4096-9e2f-1da2d819af93","html_url":"https://github.com/RustAudio/dasp","commit_stats":{"total_commits":260,"total_committers":20,"mean_commits":13.0,"dds":0.2692307692307693,"last_synced_commit":"6b15274b471835e586089e54228e54601f92d391"},"previous_names":["rustaudio/sample"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RustAudio%2Fdasp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RustAudio%2Fdasp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RustAudio%2Fdasp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RustAudio%2Fdasp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RustAudio","download_url":"https://codeload.github.com/RustAudio/dasp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248489662,"owners_count":21112616,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T19:00:25.855Z","updated_at":"2025-04-11T22:31:35.447Z","avatar_url":"https://github.com/RustAudio.png","language":"Rust","readme":"# dasp [![Actions Status][dasp-actions-svg]][dasp-actions] [![docs.rs][dasp-docs-rs-svg]][dasp-docs-rs]\n\n**Digital Audio Signal Processing in Rust.**\n\n*Formerly the [`sample` crate](https://crates.io/crates/sample).*\n\nA suite of crates providing the fundamentals for working with PCM (pulse-code\nmodulation) DSP (digital signal processing). In other words, `dasp` provides a\nsuite of low-level, high-performance tools including types, traits and functions\nfor working with digital audio signals.\n\nThe `dasp` libraries require **no dynamic allocations**\u003csup\u003e1\u003c/sup\u003e and have\n**no dependencies**. The goal is to design a library akin to the **std, but for\naudio DSP**; keeping the focus on portable and fast fundamentals.\n\n\u003csup\u003e1: Besides the feature-gated `SignalBus` trait, which is occasionally\nuseful when converting a `Signal` tree into a directed acyclic graph.\u003c/sup\u003e\n\nFind the [API documentation here][dasp-docs-rs].\n\n\n## Crates\n\n**dasp** is a modular collection of crates, allowing users to select the precise\nset of tools required for their project. The following crates are included\nwithin this repository:\n\n| **Library** | **Links** | **Description** |\n| --- | --- | --- |\n| [**`dasp`**][dasp] | [![Crates.io][dasp-crates-io-svg]][dasp-crates-io] [![docs.rs][dasp-docs-rs-svg]][dasp-docs-rs] | Top-level API with features for all crates. |\n| [**`dasp_sample`**][dasp_sample] | [![Crates.io][dasp_sample-crates-io-svg]][dasp_sample-crates-io] [![docs.rs][dasp_sample-docs-rs-svg]][dasp_sample-docs-rs] | Sample trait, types, conversions and operations. |\n| [**`dasp_frame`**][dasp_frame] | [![Crates.io][dasp_frame-crates-io-svg]][dasp_frame-crates-io] [![docs.rs][dasp_frame-docs-rs-svg]][dasp_frame-docs-rs] | Frame trait, types, conversions and operations. |\n| [**`dasp_slice`**][dasp_slice] | [![Crates.io][dasp_slice-crates-io-svg]][dasp_slice-crates-io] [![docs.rs][dasp_slice-docs-rs-svg]][dasp_slice-docs-rs] | Conversions and ops for slices of samples/frames. |\n| [**`dasp_ring_buffer`**][dasp_ring_buffer] | [![Crates.io][dasp_ring_buffer-crates-io-svg]][dasp_ring_buffer-crates-io] [![docs.rs][dasp_ring_buffer-docs-rs-svg]][dasp_ring_buffer-docs-rs] | Simple fixed and bounded ring buffers. |\n| [**`dasp_peak`**][dasp_peak] | [![Crates.io][dasp_peak-crates-io-svg]][dasp_peak-crates-io] [![docs.rs][dasp_peak-docs-rs-svg]][dasp_peak-docs-rs] | Peak detection with half/full pos/neg wave rectifiers. |\n| [**`dasp_rms`**][dasp_rms] | [![Crates.io][dasp_rms-crates-io-svg]][dasp_rms-crates-io] [![docs.rs][dasp_rms-docs-rs-svg]][dasp_rms-docs-rs] | RMS detection with configurable window. |\n| [**`dasp_envelope`**][dasp_envelope] | [![Crates.io][dasp_envelope-crates-io-svg]][dasp_envelope-crates-io] [![docs.rs][dasp_envelope-docs-rs-svg]][dasp_envelope-docs-rs] | Envelope detection with peak and RMS impls. |\n| [**`dasp_interpolate`**][dasp_interpolate] | [![Crates.io][dasp_interpolate-crates-io-svg]][dasp_interpolate-crates-io] [![docs.rs][dasp_interpolate-docs-rs-svg]][dasp_interpolate-docs-rs] | Inter-frame rate interpolation (linear, sinc, etc). |\n| [**`dasp_window`**][dasp_window] | [![Crates.io][dasp_window-crates-io-svg]][dasp_window-crates-io] [![docs.rs][dasp_window-docs-rs-svg]][dasp_window-docs-rs] | Windowing function abstraction (hann, rectangle). |\n| [**`dasp_signal`**][dasp_signal] | [![Crates.io][dasp_signal-crates-io-svg]][dasp_signal-crates-io] [![docs.rs][dasp_signal-docs-rs-svg]][dasp_signal-docs-rs] | Iterator-like API for streams of audio frames. |\n| [**`dasp_graph`**][dasp_graph] | [![Crates.io][dasp_graph-crates-io-svg]][dasp_graph-crates-io] [![docs.rs][dasp_graph-docs-rs-svg]][dasp_graph-docs-rs] | For working with modular, dynamic audio graphs. |\n\n[![deps-graph][deps-graph]][deps-graph]\n\n*Red dotted lines indicate optional dependencies, while black lines indicate\nrequired dependencies.*\n\n\n## Features\n\nUse the **Sample** trait to convert between and remain generic over any\nbit-depth in an optimal, performance-sensitive manner. Implementations are\nprovided for all signed integer, unsigned integer and floating point primitive\ntypes along with some custom types including 11, 20, 24 and 48-bit signed and\nunsigned unpacked integers. For example:\n\n```rust\nassert_eq!((-1.0).to_sample::\u003cu8\u003e(), 0);\nassert_eq!(0.0.to_sample::\u003cu8\u003e(), 128);\nassert_eq!(0i32.to_sample::\u003cu32\u003e(), 2_147_483_648);\nassert_eq!(I24::new(0).unwrap(), Sample::from_sample(0.0));\nassert_eq!(0.0, Sample::EQUILIBRIUM);\n```\n\nUse the **Frame** trait to remain generic over the number of channels at a\ndiscrete moment in time. Implementations are provided for all fixed-size arrays\nup to 32 elements in length.\n\n```rust\nlet foo = [0.1, 0.2, -0.1, -0.2];\nlet bar = foo.scale_amp(2.0);\nassert_eq!(bar, [0.2, 0.4, -0.2, -0.4]);\n\nassert_eq!(Mono::\u003cf32\u003e::EQUILIBRIUM, [0.0]);\nassert_eq!(Stereo::\u003cf32\u003e::EQUILIBRIUM, [0.0, 0.0]);\nassert_eq!(\u003c[f32; 3]\u003e::EQUILIBRIUM, [0.0, 0.0, 0.0]);\n\nlet foo = [0i16, 0];\nlet bar: [u8; 2] = foo.map(Sample::to_sample);\nassert_eq!(bar, [128u8, 128]);\n```\n\nUse the **Signal** trait (enabled by the \"signal\" feature) for working with\ninfinite-iterator-like types that yield `Frame`s. **Signal** provides methods\nfor adding, scaling, offsetting, multiplying, clipping, generating, monitoring\nand buffering streams of `Frame`s.  Working with **Signal**s allows for easy,\nreadable creation of rich and complex DSP graphs with a simple and familiar API.\n\n```rust\n// Clip to an amplitude of 0.9.\nlet frames = [[1.2, 0.8], [-0.7, -1.4]];\nlet clipped: Vec\u003c_\u003e = signal::from_iter(frames.iter().cloned()).clip_amp(0.9).take(2).collect();\nassert_eq!(clipped, vec![[0.9, 0.8], [-0.7, -0.9]]);\n\n// Add `a` with `b` and yield the result.\nlet a = [0.2, -0.6, 0.5];\nlet b = [0.2, 0.1, -0.8];\nlet a_signal = signal::from_iter(a.iter().cloned());\nlet b_signal = signal::from_iter(b.iter().cloned());\nlet added: Vec\u003cf32\u003e = a_signal.add_amp(b_signal).take(3).collect();\nassert_eq!(added, vec![0.4, -0.5, -0.3]);\n\n// Scale the playback rate by `0.5`.\nlet foo = [0.0, 1.0, 0.0, -1.0];\nlet mut source = signal::from_iter(foo.iter().cloned());\nlet a = source.next();\nlet b = source.next();\nlet interp = Linear::new(a, b);\nlet frames: Vec\u003c_\u003e = source.scale_hz(interp, 0.5).take(8).collect();\nassert_eq!(\u0026frames[..], \u0026[0.0, 0.5, 1.0, 0.5, 0.0, -0.5, -1.0, -0.5][..]);\n\n// Convert a signal to its RMS.\nlet signal = signal::rate(44_100.0).const_hz(440.0).sine();;\nlet ring_buffer = ring_buffer::Fixed::from([0.0; WINDOW_SIZE]);\nlet mut rms_signal = signal.rms(ring_buffer);\n```\n\nThe **signal** module also provides a series of **Signal** source types,\nincluding:\n\n- `FromIterator`\n- `FromInterleavedSamplesIterator`\n- `Equilibrium` (silent signal)\n- `Phase`\n- `Sine`\n- `Saw`\n- `Square`\n- `Noise`\n- `NoiseSimplex`\n- `Gen` (generate frames from a Fn() -\u003e F)\n- `GenMut` (generate frames from a FnMut() -\u003e F)\n\nUse the **slice** module functions (enabled via the \"slice\" feature) for\nprocessing chunks of `Frame`s.  Conversion functions are provided for safely\nconverting between slices of interleaved `Sample`s and slices of `Frame`s\nwithout requiring any allocation.  For example:\n\n```rust\nlet frames = \u0026[[0.0, 0.5], [0.0, -0.5]][..];\nlet samples = slice::to_sample_slice(frames);\nassert_eq!(samples, \u0026[0.0, 0.5, 0.0, -0.5][..]);\n\nlet samples = \u0026[0.0, 0.5, 0.0, -0.5][..];\nlet frames = slice::to_frame_slice(samples);\nassert_eq!(frames, Some(\u0026[[0.0, 0.5], [0.0, -0.5]][..]));\n\nlet samples = \u0026[0.0, 0.5, 0.0][..];\nlet frames = slice::to_frame_slice(samples);\nassert_eq!(frames, None::\u003c\u0026[[f32; 2]]\u003e);\n```\n\nThe **signal::interpolate** module provides a **Converter** type, for converting\nand interpolating the rate of **Signal**s. This can be useful for both sample\nrate conversion and playback rate multiplication. **Converter**s can use a range\nof interpolation methods, with Floor, Linear, and Sinc interpolation provided in\nthe library.\n\nThe **ring_buffer** module provides generic **Fixed** and **Bounded** ring\nbuffer types, both of which may be used with owned, borrowed, stack and\nallocated buffers.\n\nThe **peak** module can be used for monitoring the peak of a signal. Provided\npeak rectifiers include `full_wave`, `positive_half_wave` and\n`negative_half_wave`.\n\nThe **rms** module provides a flexible **Rms** type that can be used for RMS\n(root mean square) detection. Any **Fixed** ring buffer can be used as the\nwindow for the RMS detection.\n\nThe **envelope** module provides a **Detector** type (also known as a\n*Follower*) that allows for detecting the envelope of a signal. **Detector** is\ngeneric over the type of **Detect**ion - **Rms** and **Peak** detection are\nprovided. For example:\n\n```rust\nlet signal = signal::rate(4.0).const_hz(1.0).sine();\nlet attack = 1.0;\nlet release = 1.0;\nlet detector = envelope::Detector::peak(attack, release);\nlet mut envelope = signal.detect_envelope(detector);\nassert_eq!(\n    envelope.take(4).collect::\u003cVec\u003c_\u003e\u003e(),\n    vec![0.0, 0.6321205496788025, 0.23254416035257117, 0.7176687675647109]\n);\n```\n\n\n## `no_std`\n\nAll crates may be compiled with and without the std library. The std library is\nenabled by default, however it may be disabled via `--no-default-features`.\n\nTo enable all of a crate's features *without* the std library, you may use\n`--no-default-features --features \"all-no-std\"`.\n\nPlease note that some of the crates require the `core_intrinsics` feature in\norder to be able to perform operations like `sin`, `cos` and `powf32` in a\n`no_std` context. This means that these crates require the nightly toolchain in\norder to build in a `no_std` context.\n\n\n## Contributing\n\nIf **dasp** is missing types, conversions or other fundamental functionality\nthat you wish it had, feel free to open an issue or pull request! The more\nhands on deck, the merrier :)\n\n\n## License\n\nLicensed under either of\n\n * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)\n * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\n**Contributions**\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall be\ndual licensed as above, without any additional terms or conditions.\n\n\n[dasp-actions]: https://github.com/rustaudio/dasp/actions\n[dasp-actions-svg]: https://github.com/rustaudio/dasp/workflows/dasp/badge.svg\n[deps-graph]: ./assets/deps-graph.png\n[dasp]: ./dasp\n[dasp-crates-io]: https://crates.io/crates/dasp\n[dasp-crates-io-svg]: https://img.shields.io/crates/v/dasp.svg\n[dasp-docs-rs]: https://docs.rs/dasp/\n[dasp-docs-rs-svg]: https://docs.rs/dasp/badge.svg\n[dasp_envelope]: ./dasp_envelope\n[dasp_envelope-crates-io]: https://crates.io/crates/dasp_envelope\n[dasp_envelope-crates-io-svg]: https://img.shields.io/crates/v/dasp_envelope.svg\n[dasp_envelope-docs-rs]: https://docs.rs/dasp_envelope/\n[dasp_envelope-docs-rs-svg]: https://docs.rs/dasp_envelope/badge.svg\n[dasp_frame]: ./dasp_frame\n[dasp_frame-crates-io]: https://crates.io/crates/dasp_frame\n[dasp_frame-crates-io-svg]: https://img.shields.io/crates/v/dasp_frame.svg\n[dasp_frame-docs-rs]: https://docs.rs/dasp_frame/\n[dasp_frame-docs-rs-svg]: https://docs.rs/dasp_frame/badge.svg\n[dasp_graph]: ./dasp_graph\n[dasp_graph-crates-io]: https://crates.io/crates/dasp_graph\n[dasp_graph-crates-io-svg]: https://img.shields.io/crates/v/dasp_graph.svg\n[dasp_graph-docs-rs]: https://docs.rs/dasp_graph/\n[dasp_graph-docs-rs-svg]: https://docs.rs/dasp_graph/badge.svg\n[dasp_interpolate]: ./dasp_interpolate\n[dasp_interpolate-crates-io]: https://crates.io/crates/dasp_interpolate\n[dasp_interpolate-crates-io-svg]: https://img.shields.io/crates/v/dasp_interpolate.svg\n[dasp_interpolate-docs-rs]: https://docs.rs/dasp_interpolate/\n[dasp_interpolate-docs-rs-svg]: https://docs.rs/dasp_interpolate/badge.svg\n[dasp_peak]: ./dasp_peak\n[dasp_peak-crates-io]: https://crates.io/crates/dasp_peak\n[dasp_peak-crates-io-svg]: https://img.shields.io/crates/v/dasp_peak.svg\n[dasp_peak-docs-rs]: https://docs.rs/dasp_peak/\n[dasp_peak-docs-rs-svg]: https://docs.rs/dasp_peak/badge.svg\n[dasp_ring_buffer]: ./dasp_ring_buffer\n[dasp_ring_buffer-crates-io]: https://crates.io/crates/dasp_ring_buffer\n[dasp_ring_buffer-crates-io-svg]: https://img.shields.io/crates/v/dasp_ring_buffer.svg\n[dasp_ring_buffer-docs-rs]: https://docs.rs/dasp_ring_buffer/\n[dasp_ring_buffer-docs-rs-svg]: https://docs.rs/dasp_ring_buffer/badge.svg\n[dasp_rms]: ./dasp_rms\n[dasp_rms-crates-io]: https://crates.io/crates/dasp_rms\n[dasp_rms-crates-io-svg]: https://img.shields.io/crates/v/dasp_rms.svg\n[dasp_rms-docs-rs]: https://docs.rs/dasp_rms/\n[dasp_rms-docs-rs-svg]: https://docs.rs/dasp_rms/badge.svg\n[dasp_sample]: ./dasp_sample\n[dasp_sample-crates-io]: https://crates.io/crates/dasp_sample\n[dasp_sample-crates-io-svg]: https://img.shields.io/crates/v/dasp_sample.svg\n[dasp_sample-docs-rs]: https://docs.rs/dasp_sample/\n[dasp_sample-docs-rs-svg]: https://docs.rs/dasp_sample/badge.svg\n[dasp_signal]: ./dasp_signal\n[dasp_signal-crates-io]: https://crates.io/crates/dasp_signal\n[dasp_signal-crates-io-svg]: https://img.shields.io/crates/v/dasp_signal.svg\n[dasp_signal-docs-rs]: https://docs.rs/dasp_signal/\n[dasp_signal-docs-rs-svg]: https://docs.rs/dasp_signal/badge.svg\n[dasp_slice]: ./dasp_slice\n[dasp_slice-crates-io]: https://crates.io/crates/dasp_slice\n[dasp_slice-crates-io-svg]: https://img.shields.io/crates/v/dasp_slice.svg\n[dasp_slice-docs-rs]: https://docs.rs/dasp_slice/\n[dasp_slice-docs-rs-svg]: https://docs.rs/dasp_slice/badge.svg\n[dasp_window]: ./dasp_window\n[dasp_window-crates-io]: https://crates.io/crates/dasp_window\n[dasp_window-crates-io-svg]: https://img.shields.io/crates/v/dasp_window.svg\n[dasp_window-docs-rs]: https://docs.rs/dasp_window/\n[dasp_window-docs-rs-svg]: https://docs.rs/dasp_window/badge.svg\n","funding_links":[],"categories":["Rust"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRustAudio%2Fdasp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRustAudio%2Fdasp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRustAudio%2Fdasp/lists"}