pax_global_header00006660000000000000000000000064145435235500014520gustar00rootroot0000000000000052 comment=e9829c9bccf5ed73768135c0ddd506f5a6690f9e chadmed-bankstown-79127be/000077500000000000000000000000001454352355000154535ustar00rootroot00000000000000chadmed-bankstown-79127be/.gitignore000066400000000000000000000000231454352355000174360ustar00rootroot00000000000000/target *.kate-swp chadmed-bankstown-79127be/Cargo.lock000066400000000000000000000100511454352355000173550ustar00rootroot00000000000000# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "bankstown-lv2" version = "1.1.0" dependencies = [ "biquad", "lv2", ] [[package]] name = "biquad" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "820524f5e3e3add696ddf69f79575772e152c0e78e9f0370b56990a7e808ec3e" dependencies = [ "libm", ] [[package]] name = "libm" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "lv2" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81300c8058a7747013c8f3e27e76eeceb8226621283d30d787b970019d8404f6" dependencies = [ "lv2-atom", "lv2-core", "lv2-midi", "lv2-units", "lv2-urid", "urid", ] [[package]] name = "lv2-atom" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "951b4e7b10349d32b7b7a26c15bd0f9cf42790b59531093d474f6964f5cba971" dependencies = [ "lv2-core", "lv2-sys", "lv2-units", "urid", ] [[package]] name = "lv2-core" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d50100435f793b25e9fcfe89c227dc1b1ca93bbfae0f3710149263fe4ba049de" dependencies = [ "lv2-core-derive", "lv2-sys", "urid", ] [[package]] name = "lv2-core-derive" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bf98f786ecb49030330834aaa458f84bbaf545d7084cf3dcb2fab2f03a1838b" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "lv2-midi" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad23e6bcd0036b1859992b92bbf1855f99ed648886ed9ad9a32fc4ecf2a20f74" dependencies = [ "lv2-atom", "lv2-sys", "urid", "wmidi", ] [[package]] name = "lv2-sys" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dd0f9e7de3649dcec348de51cbf611ab88688b97c0ce038f8c07b996b2a8e30" [[package]] name = "lv2-units" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02b9470e6f71a96c49ce27ff15838b27f4f07300dec810313423b70ec7adaa39" dependencies = [ "lv2-sys", "urid", ] [[package]] name = "lv2-urid" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c0803444d1e66fbdbc345ef8243470979f8bab570cdaf0cada4586fc1624e68" dependencies = [ "lv2-core", "lv2-sys", "urid", ] [[package]] name = "proc-macro2" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "urid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6828b5d766e783093935fb2f23f26ffb28b7cb9313921cec67db8ca09f38a6a4" dependencies = [ "urid-derive", ] [[package]] name = "urid-derive" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819eee2ef008e55b0a415ed356db7772d0ad94ae499f0043015111fc34703644" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "wmidi" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca299959bb6d529c2bee3feb517899959da3052c4a29eea0a8ff568b825eb6cf" chadmed-bankstown-79127be/Cargo.toml000066400000000000000000000010461454352355000174040ustar00rootroot00000000000000[package] name = "bankstown-lv2" authors = ["James Calligeros"] description = "A barebones, fast LV2 bass enhancement plugin" license = "MIT" repository = "https://github.com/chadmed/bankstown" version = "1.1.0" edition = "2021" keywords = ["lv2", "bass", "audio", "plugin"] categories = ["multimedia::audio"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [profile.release] opt-level = 3 lto = "thin" [dependencies] biquad = "0.4.2" lv2 = "0.6.0" [lib] crate-type = ["cdylib"] name = "bankstown" chadmed-bankstown-79127be/LICENSE000066400000000000000000000021021454352355000164530ustar00rootroot00000000000000Copyright 2023 James Calligeros Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. chadmed-bankstown-79127be/Makefile000066400000000000000000000010401454352355000171060ustar00rootroot00000000000000# SPDX-Licence-Identifier: MIT # Copyright (C) 2023 James Calligeros LIBDIR ?= /usr/lib64 default: cargo build --release install: install -dDm0755 $(DESTDIR)/$(LIBDIR)/lv2/bankstown.lv2/ install -pm0755 target/release/libbankstown.so $(DESTDIR)/$(LIBDIR)/lv2/bankstown.lv2/bankstown.so install -pm0644 bankstown.ttl $(DESTDIR)/$(LIBDIR)/lv2/bankstown.lv2/bankstown.ttl install -pm0644 manifest.ttl $(DESTDIR)/$(LIBDIR)/lv2/bankstown.lv2/manifest.ttl uninstall: rm -rf $(DESTDIR)/$(LIBDIR)/lv2/bankstown.lv2/ chadmed-bankstown-79127be/README.md000066400000000000000000000033141454352355000167330ustar00rootroot00000000000000# Bankstown: a barebones bass enhancer Halfway-decent three-stage psychoacoustic bass approximation. ## Theory Speakers found in small devices have trouble reproducing bass and sub-bass faithfully. This is because they are power and space constrained, and cannot move the amount of air required to reproduce such low frequencies at audible volumes. Designers of modern devices get around this problem by taking advantage of the fact that humans are very easy to fool. We generate harmonics of bass and sub-bass frequencies to trick the human brain into thinking there is more bass than there really is. ### The long version Saturation of a discrete-time signal clamps the maximum and minimum value of any given sample. Consider a pure sine wave with a peak to peak amplitude of 3. We sample this function and are left with a series of discrete samples. We can apply a transfer function to this series which introduces nonlinearity about the peaks such that values above 2.6 are clamped to 2.0. We have "crushed" the peaks of our sine wave into something approximating a square wave. Recall that any periodic function that is not a pure trigonometric function can be described as a Fourier series of pure trigonimetric functions. That is, any waveform can be broken down into a fundamental sine wave and its harmonics. Thus, the nonlinearities introduced by our saturation function create harmonics of our input signal. The brain hears these harmonics and is able to infer the fundamental, thus tricking you into thinking there is "fuller" bass than there actually is. This trick is common in virtually everything from Bluetooth earbuds to expensive active "compact" HiFi speakers, and is the reason they can sound as good as they do. chadmed-bankstown-79127be/bankstown.ttl000066400000000000000000000077611454352355000202210ustar00rootroot00000000000000@prefix doap: . @prefix lv2: . @prefix rdf: . @prefix rdfs: . @prefix units: . @prefix epp: . a lv2:Plugin , lv2:FilterPlugin ; lv2:binary ; doap:name "Bankstown" ; lv2:requiredFeature lv2:inPlaceBroken ; lv2:optionalFeature lv2:hardRTCapable ; lv2:port [ a lv2:InputPort , lv2:AudioPort ; lv2:index 0 ; lv2:symbol "in_l" ; lv2:name "In Left" ] , [ a lv2:InputPort , lv2:AudioPort ; lv2:index 1 ; lv2:symbol "in_r" ; lv2:name "In Right" ] , [ a lv2:OutputPort , lv2:AudioPort ; lv2:index 2 ; lv2:symbol "out_l" ; lv2:name "Out Left" ] , [ a lv2:OutputPort , lv2:AudioPort ; lv2:index 3 ; lv2:symbol "out_r" ; lv2:name "Out Right" ] , [ a lv2:InputPort , lv2:ControlPort ; lv2:index 4 ; lv2:symbol "bypass" ; lv2:name "Bypass" ; lv2:portProperty lv2:toggled ; lv2:default 0.0 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ] , [ a lv2:InputPort , lv2:ControlPort ; lv2:index 5 ; lv2:symbol "amt" ; lv2:name "Amount" ; lv2:default 1.0 ; lv2:minimum 0.0 ; lv2:maximum 15.0 ; ] , [ a lv2:InputPort , lv2:ControlPort ; lv2:index 6 ; lv2:symbol "floor" ; lv2:name "Floor Frequency" ; lv2:portProperty epp:logarithmic ; lv2:portProperty epp:hasStrictBounds ; lv2:default 20 ; lv2:minimum 10 ; lv2:maximum 250 ; units:unit units:hz ; lv2:scalePoint [ rdfs:label "20" ; rdf:value 20 ] , [ rdfs:label "100" ; rdf:value 100 ] , [ rdfs:label "200" ; rdf:value 200 ] ] , [ a lv2:InputPort , lv2:ControlPort ; lv2:index 7 ; lv2:symbol "ceil" ; lv2:name "Ceiling Frequency" ; lv2:portProperty epp:logarithmic ; lv2:portProperty epp:hasStrictBounds ; lv2:default 200 ; lv2:minimum 10 ; lv2:maximum 250 ; units:unit units:hz ; lv2:scalePoint [ rdfs:label "20" ; rdf:value 20 ] , [ rdfs:label "100" ; rdf:value 100 ] , [ rdfs:label "200" ; rdf:value 200 ] ] , [ a lv2:InputPort , lv2:ControlPort ; lv2:index 8 ; lv2:symbol "final_hp" ; lv2:name "Output HPF" ; lv2:portProperty epp:logarithmic ; lv2:portProperty epp:hasStrictBounds ; lv2:default 200 ; lv2:minimum 10 ; lv2:maximum 250 ; units:unit units:hz ; lv2:scalePoint [ rdfs:label "20" ; rdf:value 20 ] , [ rdfs:label "100" ; rdf:value 100 ] , [ rdfs:label "200" ; rdf:value 200 ] ] , [ a lv2:InputPort , lv2:ControlPort ; lv2:index 9 ; lv2:symbol "sat_second" ; lv2:name "Second Harmonic" ; lv2:default 1.0 ; lv2:minimum 0.0 ; lv2:maximum 15.0 ; ] , [ a lv2:InputPort , lv2:ControlPort ; lv2:index 10 ; lv2:symbol "sat_third" ; lv2:name "Third Harmonic" ; lv2:default 1.0 ; lv2:minimum 0.0 ; lv2:maximum 15.0 ; ] , [ a lv2:InputPort , lv2:ControlPort ; lv2:index 11 ; lv2:symbol "blend" ; lv2:name "Harmonic Ratio" ; lv2:default 0.5 ; lv2:minimum 0.0 ; lv2:maximum 1.0 ; ] . chadmed-bankstown-79127be/manifest.ttl000066400000000000000000000003361454352355000200100ustar00rootroot00000000000000@prefix lv2: . @prefix rdfs: . a lv2:Plugin ; lv2:binary ; rdfs:seeAlso . chadmed-bankstown-79127be/src/000077500000000000000000000000001454352355000162425ustar00rootroot00000000000000chadmed-bankstown-79127be/src/lib.rs000066400000000000000000000173661454352355000173730ustar00rootroot00000000000000// SPDX-License-Identifier: MIT /* * Bass and sub-bass frequencies are poorly reproduced by microspeakers. Luckily, * the human brain is malleable and will reconstruct these frequencies from their * harmonics as if they were really there. We can use this phenomenon to get better * bass performance out of crappy speakers. * * Copyright (C) 2023 James Calligeros */ use std::f32::consts::E; use std::f32::consts::PI; use lv2::prelude::*; use biquad::*; /* * Input and output ports used by the plugin * * * Ports: * in_l: left channel input * in_r: right channel input * out_l: left channel output * out_r: right channel output * floor: floor frequency for harmonics * ceil: ceiling frequency for harmonics * amt: volume of harmonics to mix in to the output * bypass: bypass all filtering */ #[derive(PortCollection)] struct Ports { in_l: InputPort